소스 검색

feat: add wallet balance metrics and alerts; update price feed metrics

Daniel Chew 8 달 전
부모
커밋
e55be6db2e

+ 18 - 0
apps/price_pusher/alerts.yml

@@ -45,3 +45,21 @@ groups:
         annotations:
           summary: "High update duration"
           description: "Price updates are taking longer than 5 seconds on average"
+
+      - alert: WalletBalanceLow
+        expr: pyth_wallet_balance < 0.1
+        for: 5m
+        labels:
+          severity: warning
+        annotations:
+          summary: "Wallet balance is getting low"
+          description: "Wallet {{ $labels.wallet_address }} on network {{ $labels.network }} has balance below 0.1 native tokens"
+
+      - alert: WalletBalanceCritical
+        expr: pyth_wallet_balance < 0.01
+        for: 2m
+        labels:
+          severity: critical
+        annotations:
+          summary: "Wallet balance critically low"
+          description: "Wallet {{ $labels.wallet_address }} on network {{ $labels.network }} has balance below 0.01 native tokens. Transactions may fail soon!"

+ 446 - 92
apps/price_pusher/grafana-dashboard.json

@@ -20,7 +20,6 @@
   "graphTooltip": 0,
   "id": 1,
   "links": [],
-  "liveNow": false,
   "panels": [
     {
       "datasource": {
@@ -30,37 +29,7 @@
       "fieldConfig": {
         "defaults": {
           "color": {
-            "mode": "palette-classic"
-          },
-          "custom": {
-            "axisCenteredZero": false,
-            "axisColorMode": "text",
-            "axisLabel": "",
-            "axisPlacement": "auto",
-            "barAlignment": 0,
-            "drawStyle": "line",
-            "fillOpacity": 0,
-            "gradientMode": "none",
-            "hideFrom": {
-              "legend": false,
-              "tooltip": false,
-              "viz": false
-            },
-            "lineInterpolation": "linear",
-            "lineWidth": 1,
-            "pointSize": 5,
-            "scaleDistribution": {
-              "type": "linear"
-            },
-            "showPoints": "auto",
-            "spanNulls": false,
-            "stacking": {
-              "group": "A",
-              "mode": "none"
-            },
-            "thresholdsStyle": {
-              "mode": "off"
-            }
+            "mode": "thresholds"
           },
           "mappings": [],
           "thresholds": {
@@ -69,38 +38,103 @@
               {
                 "color": "green",
                 "value": null
-              },
-              {
-                "color": "red",
-                "value": 3600
               }
             ]
           },
-          "unit": "s"
+          "unit": "none"
         },
         "overrides": []
       },
       "gridPos": {
         "h": 8,
-        "w": 12,
+        "w": 6,
         "x": 0,
         "y": 0
       },
-      "id": 1,
+      "id": 9,
       "options": {
-        "legend": {
-          "calcs": [],
-          "displayMode": "list",
-          "placement": "bottom",
-          "showLegend": true
+        "colorMode": "value",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "percentChangeColorMode": "standard",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
         },
-        "tooltip": {
-          "mode": "single",
-          "sort": "none"
+        "showPercentChange": false,
+        "textMode": "value",
+        "wideLayout": true
+      },
+      "pluginVersion": "11.5.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "prometheus"
+          },
+          "editorMode": "code",
+          "expr": "pyth_price_feeds_total",
+          "instant": true,
+          "range": false,
+          "refId": "A"
         }
+      ],
+      "title": "Configured Price Feeds",
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "prometheus"
       },
