From 6a86ce2f91ba221d4bb02e8c6aca445b7f6b6c41 Mon Sep 17 00:00:00 2001 From: "Emmanuel .A" Date: Sun, 12 Apr 2026 23:33:55 +0100 Subject: [PATCH] chore: add developer metrics tracker to sdk --- src/internal/metrics.ts | 49 +++++++++++++++++++ src/non-custodial/index.ts | 13 +++++ src/sdk/index.ts | 5 ++ src/sdk/sponsorship/index.ts | 11 +++++ src/sdk/tokenization/cardano.ts | 9 ++++ src/sdk/tokenization/spark.ts | 9 ++++ .../wallet-developer-controlled/cardano.ts | 16 ++++++ src/sdk/wallet-developer-controlled/index.ts | 9 ++++ 8 files changed, 121 insertions(+) create mode 100644 src/internal/metrics.ts diff --git a/src/internal/metrics.ts b/src/internal/metrics.ts new file mode 100644 index 0000000..5612761 --- /dev/null +++ b/src/internal/metrics.ts @@ -0,0 +1,49 @@ +import { AxiosInstance } from "axios"; + +/** + * Tracks a transaction metric specifically for developer-controlled wallets. + * Internal SDK helper used by DCW functions. + */ +export async function trackDeveloperTransaction( + axiosInstance: AxiosInstance, + network: "mainnet" | "testnet", + blockchain: "cardano" | "bitcoin" | "spark", + type: string = "tx-submit" +) { + try { + const yearMonth = new Date().toISOString().slice(0, 7); + await axiosInstance.post("api/metrics/tx", { + walletType: "developer", + blockchain, + network: network, + type, + yearMonth, + }); + } catch (error) { + // Silent fail - tracing shouldn't break the SDK + } +} + +/** + * Tracks a platform-level metric. + * Internal SDK helper for platform-wide analytics. + */ +export async function trackPlatformMetric( + axiosInstance: AxiosInstance, + metricType: + | "mau" + | "new-wallets" + | "active-projects" + | "new-projects", + count: number = 1 +) { + try { + await axiosInstance.post("api/metrics/platform", { + metricType, + count, + }); + } catch (error) { + // Silent fail + } +} + diff --git a/src/non-custodial/index.ts b/src/non-custodial/index.ts index 285db0e..6f3006a 100644 --- a/src/non-custodial/index.ts +++ b/src/non-custodial/index.ts @@ -5,7 +5,12 @@ import { Web3WalletObject, Web3AuthProvider, } from "../"; +import axios from "axios"; +import { trackPlatformMetric } from "../internal/metrics"; + + import { getStorage, getLinking, getEncoding } from "../internal/platform-context"; + export * from "./utils"; const AUTH_KEY = "mesh-web3-services-auth"; @@ -359,7 +364,15 @@ export class Web3NonCustodialProvider { } const result = (await res.json()) as CreateWalletResponseBody; + try { + const metricsAxios = axios.create({ baseURL: this.appOrigin }); + await trackPlatformMetric(metricsAxios, "new-wallets"); + await trackPlatformMetric(metricsAxios, "mau"); + } catch (e) {} + await this.pushDevice({ + + deviceId: result.deviceId, encryptedDeviceShard, walletId: result.walletId, diff --git a/src/sdk/index.ts b/src/sdk/index.ts index 241fc23..b13a379 100644 --- a/src/sdk/index.ts +++ b/src/sdk/index.ts @@ -4,6 +4,8 @@ import { Web3Project } from "../types"; import { IFetcher, ISubmitter } from "@meshsdk/common"; import { Sponsorship } from "./sponsorship"; import { Tokenization } from "./tokenization"; +import { trackPlatformMetric } from "../internal/metrics"; + export const meshUniversalStaticUtxo = { mainnet: { @@ -148,7 +150,10 @@ export class Web3Sdk { if (status === 200) { this.project = data as Web3Project; + await trackPlatformMetric(this.axiosInstance, "active-projects"); + await trackPlatformMetric(this.axiosInstance, "mau"); return this.project; + } throw new Error("Failed to get project"); diff --git a/src/sdk/sponsorship/index.ts b/src/sdk/sponsorship/index.ts index b03103d..7f225b2 100644 --- a/src/sdk/sponsorship/index.ts +++ b/src/sdk/sponsorship/index.ts @@ -3,6 +3,8 @@ import { Asset, UTxO } from "@meshsdk/common"; import { MeshTxBuilder } from "@meshsdk/transaction"; import { meshUniversalStaticUtxo } from "../index"; import { SponsorshipTxParserPostRequestBody } from "../../types"; +import { trackDeveloperTransaction } from "../../internal/metrics"; + type SponsorshipConfig = { id: string; @@ -482,6 +484,15 @@ export class Sponsorship { const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTxReturnFullTx(unsignedTx); const txHash = await this.sdk.providerSubmitter!.submitTx(signedTx); + if(txHash){ + await trackDeveloperTransaction( + this.sdk.axiosInstance, + this.sdk.network, + "cardano", + "tx-submit", + ); + } + await this.sdk.axiosInstance.post( `api/sponsorship/${config.id}/refreshTxHash`, diff --git a/src/sdk/tokenization/cardano.ts b/src/sdk/tokenization/cardano.ts index 69ff57d..19d39d3 100644 --- a/src/sdk/tokenization/cardano.ts +++ b/src/sdk/tokenization/cardano.ts @@ -17,6 +17,8 @@ import { ListFrozenAddressesParams, ListTokenizationPoliciesParams, } from "../../types/cardano/tokenization"; +import { trackDeveloperTransaction } from "../../internal/metrics"; + export type { CreateTokenParams, @@ -313,6 +315,13 @@ export class TokenizationCardano { status: params.status || "success", metadata: params.metadata, }); + await trackDeveloperTransaction( + this.sdk.axiosInstance, + this.sdk.network, + "cardano", + "tx-submit", + ); + } catch (error) { console.warn(`Failed to log ${params.type} transaction:`, error); } diff --git a/src/sdk/tokenization/spark.ts b/src/sdk/tokenization/spark.ts index ea3906c..255c1fc 100644 --- a/src/sdk/tokenization/spark.ts +++ b/src/sdk/tokenization/spark.ts @@ -26,6 +26,8 @@ import { ListFrozenAddressesParams, ListTokenizationPoliciesParams, } from "../../types/spark/tokenization"; +import { trackDeveloperTransaction } from "../../internal/metrics"; + export type { InitTokenizationParams, @@ -671,6 +673,13 @@ export class TokenizationSpark { toAddress: params.toAddress, status: params.status || "confirmed", }); + await trackDeveloperTransaction( + this.sdk.axiosInstance, + this.sdk.network, + "spark", + "tx-submit", + ); + } catch (error) { console.warn(`Failed to log ${params.type} transaction:`, error); } diff --git a/src/sdk/wallet-developer-controlled/cardano.ts b/src/sdk/wallet-developer-controlled/cardano.ts index 8487df3..a789d37 100644 --- a/src/sdk/wallet-developer-controlled/cardano.ts +++ b/src/sdk/wallet-developer-controlled/cardano.ts @@ -2,6 +2,8 @@ import { Web3Sdk } from ".."; import { MeshCardanoHeadlessWallet } from "@meshsdk/wallet"; import { decryptWithPrivateKey } from "../../functions"; import { MultiChainWalletInfo, TokenCreationParams } from "../../types"; +import { trackDeveloperTransaction } from "../../internal/metrics"; + /** * CardanoWalletDeveloperControlled - Manages Cardano-specific developer-controlled wallets. @@ -103,7 +105,21 @@ export class CardanoWalletDeveloperControlled { walletAddressType: 1, }); + // Wrap submitTx to track metrics + const originalSubmitTx = wallet.submitTx.bind(wallet); + wallet.submitTx = async (tx: string) => { + const txHash = await originalSubmitTx(tx); + await trackDeveloperTransaction( + this.sdk.axiosInstance, + this.sdk.network, + "cardano", + "tx-submit", + ); + return txHash; + }; + return { info: web3Wallet, wallet: wallet }; + } throw new Error("Failed to get Cardano wallet"); diff --git a/src/sdk/wallet-developer-controlled/index.ts b/src/sdk/wallet-developer-controlled/index.ts index 9c3a9db..fd64da8 100644 --- a/src/sdk/wallet-developer-controlled/index.ts +++ b/src/sdk/wallet-developer-controlled/index.ts @@ -12,6 +12,11 @@ import { IssuerSparkWallet } from "@buildonspark/issuer-sdk"; import { deserializeBech32Address } from "@meshsdk/core-cst"; import { encryptWithPublicKey, decryptWithPrivateKey } from "../../functions"; import { v4 as uuidv4 } from "uuid"; +import { + trackPlatformMetric, +} from "../../internal/metrics"; + + /** * The `WalletDeveloperControlled` class provides functionality for managing developer-controlled wallets @@ -138,7 +143,11 @@ export class WalletDeveloperControlled { ); if (status === 200) { + await trackPlatformMetric(this.sdk.axiosInstance, "new-wallets"); + await trackPlatformMetric(this.sdk.axiosInstance, "mau"); return { + + info: walletData, sparkIssuerWallet: sparkWallet, cardanoWallet: cardanoWallet,