-      "title": "Time Since Last Update",
-      "type": "timeseries",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 6,
+        "x": 6,
+        "y": 0
+      },
+      "id": 12,
+      "options": {
+        "colorMode": "value",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "percentChangeColorMode": "standard",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "showPercentChange": false,
+        "textMode": "value",
+        "wideLayout": true
+      },
+      "pluginVersion": "11.5.2",
       "targets": [
         {
           "datasource": {
@@ -108,12 +142,14 @@
             "uid": "prometheus"
           },
           "editorMode": "code",
-          "expr": "time() - pyth_price_last_published_time",
-          "legendFormat": "{{alias}}",
-          "range": true,
+          "expr": "count(pyth_price_last_published_time)",
+          "instant": true,
+          "range": false,
           "refId": "A"
         }
-      ]
+      ],
+      "title": "Active Price Feeds",
+      "type": "stat"
     },
     {
       "datasource": {
@@ -155,16 +191,19 @@
         "graphMode": "area",
         "justifyMode": "auto",
         "orientation": "auto",
+        "percentChangeColorMode": "standard",
         "reduceOptions": {
-          "calcs": ["lastNotNull"],
+          "calcs": [
+            "lastNotNull"
+          ],
           "fields": "",
           "values": false
         },
-        "textMode": "auto"
+        "showPercentChange": false,
+        "textMode": "auto",
+        "wideLayout": true
       },
-      "pluginVersion": "10.0.0",
-      "title": "Time Since Last Update (Stat)",
-      "type": "stat",
+      "pluginVersion": "11.5.2",
       "targets": [
         {
           "datasource": {
@@ -173,11 +212,227 @@
           },
           "editorMode": "code",
           "expr": "time() - pyth_price_last_published_time",
+          "instant": true,
           "legendFormat": "{{alias}}",
-          "range": true,
+          "range": false,
           "refId": "A"
         }
-      ]
+      ],
+      "title": "Time Since Last Update (Stat)",
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "prometheus"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "custom": {
+            "align": "auto",
+            "cellOptions": {
+              "type": "auto"
+            },
+            "inspect": false
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          }
+        },
+        "overrides": [
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Time Since Update"
+            },
+            "properties": [
+              {
+                "id": "unit",
+                "value": "s"
+              },
+              {
+                "id": "thresholds",
+                "value": {
+                  "mode": "absolute",
+                  "steps": [
+                    {
+                      "color": "green",
+                      "value": null
+                    },
+                    {
+                      "color": "yellow",
+                      "value": 600
+                    },
+                    {
+                      "color": "red",
+                      "value": 3600
+                    }
+                  ]
+                }
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Total Updates"
+            },
+            "properties": [
+              {
+                "id": "unit",
+                "value": "short"
+              }
+            ]
+          }
+        ]
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 8
+      },
+      "id": 7,
+      "options": {
+        "cellHeight": "sm",
+        "footer": {
+          "countRows": false,
+          "fields": "",
+          "reducer": [
+            "sum"
+          ],
+          "show": false
+        },
+        "showHeader": true,
+        "sortBy": [
+          {
+            "desc": false,
+            "displayName": "Price ID"
+          }
+        ]
+      },
+      "pluginVersion": "11.5.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "prometheus"
+          },
+          "editorMode": "code",
+          "expr": "pyth_price_last_published_time",
+          "format": "table",
+          "instant": true,
+          "legendFormat": "__auto",
+          "range": false,
+          "refId": "A"
+        },
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "prometheus"
+          },
+          "editorMode": "code",
+          "expr": "time() - pyth_price_last_published_time",
+          "format": "table",
+          "instant": true,
+          "legendFormat": "__auto",
+          "range": false,
+          "refId": "B"
+        },
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "prometheus"
+          },
+          "editorMode": "code",
+          "expr": "pyth_price_updates_total",
+          "format": "table",
+          "instant": true,
+          "legendFormat": "__auto",
+          "range": false,
+          "refId": "C"
+        }
+      ],
+      "title": "Price Feeds List",
+      "transformations": [
+        {
+          "id": "joinByField",
+          "options": {
+            "byField": "price_id",
+            "mode": "outer"
+          }
+        },
+        {
+          "id": "organize",
+          "options": {
+            "excludeByName": {
+              "Time": true,
+              "Value #A": true,
+              "__name__": true,
+              "__name__#B": true,
+              "__name__#C": true,
+              "alias 2": true,
+              "alias 3": true,
+              "alias#B": true,
+              "alias#C": true,
+              "app": true,
+              "app#B": true,
+              "app#C": true,
+              "instance": true,
+              "instance#B": true,
+              "instance#C": true,
+              "job": true,
+              "job#B": true,
+              "job#C": true,
+              "price_id": false,
+              "price_id#B": true,
+              "price_id#C": true
+            },
+            "includeByName": {},
+            "indexByName": {
+              "Time 1": 4,
+              "Time 2": 10,
+              "Time 3": 15,
+              "Value #A": 9,
+              "Value #B": 2,
+              "Value #C": 3,
+              "__name__ 1": 5,
+              "__name__ 2": 16,
+              "alias 1": 1,
+              "alias 2": 11,
+              "alias 3": 17,
+              "app 1": 6,
+              "app 2": 12,
+              "app 3": 18,
+              "instance 1": 7,
+              "instance 2": 13,
+              "instance 3": 19,
+              "job 1": 8,
+              "job 2": 14,
+              "job 3": 20,
+              "price_id": 0
+            },
+            "renameByName": {
+              "Value #B": "Time Since Update",
+              "Value #C": "Total Updates",
+              "alias": "Symbol",
+              "alias 1": "Symbol",
+              "price_id": "Price ID"
+            }
+          }
+        }
+      ],
+      "type": "table"
     },
     {
       "datasource": {
@@ -190,11 +445,13 @@
             "mode": "palette-classic"
           },
           "custom": {
+            "axisBorderShow": false,
             "axisCenteredZero": false,
             "axisColorMode": "text",
             "axisLabel": "",
             "axisPlacement": "auto",
             "barAlignment": 0,
+            "barWidthFactor": 0.6,
             "drawStyle": "line",
             "fillOpacity": 0,
             "gradientMode": "none",
@@ -203,6 +460,7 @@
               "tooltip": false,
               "viz": false
             },
+            "insertNulls": false,
             "lineInterpolation": "linear",
             "lineWidth": 1,
             "pointSize": 5,
@@ -219,6 +477,7 @@
               "mode": "off"
             }
           },
+          "decimals": 0,
           "mappings": [],
           "thresholds": {
             "mode": "absolute",
@@ -228,14 +487,15 @@
                 "value": null
               }
             ]
-          }
+          },
+          "unit": "none"
         },
         "overrides": []
       },
       "gridPos": {
         "h": 8,
         "w": 12,
-        "x": 0,
+        "x": 12,
         "y": 8
       },
       "id": 3,
@@ -247,12 +507,12 @@
           "showLegend": true
         },
         "tooltip": {
+          "hideZeros": false,
           "mode": "single",
           "sort": "none"
         }
       },
-      "title": "Price Updates (Last Hour)",
-      "type": "timeseries",
+      "pluginVersion": "11.5.2",
       "targets": [
         {
           "datasource": {
@@ -265,7 +525,83 @@
           "range": true,
           "refId": "A"
         }
-      ]
+      ],
+      "title": "Price Updates (Last Hour)",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "prometheus"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "yellow",
+                "value": 0.1
+              },
+              {
+                "color": "red",
+                "value": 0.01
+              }
+            ]
+          },
+          "unit": "locale"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 16
+      },
+      "id": 10,
+      "options": {
+        "colorMode": "value",
+        "graphMode": "area",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "percentChangeColorMode": "standard",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "showPercentChange": false,
+        "textMode": "auto",
+        "wideLayout": true
+      },
+      "pluginVersion": "11.5.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "prometheus"
+          },
+          "editorMode": "code",
+          "expr": "pyth_wallet_balance",
+          "instant": true,
+          "legendFormat": "{{wallet_address}}",
+          "range": false,
+          "refId": "A"
+        }
+      ],
+      "title": "Wallet Balance",
+      "type": "stat"
     },
     {
       "datasource": {
@@ -278,11 +614,13 @@
             "mode": "palette-classic"
           },
           "custom": {
+            "axisBorderShow": false,
             "axisCenteredZero": false,
             "axisColorMode": "text",
             "axisLabel": "",
             "axisPlacement": "auto",
             "barAlignment": 0,
+            "barWidthFactor": 0.6,
             "drawStyle": "line",
             "fillOpacity": 0,
             "gradientMode": "none",
@@ -291,6 +629,7 @@
               "tooltip": false,
               "viz": false
             },
+            "insertNulls": false,
             "lineInterpolation": "linear",
             "lineWidth": 1,
             "pointSize": 5,
@@ -317,7 +656,7 @@
               }
             ]
           },
-          "unit": "s"
+          "unit": "locale"
         },
         "overrides": []
       },
@@ -325,9 +664,9 @@
         "h": 8,
         "w": 12,
         "x": 12,
-        "y": 8
+        "y": 16
       },
-      "id": 4,
+      "id": 11,
       "options": {
         "legend": {
           "calcs": [],
@@ -336,12 +675,12 @@
           "showLegend": true
         },
         "tooltip": {
+          "hideZeros": false,
           "mode": "single",
           "sort": "none"
         }
       },
-      "title": "Average Update Duration",
-      "type": "timeseries",
+      "pluginVersion": "11.5.2",
       "targets": [
         {
           "datasource": {
@@ -349,12 +688,14 @@
             "uid": "prometheus"
           },
           "editorMode": "code",
-          "expr": "rate(pyth_price_update_duration_seconds_sum[5m]) / rate(pyth_price_update_duration_seconds_count[5m])",
-          "legendFormat": "{{alias}}",
+          "expr": "pyth_wallet_balance",
+          "legendFormat": "{{wallet_address}} ({{network}})",
           "range": true,
           "refId": "A"
         }
-      ]
+      ],
+      "title": "Wallet Balance Over Time",
+      "type": "timeseries"
     },
     {
       "datasource": {
@@ -367,11 +708,13 @@
             "mode": "palette-classic"
           },
           "custom": {
+            "axisBorderShow": false,
             "axisCenteredZero": false,
             "axisColorMode": "text",
             "axisLabel": "",
             "axisPlacement": "auto",
             "barAlignment": 0,
+            "barWidthFactor": 0.6,
             "drawStyle": "line",
             "fillOpacity": 0,
             "gradientMode": "none",
@@ -380,6 +723,7 @@
               "tooltip": false,
               "viz": false
             },
+            "insertNulls": false,
             "lineInterpolation": "linear",
             "lineWidth": 1,
             "pointSize": 5,
@@ -396,6 +740,7 @@
               "mode": "off"
             }
           },
+          "decimals": 0,
           "mappings": [],
           "thresholds": {
             "mode": "absolute",
@@ -405,7 +750,8 @@
                 "value": null
               }
             ]
-          }
+          },
+          "unit": "none"
         },
         "overrides": []
       },
@@ -413,9 +759,9 @@
         "h": 8,
         "w": 12,
         "x": 0,
-        "y": 16
+        "y": 24
       },
-      "id": 5,
+      "id": 6,
       "options": {
         "legend": {
           "calcs": [],
@@ -424,12 +770,12 @@
           "showLegend": true
         },
         "tooltip": {
+          "hideZeros": false,
           "mode": "single",
           "sort": "none"
         }
       },
-      "title": "Active Price Feeds",
-      "type": "timeseries",
+      "pluginVersion": "11.5.2",
       "targets": [
         {
           "datasource": {
@@ -437,12 +783,14 @@
             "uid": "prometheus"
           },
           "editorMode": "code",
-          "expr": "pyth_active_price_feeds",
-          "legendFormat": "Active Feeds",
+          "expr": "sum(increase(pyth_price_update_errors_total[5m]))",
+          "legendFormat": "Errors",
           "range": true,
           "refId": "A"
         }
-      ]
+      ],
+      "title": "Update Errors",
+      "type": "timeseries"
     },
     {
       "datasource": {
@@ -455,11 +803,13 @@
             "mode": "palette-classic"
           },
           "custom": {
+            "axisBorderShow": false,
             "axisCenteredZero": false,
             "axisColorMode": "text",
             "axisLabel": "",
             "axisPlacement": "auto",
             "barAlignment": 0,
+            "barWidthFactor": 0.6,
             "drawStyle": "line",
             "fillOpacity": 0,
             "gradientMode": "none",
@@ -468,6 +818,7 @@
               "tooltip": false,
               "viz": false
             },
+            "insertNulls": false,
             "lineInterpolation": "linear",
             "lineWidth": 1,
             "pointSize": 5,
@@ -493,7 +844,8 @@
                 "value": null
               }
             ]
-          }
+          },
+          "unit": "s"
         },
         "overrides": []
       },
@@ -501,9 +853,9 @@
         "h": 8,
         "w": 12,
         "x": 12,
-        "y": 16
+        "y": 24
       },
-      "id": 6,
+      "id": 4,
       "options": {
         "legend": {
           "calcs": [],
@@ -512,12 +864,12 @@
           "showLegend": true
         },
         "tooltip": {
+          "hideZeros": false,
           "mode": "single",
           "sort": "none"
         }
       },
-      "title": "Update Errors",
-      "type": "timeseries",
+      "pluginVersion": "11.5.2",
       "targets": [
         {
           "datasource": {
@@ -525,17 +877,19 @@
             "uid": "prometheus"
           },
           "editorMode": "code",
-          "expr": "sum(increase(pyth_price_update_errors_total[5m]))",
-          "legendFormat": "Errors",
+          "expr": "rate(pyth_price_update_duration_seconds_sum[5m]) / rate(pyth_price_update_duration_seconds_count[5m])",
+          "legendFormat": "{{alias}}",
           "range": true,
           "refId": "A"
         }
-      ]
+      ],
+      "title": "Average Update Duration",
+      "type": "timeseries"
     }
   ],
+  "preload": false,
   "refresh": "5s",
-  "schemaVersion": 38,
-  "style": "dark",
+  "schemaVersion": 40,
   "tags": [],
   "templating": {
     "list": []
@@ -548,6 +902,6 @@
   "timezone": "",
   "title": "Pyth Price Pusher Dashboard",
   "uid": "pyth-price-pusher",
-  "version": 1,
+  "version": 39,
   "weekStart": ""
 }

+ 1 - 1
apps/price_pusher/price-config.stable.sample.yaml

@@ -13,7 +13,7 @@
     price_deviation: 0.5
     confidence_ratio: 0.1
 - alias: PYTH/USD
-  id: 2f95862b045670cd22bee3114c39763a4a08beeb663b145d283c31d7d1101c23
+  id: 0bbf28e9a841a1cc788f6a361b17ca072d0ea3098a1e5df1c3922d06719579ff
   time_difference: 60
   price_deviation: 0.5
   confidence_ratio: 1

+ 44 - 2
apps/price_pusher/src/controller.ts

@@ -4,10 +4,20 @@ import { IPriceListener, IPricePusher } from "./interface";
 import { PriceConfig, shouldUpdate, UpdateCondition } from "./price-config";
 import { Logger } from "pino";
 import { PricePusherMetrics } from "./metrics";
+import { SuperWalletClient } from "./evm/super-wallet";
+
+// Define the wallet balance info interface
+interface WalletBalanceInfo {
+  client: SuperWalletClient;
+  address: string;
+  network: string;
+  updateInterval: DurationInSeconds;
+}
 
 export class Controller {
   private pushingFrequency: DurationInSeconds;
   private metrics?: PricePusherMetrics;
+  private walletBalanceInfo?: WalletBalanceInfo;
 
   constructor(
     private priceConfigs: PriceConfig[],
@@ -18,14 +28,36 @@ export class Controller {
     config: {
       pushingFrequency: DurationInSeconds;
       metrics?: PricePusherMetrics;
+      walletBalanceInfo?: WalletBalanceInfo;
     }
   ) {
     this.pushingFrequency = config.pushingFrequency;
     this.metrics = config.metrics;
+    this.walletBalanceInfo = config.walletBalanceInfo;
 
-    // Set the number of active price feeds if metrics are enabled
+    // Set the number of price feeds if metrics are enabled
     if (this.metrics) {
-      this.metrics.setActivePriceFeeds(this.priceConfigs.length);
+      this.metrics.setPriceFeedsTotal(this.priceConfigs.length);
+    }
+  }
+
+  // Get wallet balance and update metrics
+  private async updateWalletBalance(): Promise<void> {
+    if (!this.metrics || !this.walletBalanceInfo) return;
+
+    try {
+      const { client, address, network } = this.walletBalanceInfo;
+      const balance = await client.getBalance({ address: address as `0x${string}` });
+
+      this.metrics.updateWalletBalance(address, network, balance);
+      this.logger.debug(
+        `Updated wallet balance: ${address} = ${balance.toString()}`
+      );
+    } catch (error) {
+      this.logger.error(
+        { error },
+        "Error fetching wallet balance for metrics"
+      );
     }
   }
 
@@ -34,6 +66,11 @@ export class Controller {
     await this.sourcePriceListener.start();
     await this.targetPriceListener.start();
 
+    // Update wallet balance initially if metrics are enabled
+    if (this.metrics && this.walletBalanceInfo) {
+      await this.updateWalletBalance();
+    }
+
     // wait for the listeners to get updated. There could be a restart
     // before this run and we need to respect the cooldown duration as
     // their might be a message sent before.
@@ -46,6 +83,11 @@ export class Controller {
       const pricesToPush: PriceConfig[] = [];
       const pubTimesToPush: UnixTimestamp[] = [];
 
+      // Update wallet balance if metrics are enabled
+      if (this.metrics && this.walletBalanceInfo) {
+        await this.updateWalletBalance();
+      }
+
       for (const priceConfig of this.priceConfigs) {
         const priceId = priceConfig.id;
         const alias = priceConfig.alias;

+ 7 - 1
apps/price_pusher/src/evm/command.ts

@@ -199,9 +199,15 @@ export default {
       {
         pushingFrequency,
         metrics,
+        walletBalanceInfo: metrics ? {
+          client,
+          address: client.account.address,
+          network: await client.getChainId().then(id => id.toString()),
+          updateInterval: pushingFrequency
+        } : undefined
       }
     );
 
-    controller.start();
+    await controller.start();
   },
 };

+ 34 - 7
apps/price_pusher/src/metrics.ts

@@ -13,9 +13,11 @@ export class PricePusherMetrics {
   public lastPublishedTime: Gauge<string>;
   public priceUpdatesTotal: Counter<string>;
   public priceUpdateDuration: Histogram<string>;
-  public activePriceFeeds: Gauge<string>;
+  public priceFeedsTotal: Gauge<string>;
   public priceUpdateErrors: Counter<string>;
   public priceUpdateAttempts: Counter<string>;
+  // Wallet metrics
+  public walletBalance: Gauge<string>;
 
   constructor(logger: Logger) {
     this.logger = logger;
@@ -48,9 +50,9 @@ export class PricePusherMetrics {
       registers: [this.registry],
     });
 
-    this.activePriceFeeds = new Gauge({
-      name: "pyth_active_price_feeds",
-      help: "Number of active price feeds being monitored",
+    this.priceFeedsTotal = new Gauge({
+      name: "pyth_price_feeds_total",
+      help: "Total number of price feeds being monitored",
       registers: [this.registry],
     });
 
@@ -68,6 +70,14 @@ export class PricePusherMetrics {
       registers: [this.registry],
     });
 
+    // Wallet balance metric
+    this.walletBalance = new Gauge({
+      name: "pyth_wallet_balance",
+      help: "Current wallet balance of the price pusher in native token units",
+      labelNames: ["wallet_address", "network"],
+      registers: [this.registry],
+    });
+
     // Setup the metrics endpoint
     this.server.get("/metrics", async (req, res) => {
       res.set("Content-Type", this.registry.contentType);
@@ -117,9 +127,9 @@ export class PricePusherMetrics {
     });
   }
 
-  // Set the number of active price feeds
-  public setActivePriceFeeds(count: number): void {
-    this.activePriceFeeds.set(count);
+  // Set the number of price feeds
+  public setPriceFeedsTotal(count: number): void {
+    this.priceFeedsTotal.set(count);
   }
 
   // Create a timer for measuring price update duration
@@ -130,4 +140,21 @@ export class PricePusherMetrics {
     });
     return end;
   }
+
+  // Update wallet balance
+  public updateWalletBalance(
+    walletAddress: string,
+    network: string,
+    balance: bigint | number
+  ): void {
+    // Convert to number for compatibility with prometheus
+    const balanceNum = typeof balance === 'bigint' ? Number(balance) / 1e18 : balance;
+    this.walletBalance.set(
+      { wallet_address: walletAddress, network },
+      balanceNum
+    );
+    this.logger.debug(
+      `Updated wallet balance metric: ${walletAddress} = ${balanceNum}`
+    );
+  }
 }