diff --git a/packages/extension/package.json b/packages/extension/package.json
index 8218c3344..ff7af2231 100644
--- a/packages/extension/package.json
+++ b/packages/extension/package.json
@@ -39,6 +39,7 @@
     "@kadena/client": "^1.18.0",
     "@kadena/pactjs-cli": "^1.18.0",
     "@ledgerhq/hw-transport-webusb": "^6.29.8",
+    "@massalabs/massa-web3": "5.2.1-dev.20250730141858",
     "@metamask/eth-sig-util": "^8.2.0",
     "@metaplex-foundation/mpl-bubblegum": "^5.0.2",
     "@metaplex-foundation/umi": "^1.2.0",
diff --git a/packages/extension/src/libs/background/index.ts b/packages/extension/src/libs/background/index.ts
index d00f28109..ca4fdee91 100644
--- a/packages/extension/src/libs/background/index.ts
+++ b/packages/extension/src/libs/background/index.ts
@@ -48,6 +48,7 @@ class BackgroundHandler {
       [ProviderName.bitcoin]: {},
       [ProviderName.kadena]: {},
       [ProviderName.solana]: {},
+      [ProviderName.massa]: {},
     };
     this.#providers = Providers;
   }
diff --git a/packages/extension/src/libs/background/types.ts b/packages/extension/src/libs/background/types.ts
index 73cc10eb9..ae2c834cd 100644
--- a/packages/extension/src/libs/background/types.ts
+++ b/packages/extension/src/libs/background/types.ts
@@ -3,6 +3,7 @@ import type EthereumProvider from '@/providers/ethereum';
 import type PolkadotProvider from '@/providers/polkadot';
 import type KadenaProvider from '@/providers/kadena';
 import SolanaProvider from '@/providers/solana';
+import MassaProvider from '@/providers/massa';
 
 export interface TabProviderType {
   [key: string]: Record<
@@ -12,6 +13,7 @@ export interface TabProviderType {
     | BitcoinProvider
     | KadenaProvider
     | SolanaProvider
+    | MassaProvider
   >;
 }
 export interface ProviderType {
@@ -20,7 +22,8 @@ export interface ProviderType {
     | typeof PolkadotProvider
     | typeof BitcoinProvider
     | typeof KadenaProvider
-    | typeof SolanaProvider;
+    | typeof SolanaProvider
+    | typeof MassaProvider;
 }
 export interface ExternalMessageOptions {
   savePersistentEvents: boolean;
diff --git a/packages/extension/src/libs/tokens-state/index.ts b/packages/extension/src/libs/tokens-state/index.ts
index 8feb22300..b86a5ec00 100644
--- a/packages/extension/src/libs/tokens-state/index.ts
+++ b/packages/extension/src/libs/tokens-state/index.ts
@@ -6,6 +6,7 @@ import {
   CustomToken,
   CustomErc20Token,
   TokenType,
+  CustomMassaToken,
 } from './types';
 import { NetworkNames } from '@enkryptcom/types';
 
@@ -24,7 +25,7 @@ export class TokensState {
    */
   async addErc20Token(
     chainName: NetworkNames,
-    token: CustomErc20Token,
+    token: CustomErc20Token | CustomMassaToken,
   ): Promise<boolean> {
     let state: IState | null = await this.storage.get(StorageKeys.customTokens);
 
diff --git a/packages/extension/src/libs/tokens-state/types.ts b/packages/extension/src/libs/tokens-state/types.ts
index b64799858..8220ae87f 100644
--- a/packages/extension/src/libs/tokens-state/types.ts
+++ b/packages/extension/src/libs/tokens-state/types.ts
@@ -21,4 +21,8 @@ export interface CustomErc20Token extends CustomToken {
   address: `0x${string}`;
 }
 
+export interface CustomMassaToken extends CustomToken {
+  address: `AS${string}`;
+}
+
 export type IState = Partial<Record<NetworkNames, CustomToken[]>>;
diff --git a/packages/extension/src/libs/utils/initialize-wallet.ts b/packages/extension/src/libs/utils/initialize-wallet.ts
index 60d159be4..6b97b9454 100644
--- a/packages/extension/src/libs/utils/initialize-wallet.ts
+++ b/packages/extension/src/libs/utils/initialize-wallet.ts
@@ -4,6 +4,7 @@ import PolkadotNetworks from '@/providers/polkadot/networks';
 import BitcoinNetworks from '@/providers/bitcoin/networks';
 import KadenaNetworks from '@/providers/kadena/networks';
 import SolanaNetworks from '@/providers/solana/networks';
+import MassaNetworks from '@/providers/massa/networks';
 import { NetworkNames, WalletType } from '@enkryptcom/types';
 import { getAccountsByNetworkName } from '@/libs/utils/accounts';
 import BackupState from '../backup-state';
@@ -23,6 +24,9 @@ export const initAccounts = async (keyring: KeyRing) => {
   const ed25519sol = (
     await getAccountsByNetworkName(NetworkNames.Solana)
   ).filter(acc => !acc.isTestWallet);
+  const ed25519massa = (
+    await getAccountsByNetworkName(NetworkNames.Massa)
+  ).filter(acc => !acc.isTestWallet);
   if (secp256k1.length == 0)
     await keyring.saveNewAccount({
       basePath: EthereumNetworks.ethereum.basePath,
@@ -58,6 +62,13 @@ export const initAccounts = async (keyring: KeyRing) => {
       signerType: SolanaNetworks.solana.signer[0],
       walletType: WalletType.mnemonic,
     });
+  if (ed25519massa.length == 0)
+    await keyring.saveNewAccount({
+      basePath: MassaNetworks.mainnet.basePath,
+      name: 'Massa Account 1',
+      signerType: MassaNetworks.mainnet.signer[0],
+      walletType: WalletType.mnemonic,
+    });
 };
 export const onboardInitializeWallets = async (options: {
   mnemonic: string;
diff --git a/packages/extension/src/libs/utils/networks.ts b/packages/extension/src/libs/utils/networks.ts
index 608652fcc..2eccad1da 100644
--- a/packages/extension/src/libs/utils/networks.ts
+++ b/packages/extension/src/libs/utils/networks.ts
@@ -13,6 +13,8 @@ import Polkadot from '@/providers/polkadot/networks/polkadot';
 import Bitcoin from '@/providers/bitcoin/networks/bitcoin';
 import Kadena from '@/providers/kadena/networks/kadena';
 import Solana from '@/providers/solana/networks/solana';
+import MassaNetworks from '@/providers/massa/networks';
+import Massa from '@/providers/massa/networks/mainnet';
 
 const providerNetworks: Record<ProviderName, Record<string, BaseNetwork>> = {
   [ProviderName.ethereum]: EthereumNetworks,
@@ -20,6 +22,7 @@ const providerNetworks: Record<ProviderName, Record<string, BaseNetwork>> = {
   [ProviderName.bitcoin]: BitcoinNetworks,
   [ProviderName.kadena]: KadenaNetworks,
   [ProviderName.solana]: SolanaNetworks,
+  [ProviderName.massa]: MassaNetworks,
   [ProviderName.enkrypt]: {},
 };
 const getAllNetworks = async (
@@ -34,7 +37,9 @@ const getAllNetworks = async (
     .concat(Object.values(PolkadotNetworks) as BaseNetwork[])
     .concat(Object.values(BitcoinNetworks) as BaseNetwork[])
     .concat(Object.values(KadenaNetworks) as BaseNetwork[])
-    .concat(Object.values(SolanaNetworks) as BaseNetwork[]);
+    .concat(Object.values(SolanaNetworks) as BaseNetwork[])
+    .concat(Object.values(MassaNetworks) as BaseNetwork[]);
+
   if (!includeCustom) {
     return allNetworks;
   }
@@ -67,17 +72,20 @@ const DEFAULT_SUBSTRATE_NETWORK_NAME = NetworkNames.Polkadot;
 const DEFAULT_BTC_NETWORK_NAME = NetworkNames.Bitcoin;
 const DEFAULT_KADENA_NETWORK_NAME = NetworkNames.Kadena;
 const DEFAULT_SOLANA_NETWORK_NAME = NetworkNames.Solana;
+const DEFAULT_MASSA_NETWORK_NAME = NetworkNames.Massa;
 
 const DEFAULT_EVM_NETWORK = Ethereum;
 const DEFAULT_SUBSTRATE_NETWORK = Polkadot;
 const DEFAULT_BTC_NETWORK = Bitcoin;
 const DEFAULT_KADENA_NETWORK = Kadena;
 const DEFAULT_SOLANA_NETWORK = Solana;
+const DEFAULT_MASSA_NETWORK = Massa;
 
 const POPULAR_NAMES = [
   NetworkNames.Bitcoin,
   NetworkNames.Ethereum,
   NetworkNames.Solana,
+  NetworkNames.Massa,
   NetworkNames.Matic,
   NetworkNames.Polkadot,
   NetworkNames.Binance,
@@ -100,4 +108,6 @@ export {
   DEFAULT_KADENA_NETWORK_NAME,
   DEFAULT_SOLANA_NETWORK,
   DEFAULT_SOLANA_NETWORK_NAME,
+  DEFAULT_MASSA_NETWORK,
+  DEFAULT_MASSA_NETWORK_NAME,
 };
diff --git a/packages/extension/src/providers/index.ts b/packages/extension/src/providers/index.ts
index f1b8e6106..90498059e 100644
--- a/packages/extension/src/providers/index.ts
+++ b/packages/extension/src/providers/index.ts
@@ -3,6 +3,7 @@ import PolkadotProvider from '@/providers/polkadot';
 import BitcoinProvider from '@/providers/bitcoin';
 import KadenaProvider from '@/providers/kadena';
 import SolanaProvider from '@/providers/solana';
+import MassaProvider from '@/providers/massa';
 import { ProviderName } from '@/types/provider';
 
 export default {
@@ -11,4 +12,5 @@ export default {
   [ProviderName.bitcoin]: BitcoinProvider,
   [ProviderName.kadena]: KadenaProvider,
   [ProviderName.solana]: SolanaProvider,
+  [ProviderName.massa]: MassaProvider,
 };
diff --git a/packages/extension/src/providers/massa/index.ts b/packages/extension/src/providers/massa/index.ts
new file mode 100644
index 000000000..6ed5245a8
--- /dev/null
+++ b/packages/extension/src/providers/massa/index.ts
@@ -0,0 +1,92 @@
+import { BaseNetwork } from '@/types/base-network';
+import getRequestProvider, { RequestClass } from '@enkryptcom/request';
+import { MiddlewareFunction, OnMessageResponse } from '@enkryptcom/types';
+import Middlewares from './methods';
+import EventEmitter from 'eventemitter3';
+import {
+  BackgroundProviderInterface,
+  ProviderName,
+  ProviderRPCRequest,
+} from '@/types/provider';
+import GetUIPath from '@/libs/utils/get-ui-path';
+import PublicKeyRing from '@/libs/keyring/public-keyring';
+import UIRoutes from './ui/routes/names';
+import { RoutesType } from '@/types/ui';
+import massaNetworks from './networks';
+import { NetworkNames } from '@enkryptcom/types';
+
+export default class MassaProvider
+  extends EventEmitter
+  implements BackgroundProviderInterface
+{
+  public network: BaseNetwork;
+  requestProvider: RequestClass;
+  middlewares: MiddlewareFunction[] = [];
+  namespace: string;
+  KeyRing: PublicKeyRing;
+  UIRoutes: RoutesType;
+  toWindow: (message: string) => void;
+
+  constructor(
+    toWindow: (message: string) => void,
+    network: BaseNetwork = massaNetworks[NetworkNames.Massa],
+  ) {
+    super();
+    this.network = network;
+    this.toWindow = toWindow;
+    this.setMiddleWares();
+    this.requestProvider = getRequestProvider('', this.middlewares);
+    this.requestProvider.on('notification', (notif: any) => {
+      this.sendNotification(JSON.stringify(notif));
+    });
+    this.namespace = ProviderName.massa;
+    this.KeyRing = new PublicKeyRing();
+
+    this.UIRoutes = UIRoutes;
+  }
+
+  private setMiddleWares(): void {
+    this.middlewares = Middlewares(this).map(mw => mw.bind(this));
+  }
+
+  setRequestProvider(network: BaseNetwork): void {
+    const prevURL = new URL(this.network.node);
+    const newURL = new URL(network.node);
+    this.network = network;
+    if (prevURL.protocol === newURL.protocol)
+      this.requestProvider.changeNetwork(network.node);
+    else
+      this.requestProvider = getRequestProvider(network.node, this.middlewares);
+  }
+
+  async isPersistentEvent(): Promise<boolean> {
+    return false;
+  }
+
+  async sendNotification(notif: string): Promise<void> {
+    return this.toWindow(notif);
+  }
+
+  request(request: ProviderRPCRequest): Promise<OnMessageResponse> {
+    return this.requestProvider
+      .request(request)
+      .then(res => {
+        return {
+          result: JSON.stringify(res),
+        };
+      })
+      .catch(e => {
+        return {
+          error: JSON.stringify(e.message),
+        };
+      });
+  }
+
+  getUIPath(page: string): string {
+    return GetUIPath(page, this.namespace);
+  }
+
+  getCurrentNetwork(): BaseNetwork {
+    return this.network;
+  }
+}
diff --git a/packages/extension/src/providers/massa/libs/activity-handlers/index.ts b/packages/extension/src/providers/massa/libs/activity-handlers/index.ts
new file mode 100644
index 000000000..301f4ec93
--- /dev/null
+++ b/packages/extension/src/providers/massa/libs/activity-handlers/index.ts
@@ -0,0 +1,3 @@
+import MassaActivity from './massa';
+
+export { MassaActivity };
diff --git a/packages/extension/src/providers/massa/libs/activity-handlers/massa.ts b/packages/extension/src/providers/massa/libs/activity-handlers/massa.ts
new file mode 100644
index 000000000..8c1bbc7a9
--- /dev/null
+++ b/packages/extension/src/providers/massa/libs/activity-handlers/massa.ts
@@ -0,0 +1,27 @@
+import { BaseNetwork } from '@/types/base-network';
+import { Activity, ActivityStatus, ActivityType } from '@/types/activity';
+import { ActivityHandlerType } from '@/libs/activity-state/types';
+import ActivityState from '@/libs/activity-state';
+
+const MassaActivity: ActivityHandlerType = async (
+  network: BaseNetwork,
+  address: string,
+): Promise<Activity[]> => {
+  try {
+    // Get activities from local storage
+    const activityState = new ActivityState();
+    const activities = await activityState.getAllActivities({
+      address,
+      network: network.name,
+    });
+
+    // For now, return local activities
+    // In the future, this can be extended to fetch from Massa explorer API
+    return activities;
+  } catch (error) {
+    console.error('Error fetching Massa activities:', error);
+    return [];
+  }
+};
+
+export default MassaActivity;
diff --git a/packages/extension/src/providers/massa/libs/api.ts b/packages/extension/src/providers/massa/libs/api.ts
new file mode 100644
index 000000000..03c45f4a0
--- /dev/null
+++ b/packages/extension/src/providers/massa/libs/api.ts
@@ -0,0 +1,60 @@
+import { ProviderAPIInterface } from '@/types/provider';
+import {
+  JsonRpcPublicProvider,
+  MRC20,
+  NodeStatusInfo,
+  OperationStatus,
+} from '@massalabs/massa-web3';
+
+export default class MassaAPI extends ProviderAPIInterface {
+  public provider: JsonRpcPublicProvider;
+  public node: string;
+
+  constructor(node: string) {
+    super(node);
+    this.node = node;
+    this.provider = JsonRpcPublicProvider.fromRPCUrl(
+      node,
+    ) as JsonRpcPublicProvider;
+  }
+
+  public get api() {
+    return this;
+  }
+
+  async init(): Promise<void> {}
+
+  async getBalance(address: string): Promise<string> {
+    const [account] = await this.provider.balanceOf([address], false);
+    if (!account) return '0';
+    return account.balance.toString();
+  }
+
+  async getBalanceMRC20(address: string, contract: string): Promise<string> {
+    const mrc20 = new MRC20(this.provider, contract);
+    const balance = await mrc20.balanceOf(address);
+    return balance.toString();
+  }
+
+  async getMinimalFee(): Promise<string> {
+    try {
+      const networkInfo = await this.provider.networkInfos();
+      return networkInfo.minimalFee.toString();
+    } catch (error) {
+      // Return a default minimal fee if network info is not available
+      return '10000000'; // 0.01 MAS in base units (9 decimals)
+    }
+  }
+
+  async getTransactionStatus(opId: string): Promise<OperationStatus | null> {
+    try {
+      return this.provider.getOperationStatus(opId);
+    } catch (error) {
+      return null;
+    }
+  }
+
+  async getNodeStatus(): Promise<NodeStatusInfo> {
+    return this.provider.getNodeStatus();
+  }
+}
diff --git a/packages/extension/src/providers/massa/methods/index.ts b/packages/extension/src/providers/massa/methods/index.ts
new file mode 100644
index 000000000..1d3a3d8bb
--- /dev/null
+++ b/packages/extension/src/providers/massa/methods/index.ts
@@ -0,0 +1,19 @@
+import { MiddlewareFunction } from '@enkryptcom/types';
+import { BackgroundProviderInterface } from '@/types/provider';
+import massa_getBalance from './massa_getBalance';
+import massa_getNetwork from './massa_getNetwork';
+import massa_setNetwork from './massa_setNetwork';
+
+export default (
+  provider: BackgroundProviderInterface,
+): MiddlewareFunction[] => {
+  return [
+    massa_getBalance,
+    massa_getNetwork,
+    massa_setNetwork,
+    async (request, response, next) => {
+      // Add any additional Massa-specific middleware logic here
+      return next();
+    },
+  ];
+};
diff --git a/packages/extension/src/providers/massa/methods/massa_getBalance.ts b/packages/extension/src/providers/massa/methods/massa_getBalance.ts
new file mode 100644
index 000000000..a7ff97509
--- /dev/null
+++ b/packages/extension/src/providers/massa/methods/massa_getBalance.ts
@@ -0,0 +1,34 @@
+import { MiddlewareFunction } from '@enkryptcom/types';
+import { ProviderRPCRequest } from '@/types/provider';
+import { Address } from '@massalabs/massa-web3';
+import { getCustomError } from '@/libs/error';
+import MassaProvider from '..';
+import { MassaNetwork } from '../networks/massa-base';
+
+const method: MiddlewareFunction = async function (
+  this: MassaProvider,
+  payload: ProviderRPCRequest,
+  res,
+  next,
+): Promise<void> {
+  if (payload.method !== 'massa_getBalance') return next();
+  else {
+    try {
+      const address = payload.params?.[0];
+      const network = this.network as MassaNetwork;
+      if (!address || !network.isValidAddress(address)) {
+        res(getCustomError('Please enter a valid Massa address'));
+        return;
+      }
+
+      const api = await network.api();
+      const balance = await api.getBalance(address);
+
+      res(null, balance);
+    } catch (error) {
+      res(getCustomError('Could not fetch balance from network'));
+    }
+  }
+};
+
+export default method;
diff --git a/packages/extension/src/providers/massa/methods/massa_getNetwork.ts b/packages/extension/src/providers/massa/methods/massa_getNetwork.ts
new file mode 100644
index 000000000..ac12aea67
--- /dev/null
+++ b/packages/extension/src/providers/massa/methods/massa_getNetwork.ts
@@ -0,0 +1,22 @@
+import { MiddlewareFunction } from '@enkryptcom/types';
+import { ProviderRPCRequest } from '@/types/provider';
+import { NetworkNames } from '@enkryptcom/types';
+import MassaProvider from '..';
+
+const method: MiddlewareFunction = async function (
+  this: MassaProvider,
+  payload: ProviderRPCRequest,
+  res,
+  next,
+): Promise<void> {
+  if (payload.method !== 'massa_getNetwork') return next();
+  else {
+    try {
+      res(null, this.network.name);
+    } catch (error) {
+      res(null, NetworkNames.Massa);
+    }
+  }
+};
+
+export default method;
diff --git a/packages/extension/src/providers/massa/methods/massa_setNetwork.ts b/packages/extension/src/providers/massa/methods/massa_setNetwork.ts
new file mode 100644
index 000000000..d8d895d51
--- /dev/null
+++ b/packages/extension/src/providers/massa/methods/massa_setNetwork.ts
@@ -0,0 +1,55 @@
+import { MiddlewareFunction } from '@enkryptcom/types';
+import { ProviderRPCRequest } from '@/types/provider';
+import { getCustomError } from '@/libs/error';
+import massaNetworks from '../networks';
+import MassaProvider from '..';
+
+const method: MiddlewareFunction = async function (
+  this: MassaProvider,
+  payload: ProviderRPCRequest,
+  res,
+  next,
+): Promise<void> {
+  if (payload.method !== 'massa_setNetwork') return next();
+  else {
+    try {
+      const networkName = payload.params?.[0];
+
+      if (!networkName) {
+        res(getCustomError('Network name is required'));
+        return;
+      }
+
+      // Check if the network exists
+      const availableNetworks = Object.keys(massaNetworks);
+
+      if (!availableNetworks.includes(networkName)) {
+        res(
+          getCustomError(
+            `Invalid network name. Available networks: ${availableNetworks.join(', ')}`,
+          ),
+        );
+        return;
+      }
+
+      // Get the network object
+      const network = massaNetworks[networkName as keyof typeof massaNetworks];
+
+      // Set the network in the provider
+      if (this.setRequestProvider) {
+        this.setRequestProvider(network);
+        res(null, { success: true, network: network.name });
+      } else {
+        res(getCustomError('Network switching not supported'));
+      }
+    } catch (error) {
+      res(
+        getCustomError(
+          `Network switching failed: ${(error as Error).message || 'Unknown error'}`,
+        ),
+      );
+    }
+  }
+};
+
+export default method;
diff --git a/packages/extension/src/providers/massa/networks/buildnet.ts b/packages/extension/src/providers/massa/networks/buildnet.ts
new file mode 100644
index 000000000..81c3feab8
--- /dev/null
+++ b/packages/extension/src/providers/massa/networks/buildnet.ts
@@ -0,0 +1,19 @@
+import { NetworkNames } from '@enkryptcom/types';
+import { MassaNetwork, createMassaNetworkOptions } from './massa-base';
+import { CHAIN_ID, PublicApiUrl } from '@massalabs/massa-web3';
+
+const buildnetOptions = createMassaNetworkOptions({
+  name: NetworkNames.MassaBuildnet,
+  name_long: 'Massa Buildnet',
+  blockExplorerTX: 'https://www.massexplo.com/tx/[[txHash]]?network=buildnet',
+  blockExplorerAddr:
+    'https://www.massexplo.com/address/[[address]]?network=buildnet',
+  isTestNetwork: true,
+  node: PublicApiUrl.Buildnet,
+  chainId: CHAIN_ID.Buildnet,
+  coingeckoID: 'massa',
+});
+
+const buildnet = new MassaNetwork(buildnetOptions);
+
+export default buildnet;
diff --git a/packages/extension/src/providers/massa/networks/icons/Massa_logo.webp b/packages/extension/src/providers/massa/networks/icons/Massa_logo.webp
new file mode 100644
index 000000000..8ab091f59
Binary files /dev/null and b/packages/extension/src/providers/massa/networks/icons/Massa_logo.webp differ
diff --git a/packages/extension/src/providers/massa/networks/index.ts b/packages/extension/src/providers/massa/networks/index.ts
new file mode 100644
index 000000000..b14e25172
--- /dev/null
+++ b/packages/extension/src/providers/massa/networks/index.ts
@@ -0,0 +1,8 @@
+import mainnet from './mainnet';
+import buildnet from './buildnet';
+import { NetworkNames } from '@enkryptcom/types';
+
+export default {
+  [NetworkNames.Massa]: mainnet,
+  [NetworkNames.MassaBuildnet]: buildnet,
+};
diff --git a/packages/extension/src/providers/massa/networks/mainnet.ts b/packages/extension/src/providers/massa/networks/mainnet.ts
new file mode 100644
index 000000000..adb111121
--- /dev/null
+++ b/packages/extension/src/providers/massa/networks/mainnet.ts
@@ -0,0 +1,18 @@
+import { NetworkNames } from '@enkryptcom/types';
+import { CHAIN_ID, PublicApiUrl } from '@massalabs/massa-web3';
+import { MassaNetwork, createMassaNetworkOptions } from './massa-base';
+
+const mainnetOptions = createMassaNetworkOptions({
+  name: NetworkNames.Massa,
+  name_long: 'Massa',
+  blockExplorerTX: 'https://explorer.massa.net/operation/[[txHash]]',
+  blockExplorerAddr: 'https://explorer.massa.net/address/[[address]]',
+  isTestNetwork: false,
+  node: PublicApiUrl.Mainnet,
+  chainId: CHAIN_ID.Mainnet,
+  coingeckoID: 'massa',
+});
+
+const mainnet = new MassaNetwork(mainnetOptions);
+
+export default mainnet;
diff --git a/packages/extension/src/providers/massa/networks/massa-base.ts b/packages/extension/src/providers/massa/networks/massa-base.ts
new file mode 100644
index 000000000..1158a30eb
--- /dev/null
+++ b/packages/extension/src/providers/massa/networks/massa-base.ts
@@ -0,0 +1,289 @@
+import { NetworkNames } from '@enkryptcom/types';
+import { BaseNetwork } from '@/types/base-network';
+import MassaAPI from '../libs/api';
+import { SignerType } from '@enkryptcom/types';
+import { ProviderName } from '@/types/provider';
+import { MassaNetworkOptions } from '../types';
+import { Activity } from '@/types/activity';
+import { AssetsType } from '@/types/provider';
+import { fromBase } from '@enkryptcom/utils';
+import { formatFloatingPointValue } from '@/libs/utils/number-formatter';
+import MarketData from '@/libs/market-data';
+import BigNumber from 'bignumber.js';
+import icon from './icons/Massa_logo.webp';
+import createIcon from '../../ethereum/libs/blockies';
+import { TokensState } from '@/libs/tokens-state';
+import {
+  CustomErc20Token,
+  CustomMassaToken,
+  TokenType,
+} from '@/libs/tokens-state/types';
+import Sparkline from '@/libs/sparkline';
+import { MassaActivity } from '../libs/activity-handlers';
+import wrapActivityHandler from '@/libs/activity-state/wrap-activity-handler';
+import { Address } from '@massalabs/massa-web3';
+
+export class MassaNetwork extends BaseNetwork {
+  chainId: bigint;
+  private activityHandler?: (
+    network: BaseNetwork,
+    address: string,
+  ) => Promise<Activity[]>;
+
+  constructor(options: MassaNetworkOptions) {
+    super(options);
+    this.chainId = options.chainId!;
+    this.activityHandler =
+      options.activityHandler || wrapActivityHandler(MassaActivity);
+  }
+
+  async getAllTokens(): Promise<any[]> {
+    return [];
+  }
+
+  async getAllTokenInfo(address: string): Promise<AssetsType[]> {
+    try {
+      // Get native MAS balance
+      const api = (await this.api()) as MassaAPI;
+      const balance = await api.getBalance(address);
+      const balanceFormatted = fromBase(balance, this.decimals);
+      const balanceDisplayFormatted =
+        formatFloatingPointValue(balanceFormatted).value;
+
+      // Get MAS price from CoinGecko
+      let price = '0';
+      let priceChangePercentage = 0;
+      let sparklineData = '';
+
+      try {
+        if (this.coingeckoID) {
+          const marketData = new MarketData();
+          const tokenPrice = await marketData.getTokenPrice(this.coingeckoID);
+          const marketInfos = await marketData.getMarketData([
+            this.coingeckoID,
+          ]);
+          const marketInfo = marketInfos[0];
+
+          if (tokenPrice) {
+            price = tokenPrice;
+          }
+
+          if (marketInfo) {
+            priceChangePercentage = marketInfo.price_change_percentage_24h || 0;
+            if (marketInfo.sparkline_in_24h?.price) {
+              // Convert sparkline data to string format expected by UI
+              sparklineData = JSON.stringify(
+                marketInfo.sparkline_in_24h.price.slice(-25),
+              ); // Last 25 points
+            }
+          }
+        }
+      } catch (priceError) {
+        // Price data not available, continue with default values
+      }
+
+      // Calculate USD values
+      const balanceUSD = new BigNumber(balanceDisplayFormatted)
+        .times(price)
+        .toNumber();
+      const balanceUSDf = new BigNumber(balanceDisplayFormatted)
+        .times(price)
+        .toString();
+      const priceFormatted = formatFloatingPointValue(price).value;
+
+      const nativeTokenAsset: AssetsType = {
+        name: this.currencyNameLong,
+        symbol: this.currencyName,
+        icon: this.icon,
+        balance,
+        balancef: balanceDisplayFormatted,
+        balanceUSD,
+        balanceUSDf,
+        value: price,
+        valuef: priceFormatted,
+        decimals: this.decimals,
+        sparkline: sparklineData,
+        priceChangePercentage,
+      };
+
+      const assets = [nativeTokenAsset];
+
+      // Add custom tokens support
+      const tokensState = new TokensState();
+      const customTokens = await tokensState
+        .getTokensByNetwork(this.name)
+        .then(tokens => {
+          const erc20Tokens = tokens.filter(token => {
+            if (token.type !== TokenType.ERC20) {
+              return false;
+            }
+
+            for (const a of assets) {
+              if (
+                a.contract &&
+                (token as CustomMassaToken).address &&
+                a.contract.toLowerCase() ===
+                  (token as CustomMassaToken).address.toLowerCase()
+              ) {
+                return false;
+              }
+            }
+
+            return true;
+          }) as CustomMassaToken[];
+
+          return erc20Tokens.map(
+            ({ name, symbol, address, icon, decimals }) => {
+              return {
+                name,
+                symbol,
+                contract: address,
+                icon,
+                decimals,
+                balance: '0', // Will be fetched below
+              };
+            },
+          );
+        });
+
+      // Fetch balances for custom tokens
+      const balancePromises = customTokens.map(async token => {
+        try {
+          return api.getBalanceMRC20(address, token.contract);
+        } catch (error) {
+          return '0';
+        }
+      });
+
+      const balances = await Promise.all(balancePromises);
+
+      // Update token balances with fetched values
+      customTokens.forEach((token, index) => {
+        token.balance = balances[index];
+      });
+
+      const marketData = new MarketData();
+      const marketInfos = await marketData.getMarketInfoByContracts(
+        customTokens.map(token => token.contract.toLowerCase()),
+        this.coingeckoPlatform!,
+      );
+
+      const customAssets: AssetsType[] = customTokens.map(token => {
+        const asset: AssetsType = {
+          name: token.name,
+          symbol: token.symbol,
+          balance: token.balance ?? '0',
+          balancef: formatFloatingPointValue(
+            fromBase(token.balance ?? '0', token.decimals),
+          ).value,
+          contract: token.contract,
+          balanceUSD: 0,
+          balanceUSDf: '0',
+          value: '0',
+          valuef: '0',
+          decimals: token.decimals,
+          sparkline: '',
+          priceChangePercentage: 0,
+          icon: token.icon,
+        };
+
+        // Check if token is a stablecoin (contains DAI or USD in symbol)
+        const isStablecoin =
+          token.symbol.toUpperCase().includes('DAI') ||
+          token.symbol.toUpperCase().includes('USD');
+
+        if (isStablecoin) {
+          // Use $1 price for stablecoins
+          const usdBalance = new BigNumber(
+            fromBase(token.balance ?? '0', token.decimals),
+          ).times(1);
+          asset.balanceUSD = usdBalance.toNumber();
+          asset.balanceUSDf = usdBalance.toString();
+          asset.value = '1';
+          asset.valuef = '1';
+          asset.priceChangePercentage = 0;
+        } else {
+          // Use real market data for other tokens
+          const marketInfo = marketInfos[token.contract.toLowerCase()];
+
+          if (marketInfo) {
+            const usdBalance = new BigNumber(
+              fromBase(token.balance ?? '0', token.decimals),
+            ).times(marketInfo.current_price ?? 0);
+            asset.balanceUSD = usdBalance.toNumber();
+            asset.balanceUSDf = usdBalance.toString();
+            asset.value = marketInfo.current_price?.toString() ?? '0';
+            asset.valuef = marketInfo.current_price?.toString() ?? '0';
+            asset.sparkline = new Sparkline(
+              marketInfo.sparkline_in_24h.price,
+              25,
+            ).dataValues;
+            asset.priceChangePercentage =
+              marketInfo.price_change_percentage_24h_in_currency || 0;
+          }
+        }
+
+        return asset;
+      });
+
+      return [...assets, ...customAssets];
+    } catch (error) {
+      return [];
+    }
+  }
+
+  async getAllActivity(address: string): Promise<Activity[]> {
+    if (this.activityHandler) {
+      return this.activityHandler(this, address);
+    }
+    return [];
+  }
+
+  isValidAddress = (address: string): boolean => {
+    try {
+      Address.fromString(address);
+    } catch (error) {
+      return false;
+    }
+    return true;
+  };
+}
+
+// Helper function to create standard Massa network options
+export function createMassaNetworkOptions(config: {
+  name: NetworkNames;
+  name_long: string;
+  blockExplorerTX: string;
+  blockExplorerAddr: string;
+  isTestNetwork: boolean;
+  node: string;
+  chainId: bigint;
+  coingeckoID?: string;
+}): MassaNetworkOptions {
+  return {
+    name: config.name,
+    name_long: config.name_long,
+    homePage: 'https://massa.net/',
+    blockExplorerTX: config.blockExplorerTX,
+    blockExplorerAddr: config.blockExplorerAddr,
+    isTestNetwork: config.isTestNetwork,
+    currencyName: 'MAS',
+    currencyNameLong: 'Massa',
+    node: config.node,
+    icon,
+    decimals: 9,
+    signer: [SignerType.ed25519mas],
+    displayAddress: (address: string) => address,
+    provider: ProviderName.massa,
+    identicon: createIcon,
+    basePath: "m/44'/632'",
+    chainId: config.chainId,
+    coingeckoID: config.coingeckoID,
+    customTokens: true,
+    api: async () => {
+      const api = new MassaAPI(config.node);
+      await api.init();
+      return api;
+    },
+  };
+}
diff --git a/packages/extension/src/providers/massa/types/index.ts b/packages/extension/src/providers/massa/types/index.ts
new file mode 100644
index 000000000..08d37ad26
--- /dev/null
+++ b/packages/extension/src/providers/massa/types/index.ts
@@ -0,0 +1,31 @@
+import { NetworkName, CHAIN_ID } from '@massalabs/massa-web3';
+import { BaseNetworkOptions } from '@/types/base-network';
+import { ToTokenData } from '@/ui/action/types/token';
+import { BaseNetwork } from '@/types/base-network';
+import { Activity } from '@/types/activity';
+
+export const MassaNetworks = NetworkName;
+
+export interface MassaNetworkOptions extends BaseNetworkOptions {
+  chainId?: (typeof CHAIN_ID)[keyof typeof CHAIN_ID];
+  activityHandler?: (
+    network: BaseNetwork,
+    address: string,
+  ) => Promise<Activity[]>;
+}
+
+export interface TxFeeInfo {
+  nativeValue: string;
+  fiatValue: string;
+  nativeSymbol: string;
+  fiatSymbol: string;
+}
+
+export interface VerifyTransactionParams {
+  fromAddress: string;
+  fromAddressName: string;
+  toAddress: string;
+  toToken: ToTokenData;
+  toTokenAddress?: string;
+  txFee: TxFeeInfo;
+}
diff --git a/packages/extension/src/providers/massa/ui/index.ts b/packages/extension/src/providers/massa/ui/index.ts
new file mode 100644
index 000000000..9d0e66586
--- /dev/null
+++ b/packages/extension/src/providers/massa/ui/index.ts
@@ -0,0 +1,9 @@
+import { ProviderName, UIExportOptions } from '@/types/provider';
+import getRoutes from './routes';
+
+const uiExport: UIExportOptions = {
+  providerName: ProviderName.massa,
+  routes: getRoutes(ProviderName.massa),
+};
+
+export default uiExport;
diff --git a/packages/extension/src/providers/massa/ui/libs/signer.ts b/packages/extension/src/providers/massa/ui/libs/signer.ts
new file mode 100644
index 000000000..69dab7896
--- /dev/null
+++ b/packages/extension/src/providers/massa/ui/libs/signer.ts
@@ -0,0 +1,132 @@
+import { InternalMethods, InternalOnMessageResponse } from '@/types/messenger';
+import { bufferToHex, hexToBuffer } from '@enkryptcom/utils';
+import sendUsingInternalMessengers from '@/libs/messenger/internal-messenger';
+import { BaseNetwork } from '@/types/base-network';
+import { EnkryptAccount } from '@enkryptcom/types';
+import {
+  Address,
+  CallOperation,
+  MAX_GAS_CALL,
+  OperationManager,
+  OperationType,
+  PublicKey,
+  TransferOperation,
+} from '@massalabs/massa-web3';
+import { MassaNetworkOptions } from '../../types';
+
+export interface MassaTransactionOptions {
+  account: EnkryptAccount;
+  network: BaseNetwork;
+  payload: {
+    type: OperationType;
+    from: string;
+    to: string;
+    amount: string;
+    fee: string;
+    expirePeriod: number;
+    data?: string;
+    maxGas?: string;
+    coins?: string;
+    func?: string;
+  };
+}
+
+export interface MassaSignedTransaction {
+  from: string;
+  to: string;
+  amount: string;
+  fee: string;
+  expirePeriod: number;
+  signature: string;
+  publicKey: string;
+  serializedHex: string;
+}
+
+/**
+ * Sign a Massa transaction
+ */
+export const MassaTransactionSigner = (
+  options: MassaTransactionOptions,
+): Promise<MassaSignedTransaction> => {
+  const { account, payload, network } = options;
+
+  let operationDetails: TransferOperation | CallOperation;
+  if (payload.type === OperationType.Transaction) {
+    operationDetails = {
+      type: payload.type,
+      amount: BigInt(payload.amount),
+      recipientAddress: Address.fromString(payload.to),
+      fee: BigInt(payload.fee),
+      expirePeriod: payload.expirePeriod,
+    };
+  } else if (payload.type === OperationType.CallSmartContractFunction) {
+    if (!payload.func) {
+      throw new Error('Invalid payload, target function is required');
+    }
+    operationDetails = {
+      type: payload.type,
+      parameter: hexToBuffer(payload.data ?? ''),
+      fee: BigInt(payload.fee),
+      expirePeriod: payload.expirePeriod,
+      maxGas: BigInt(payload.maxGas ?? MAX_GAS_CALL),
+      coins: BigInt(payload.coins ?? '0'),
+      address: payload.to,
+      func: payload.func,
+    };
+  } else {
+    throw new Error(`Unsupported operation type: ${payload.type}`);
+  }
+
+  const chainId = (network as MassaNetworkOptions).chainId;
+  const publicKey = PublicKey.fromString(account.publicKey);
+  const serialized = OperationManager.canonicalize(
+    chainId!,
+    operationDetails,
+    publicKey,
+  );
+  const bufferTosign = bufferToHex(serialized);
+
+  return sendUsingInternalMessengers({
+    method: InternalMethods.sign,
+    params: [bufferTosign, account],
+  }).then(res => {
+    if (res.error) {
+      return Promise.reject(res);
+    } else {
+      const signature = JSON.parse(res.result as string) || '';
+
+      const signedTx: MassaSignedTransaction = {
+        ...payload,
+        signature,
+        publicKey: account.publicKey,
+        serializedHex: bufferToHex(
+          OperationManager.serialize(operationDetails),
+        ),
+      };
+
+      return signedTx;
+    }
+  });
+};
+
+/**
+ * Sign a Massa message
+ */
+export const MassaMessageSigner = (options: {
+  account: EnkryptAccount;
+  network: BaseNetwork;
+  payload: Buffer;
+}): Promise<InternalOnMessageResponse> => {
+  const { account, payload } = options;
+
+  const msgHash = bufferToHex(payload);
+  return sendUsingInternalMessengers({
+    method: InternalMethods.sign,
+    params: [msgHash, account],
+  }).then(res => {
+    if (res.error) return res;
+    return {
+      result: res.result,
+    };
+  });
+};
diff --git a/packages/extension/src/providers/massa/ui/routes/index.ts b/packages/extension/src/providers/massa/ui/routes/index.ts
new file mode 100644
index 000000000..a248cd380
--- /dev/null
+++ b/packages/extension/src/providers/massa/ui/routes/index.ts
@@ -0,0 +1,12 @@
+import { RouteRecordRaw } from 'vue-router';
+import RouteNames from './names';
+
+const routes = Object.assign({}, RouteNames);
+
+export default (namespace: string): RouteRecordRaw[] => {
+  return Object.values(routes).map(route => {
+    route.path = `/${namespace}/${route.path}`;
+    route.name = `${namespace}-${String(route.name)}`;
+    return route;
+  });
+};
diff --git a/packages/extension/src/providers/massa/ui/routes/names.ts b/packages/extension/src/providers/massa/ui/routes/names.ts
new file mode 100644
index 000000000..7ab9121ba
--- /dev/null
+++ b/packages/extension/src/providers/massa/ui/routes/names.ts
@@ -0,0 +1,16 @@
+import { RouteRecordRaw } from 'vue-router';
+
+const routes: Record<string, RouteRecordRaw> = {
+  send: {
+    path: 'send',
+    name: 'massa-send',
+    component: () => import('../send-transaction/index.vue'),
+  },
+  verify: {
+    path: 'verify',
+    name: 'massa-verify',
+    component: () => import('../send-transaction/verify-transaction/index.vue'),
+  },
+};
+
+export default routes;
diff --git a/packages/extension/src/providers/massa/ui/send-transaction/components/send-address-input.vue b/packages/extension/src/providers/massa/ui/send-transaction/components/send-address-input.vue
new file mode 100644
index 000000000..6ff6bd897
--- /dev/null
+++ b/packages/extension/src/providers/massa/ui/send-transaction/components/send-address-input.vue
@@ -0,0 +1,215 @@
+<template>
+  <div class="send-address-input" :class="{ focus: isFocus }">
+    <div class="send-address-input__avatar">
+      <img
+        v-if="isValidMassaAddress && massaAddress && identiconSrc"
+        :src="identiconSrc"
+        alt=""
+        @error="handleIdenticonError"
+      />
+      <img
+        v-else
+        :src="placeholderIdenticonSrc"
+        alt=""
+        class="send-address-input__avatar-placeholder"
+      />
+    </div>
+    <div class="send-address-input__address">
+      <p v-if="!from">To:</p>
+      <p v-else>From:</p>
+      <input
+        ref="addressInput"
+        v-model="address"
+        type="text"
+        :disabled="disableDirectInput"
+        placeholder="Enter Massa address"
+        :style="{
+          color: massaAddress && !isValidMassaAddress ? 'red' : 'black',
+        }"
+        @focus="changeFocus"
+        @blur="changeFocus"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { replaceWithEllipsis } from '@/ui/action/utils/filters';
+import { computed, ref } from 'vue';
+import { PropType } from 'vue';
+import { Address } from '@massalabs/massa-web3';
+import { MassaNetwork } from '../../../networks/massa-base';
+
+const isFocus = ref<boolean>(false);
+const addressInput = ref<HTMLInputElement>();
+const identiconError = ref<boolean>(false);
+
+const pasteFromClipboard = () => {
+  addressInput.value?.focus();
+  document.execCommand('paste');
+};
+defineExpose({ addressInput, pasteFromClipboard });
+
+const props = defineProps({
+  value: {
+    type: String,
+    default: () => {
+      return '';
+    },
+  },
+  network: {
+    type: Object as PropType<MassaNetwork>,
+    default: () => ({}),
+  },
+  from: {
+    type: Boolean,
+    default: false,
+  },
+  disableDirectInput: Boolean,
+});
+
+const emit = defineEmits<{
+  (e: 'update:inputAddress', address: string): void;
+  (e: 'toggle:showContacts', show: boolean): void;
+}>();
+
+const massaAddress = computed(() => {
+  return props.value;
+});
+
+const isValidMassaAddress = computed(() => {
+  if (!massaAddress.value || massaAddress.value.trim() === '') return false;
+  return props.network.isValidAddress(massaAddress.value);
+});
+
+const identiconSrc = computed(() => {
+  if (
+    !isValidMassaAddress.value ||
+    !massaAddress.value ||
+    identiconError.value
+  ) {
+    return null;
+  }
+
+  try {
+    if (props.network && props.network.identicon) {
+      return props.network.identicon(massaAddress.value);
+    }
+  } catch (error) {
+    console.error('Error generating identicon:', error);
+    identiconError.value = true;
+  }
+
+  return null;
+});
+
+const placeholderIdenticonSrc = computed(() => {
+  if (props.network && props.network.identicon) {
+    return props.network.identicon(
+      '000000000000000000000000000000000000000000000000000000000000000000',
+    );
+  }
+  return '';
+});
+
+const address = computed({
+  get: () => {
+    if (!massaAddress.value || massaAddress.value.trim() === '') return '';
+    return isFocus.value
+      ? massaAddress.value
+      : replaceWithEllipsis(massaAddress.value, 6, 6);
+  },
+  set: value => emit('update:inputAddress', value),
+});
+
+const changeFocus = (val: FocusEvent) => {
+  isFocus.value = val.type === 'focus';
+  if (isFocus.value) emit('toggle:showContacts', isFocus.value);
+};
+
+const handleIdenticonError = () => {
+  console.error('Failed to load identicon for address:', massaAddress.value);
+  identiconError.value = true;
+};
+</script>
+
+<style lang="less">
+@import '@action/styles/theme.less';
+
+.send-address-input {
+  height: 64px;
+  background: #ffffff;
+  margin: 12px 32px 8px 32px;
+  box-sizing: border-box;
+  border: 1px solid @gray02;
+  box-sizing: border-box;
+  border-radius: 10px;
+  width: calc(~'100% - 64px');
+  padding: 16px;
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  flex-direction: row;
+  position: relative;
+
+  &.focus {
+    border: 2px solid @primary;
+    width: calc(~'100% - 62px');
+    margin: 12px 31px 8px 31px;
+  }
+
+  &__avatar {
+    background: @buttonBg;
+    box-shadow: inset 0px 0px 1px rgba(0, 0, 0, 0.16);
+    width: 32px;
+    height: 32px;
+    border-radius: 100%;
+    overflow: hidden;
+    margin-right: 12px;
+
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+  &__address {
+    p {
+      font-style: normal;
+      font-weight: 400;
+      font-size: 12px;
+      line-height: 16px;
+      letter-spacing: 0.5px;
+      color: @secondaryLabel;
+      margin: 0;
+    }
+
+    input {
+      width: 290px;
+      height: 24px;
+      font-style: normal;
+      font-weight: 400;
+      font-size: 16px;
+      line-height: 24px;
+      letter-spacing: 0.25px;
+      color: @primaryLabel;
+      border: 0 none;
+      outline: none;
+      padding: 0;
+    }
+  }
+
+  &__arrow {
+    position: absolute;
+    font-size: 0;
+    cursor: pointer;
+    padding: 4px;
+    right: 8px;
+    top: 16px;
+  }
+
+  &__avatar-placeholder {
+    opacity: 0.6;
+  }
+}
+</style>
diff --git a/packages/extension/src/providers/massa/ui/send-transaction/components/send-token-select.vue b/packages/extension/src/providers/massa/ui/send-transaction/components/send-token-select.vue
new file mode 100644
index 000000000..998a8de9e
--- /dev/null
+++ b/packages/extension/src/providers/massa/ui/send-transaction/components/send-token-select.vue
@@ -0,0 +1,118 @@
+<template>
+  <a class="send-token-select" @click="emit('update:toggleTokenSelect')">
+    <div class="send-token-select__image">
+      <img :src="token.icon" alt="" />
+    </div>
+    <div class="send-token-select__info">
+      <h5>{{ token.name }}</h5>
+      <p>
+        {{ balance ? $filters.formatFloatingPointValue(balance).value : '~' }}
+        <span>{{ token.symbol }}</span>
+      </p>
+    </div>
+
+    <div class="send-token-select__arrow">
+      <switch-arrow />
+    </div>
+  </a>
+</template>
+
+<script setup lang="ts">
+import { computed, PropType } from 'vue';
+import SwitchArrow from '@action/icons/header/switch_arrow.vue';
+import { fromBase } from '@enkryptcom/utils';
+import { AssetsType } from '@/types/provider';
+
+const emit = defineEmits<{
+  (e: 'update:toggleTokenSelect'): void;
+}>();
+
+const props = defineProps({
+  token: {
+    type: Object as PropType<Partial<AssetsType>>,
+    default: () => {
+      return {};
+    },
+  },
+});
+
+const balance = computed(() =>
+  props.token && props.token.balance
+    ? fromBase(props.token.balance, props.token.decimals ?? 9)
+    : undefined,
+);
+</script>
+
+<style lang="less">
+@import '@action/styles/theme.less';
+
+.send-token-select {
+  height: 64px;
+  background: #ffffff;
+  margin: 0 32px 8px 32px;
+  box-sizing: border-box;
+  border: 1px solid @gray02;
+  box-sizing: border-box;
+  border-radius: 10px;
+  width: calc(~'100% - 64px');
+  padding: 16px;
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  flex-direction: row;
+  position: relative;
+  cursor: pointer;
+  text-decoration: none;
+
+  &__image {
+    background: @buttonBg;
+    box-shadow: inset 0px 0px 1px rgba(0, 0, 0, 0.16);
+    width: 32px;
+    height: 32px;
+    border-radius: 100%;
+    overflow: hidden;
+    margin-right: 12px;
+
+    img {
+      width: 100%;
+      height: 100%;
+      object-fit: contain;
+    }
+  }
+
+  &__info {
+    h5 {
+      font-style: normal;
+      font-weight: 400;
+      font-size: 16px;
+      line-height: 24px;
+      color: @primaryLabel;
+      width: 290px;
+      margin: 0 0 1px 0;
+    }
+
+    p {
+      font-style: normal;
+      font-weight: 400;
+      font-size: 12px;
+      line-height: 16px;
+      letter-spacing: 0.5px;
+      color: @secondaryLabel;
+      margin: 0;
+      width: 290px;
+
+      span {
+        font-variant: small-caps;
+      }
+    }
+  }
+
+  &__arrow {
+    position: absolute;
+    font-size: 0;
+    padding: 4px;
+    right: 8px;
+    top: 16px;
+  }
+}
+</style>
diff --git a/packages/extension/src/providers/massa/ui/send-transaction/index.vue b/packages/extension/src/providers/massa/ui/send-transaction/index.vue
new file mode 100644
index 000000000..81390c31b
--- /dev/null
+++ b/packages/extension/src/providers/massa/ui/send-transaction/index.vue
@@ -0,0 +1,673 @@
+<template>
+  <div class="container">
+    <div class="send-transaction">
+      <send-header
+        :is-send-token="true"
+        :is-nft-available="false"
+        @close="close"
+        @toggle-type="toggleSelector"
+      />
+
+      <send-address-input
+        ref="addressInputFrom"
+        :from="true"
+        :value="addressFrom"
+        :network="network"
+        :disable-direct-input="true"
+        @click="toggleSelectContactFrom(true)"
+        @update:input-address="inputAddressFrom"
+        @toggle:show-contacts="toggleSelectContactFrom"
+      />
+
+      <send-from-contacts-list
+        :show-accounts="isOpenSelectContactFrom"
+        :account-info="accountInfo"
+        :address="addressFrom"
+        :network="network"
+        @selected:account="selectAccountFrom"
+        @close="toggleSelectContactFrom"
+      />
+
+      <send-address-input
+        ref="addressInputTo"
+        :value="addressTo"
+        :network="network"
+        @update:input-address="inputAddressTo"
+        @toggle:show-contacts="toggleSelectContactTo"
+      />
+
+      <send-contacts-list
+        :show-accounts="isOpenSelectContactTo"
+        :account-info="accountInfo"
+        :address="addressTo"
+        :network="network"
+        @selected:account="selectAccountTo"
+        @update:paste-from-clipboard="addressInputTo.pasteFromClipboard()"
+        @close="toggleSelectContactTo"
+      />
+
+      <send-token-select
+        v-if="selectedAsset"
+        :token="selectedAsset"
+        @update:toggle-token-select="toggleSelectToken"
+      />
+
+      <assets-select-list
+        v-model="isOpenSelectToken"
+        :is-send="true"
+        :assets="accountAssets"
+        :is-loading="isLoadingAssets"
+        @update:select-asset="selectToken"
+      />
+
+      <send-input-amount
+        :amount="amount"
+        :fiat-value="tokenPrice"
+        :has-enough-balance="hasEnoughBalance"
+        :show-max="true"
+        @update:input-amount="inputAmount"
+        @update:input-set-max="setMaxValue"
+      />
+
+      <send-alert
+        v-show="!hasEnoughBalance && amount && parseFloat(amount) > 0"
+        :native-symbol="selectedAsset?.symbol || network.name"
+        :price="amountFiatValue"
+        :is-balance-zero="
+          selectedAsset
+            ? parseFloat(
+                fromBase(selectedAsset.balance || '0', selectedAsset.decimals),
+              ) === 0
+            : parseFloat(accountBalance) === 0
+        "
+        :native-value="insufficientAmount"
+        :decimals="selectedAsset?.decimals || 9"
+        :not-enough="!hasEnoughBalance"
+      />
+
+      <div class="fee-input-container">
+        <label>Fee (MAS)</label>
+        <input
+          v-model="fee"
+          type="number"
+          placeholder="0.01"
+          class="fee-input"
+          step="0.000000001"
+          min="0"
+        />
+        <div class="fee-info">Minimal fee from network</div>
+      </div>
+
+      <div class="send-transaction__buttons">
+        <div class="send-transaction__buttons-cancel">
+          <base-button title="Cancel" :click="close" :no-background="true" />
+        </div>
+        <div class="send-transaction__buttons-send">
+          <base-button
+            :title="sendButtonTitle"
+            :click="sendAction"
+            :disabled="!isInputsValid"
+          />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted, PropType, computed, watch, nextTick } from 'vue';
+import { useRouter } from 'vue-router';
+import SendHeader from '@/providers/common/ui/send-transaction/send-header.vue';
+import SendAddressInput from './components/send-address-input.vue';
+import SendContactsList from '@/providers/common/ui/send-transaction/send-contacts-list.vue';
+import SendFromContactsList from '@/providers/common/ui/send-transaction/send-from-contacts-list.vue';
+import SendInputAmount from '@/providers/common/ui/send-transaction/send-input-amount.vue';
+import SendTokenSelect from './components/send-token-select.vue';
+import AssetsSelectList from '@action/views/assets-select-list/index.vue';
+import BaseButton from '@action/components/base-button/index.vue';
+import SendAlert from '@/providers/common/ui/send-transaction/send-alert.vue';
+import { AccountsHeaderData } from '@action/types/account';
+import { BaseNetwork } from '@/types/base-network';
+import BigNumber from 'bignumber.js';
+import { fromBase, toBase, isValidDecimals } from '@enkryptcom/utils';
+import { isNumericPositive } from '@/libs/utils/number-formatter';
+import { Address, formatMas } from '@massalabs/massa-web3';
+import MassaAPI from '../../libs/api';
+import PublicKeyRing from '@/libs/keyring/public-keyring';
+import { AssetsType } from '@/types/provider';
+
+import { VerifyTransactionParams, TxFeeInfo } from '../../types';
+import { routes as RouterNames } from '@/ui/action/router';
+import { SignerType } from '@enkryptcom/types';
+
+interface AccountInfo {
+  address: string;
+  balance: string;
+  name: string;
+  publicKey: string;
+  type: string;
+}
+
+const props = defineProps({
+  network: {
+    type: Object as PropType<BaseNetwork>,
+    default: () => ({}),
+  },
+  accountInfo: {
+    type: Object as PropType<AccountsHeaderData>,
+    default: () => ({}),
+  },
+});
+
+const router = useRouter();
+const addressInputTo = ref();
+const addressInputFrom = ref();
+const amount = ref<string>('');
+const fee = ref<string>('0.01');
+const addressTo = ref<string>('');
+const addressFrom = ref<string>('');
+const isOpenSelectContactTo = ref<boolean>(false);
+const isOpenSelectContactFrom = ref<boolean>(false);
+const isOpenSelectToken = ref<boolean>(false);
+const isLoadingAssets = ref<boolean>(false);
+const keyRing = new PublicKeyRing();
+
+const account = computed(() => {
+  // Create a proper AccountInfo object from AccountsHeaderData
+  if (props.accountInfo?.selectedAccount) {
+    const selectedIndex = props.accountInfo.activeAccounts.findIndex(
+      acc => acc.address === props.accountInfo.selectedAccount?.address,
+    );
+    const balance =
+      selectedIndex >= 0
+        ? props.accountInfo.activeBalances[selectedIndex] || '0'
+        : '0';
+
+    return {
+      address: props.accountInfo.selectedAccount.address,
+      balance: balance,
+      name: props.accountInfo.selectedAccount.name,
+      publicKey: props.accountInfo.selectedAccount.publicKey || '',
+      type: props.accountInfo.selectedAccount.walletType || '',
+    };
+  }
+  return {
+    address: '',
+    balance: '0',
+    name: '',
+    publicKey: '',
+    type: '',
+  };
+});
+
+const network = computed(() => {
+  return props.network;
+});
+
+const accountBalance = computed(() => {
+  return account.value.balance;
+});
+
+const masTokenInfo = ref<AssetsType | null>(null);
+const selectedAsset = ref<AssetsType | null>(null);
+const accountAssets = ref<any[]>([]);
+
+const tokenPrice = computed(() => {
+  return selectedAsset.value?.value || '0';
+});
+
+const amountFiatValue = computed(() => {
+  if (
+    !isNumericPositive(sendAmount.value) ||
+    parseFloat(sendAmount.value) <= 0
+  ) {
+    return '0';
+  }
+  // Calculate fiat value using the selected token price
+  const sendAmountBN = new BigNumber(sendAmount.value);
+  const fiatValueBN = sendAmountBN.times(tokenPrice.value);
+  return fiatValueBN.toFixed(2);
+});
+
+const feeFiatValue = computed(() => {
+  if (!isNumericPositive(fee.value) || parseFloat(fee.value) <= 0) {
+    return '0';
+  }
+
+  // Calculate fiat value using the cached MAS price
+  const amountBN = new BigNumber(fee.value);
+  const masPrice = masTokenInfo.value?.value || '0';
+  const valueBN = amountBN.times(masPrice);
+
+  return valueBN.toFixed(2);
+});
+
+const sendAmount = computed(() => {
+  if (amount.value && amount.value !== '') return amount.value;
+  return '0';
+});
+
+const hasEnoughBalance = computed(() => {
+  if (!isNumericPositive(sendAmount.value) || !selectedAsset.value) {
+    return true;
+  }
+
+  const amount = BigInt(toBase(sendAmount.value, selectedAsset.value.decimals));
+  const tokenBalance = BigInt(selectedAsset.value.balance || '0');
+  const masBalance = BigInt(toBase(accountBalance.value, 9));
+  const feeRaw = BigInt(toBase(fee.value, 9));
+
+  // For MAS token, check if amount + fee <= balance
+  if (selectedAsset.value.symbol === 'MAS') {
+    return amount + feeRaw <= tokenBalance;
+  } else if (masBalance < feeRaw) {
+    return false;
+  }
+
+  return amount <= tokenBalance;
+});
+
+const insufficientAmount = computed(() => {
+  if (!isNumericPositive(sendAmount.value) || !selectedAsset.value) {
+    return '0';
+  }
+
+  // Convert all values to base units (smallest unit) for comparison
+  const amountBase = toBase(sendAmount.value, selectedAsset.value.decimals);
+  const balanceBase = selectedAsset.value.balance || '0'; // balance is already in base units
+  const feeBase = toBase(fee.value, 9); // Fee is always in MAS
+
+  const amountNum = BigInt(amountBase);
+  const balanceNum = BigInt(balanceBase);
+  const feeNum = BigInt(feeBase);
+
+  // For MAS token, check if amount + fee <= balance
+  if (selectedAsset.value.symbol === 'MAS') {
+    const totalNeeded = amountNum + feeNum;
+    if (totalNeeded > balanceNum) {
+      const insufficientBase = totalNeeded - balanceNum;
+      return fromBase(insufficientBase.toString(), 9);
+    }
+  } else {
+    // For other tokens, only check if amount <= balance
+    if (amountNum > balanceNum) {
+      const insufficientBase = amountNum - balanceNum;
+      return fromBase(
+        insufficientBase.toString(),
+        selectedAsset.value.decimals,
+      );
+    }
+  }
+  return '0';
+});
+
+const sendButtonTitle = computed(() => {
+  let title = 'Send';
+  if (
+    isNumericPositive(sendAmount.value) &&
+    parseFloat(sendAmount.value) > 0 &&
+    selectedAsset.value
+  ) {
+    title = 'Send ' + sendAmount.value + ' ' + selectedAsset.value.symbol;
+  }
+  return title;
+});
+
+const isInputsValid = computed<boolean>(() => {
+  // First check if address is provided
+  if (!addressTo.value || addressTo.value.trim() === '') {
+    return false;
+  }
+
+  // Check if address is valid
+  try {
+    Address.fromString(addressTo.value);
+  } catch (error) {
+    return false;
+  }
+
+  // Check if a token is selected
+  if (!selectedAsset.value) {
+    return false;
+  }
+
+  // Check if amount has valid decimals for the selected token
+  if (!isValidDecimals(sendAmount.value, selectedAsset.value.decimals)) {
+    return false;
+  }
+
+  // Check if amount is a valid number
+  const amountNum = parseFloat(sendAmount.value);
+  if (isNaN(amountNum)) {
+    return false;
+  }
+
+  // Check if amount is greater than 0
+  if (amountNum <= 0) {
+    return false;
+  }
+
+  const result = hasEnoughBalance.value;
+  return result;
+});
+
+// Watch for address changes to update token info
+watch(addressFrom, () => {
+  updateMasTokenInfo();
+});
+
+onMounted(async () => {
+  const currentAccount = account.value;
+  if (currentAccount?.address && !addressFrom.value) {
+    addressFrom.value = currentAccount.address;
+  } else {
+    const accounts = await keyRing.getAccounts([SignerType.ed25519mas]);
+    addressFrom.value = accounts[0].address;
+  }
+
+  // Fetch minimal fee from the network
+  try {
+    const api = (await network.value.api()) as MassaAPI;
+    const minimalFeeBase = await api.getMinimalFee();
+    const minimalFee = formatMas(BigInt(minimalFeeBase));
+    fee.value = minimalFee;
+  } catch (error) {
+    // Keep default fee of 0.01 if API call fails
+  }
+
+  // Fetch MAS token info and load assets
+  await updateMasTokenInfo();
+  await loadAccountAssets();
+});
+
+const updateAccountBalance = async () => {
+  if (addressFrom.value) {
+    try {
+      const api = (await network.value.api()) as MassaAPI;
+      const balance = await api.getBalance(addressFrom.value);
+      // Update the account object with the new balance
+      if (account.value) {
+        account.value.balance = balance;
+      }
+    } catch (error) {}
+  }
+};
+
+const updateMasTokenInfo = async () => {
+  if (!addressFrom.value) return;
+
+  try {
+    const tokenInfos = await network.value.getAllTokenInfo(addressFrom.value);
+    masTokenInfo.value =
+      tokenInfos.find((t: AssetsType) => t.symbol === 'MAS') || null;
+  } catch (error) {
+    console.error('Failed to fetch MAS token info:', error);
+  }
+};
+
+const loadAccountAssets = async () => {
+  if (!addressFrom.value) return;
+
+  try {
+    isLoadingAssets.value = true;
+    const tokenInfos = await network.value.getAllTokenInfo(addressFrom.value);
+
+    // Add price field to AssetsType objects for compatibility with AssetsSelectList
+    const tokensWithPrice = tokenInfos.map((token: AssetsType) => ({
+      ...token,
+      price: token.value, // Use value field as price for USD display
+    }));
+
+    accountAssets.value = tokensWithPrice;
+
+    // Set MAS as default selected token (keep as AssetsType for selectedAsset)
+    const masToken = tokenInfos.find((t: AssetsType) => t.symbol === 'MAS');
+    if (masToken) {
+      selectedAsset.value = masToken;
+    }
+  } catch (error) {
+    console.error('Failed to load account assets:', error);
+  } finally {
+    isLoadingAssets.value = false;
+  }
+};
+
+const close = () => {
+  router.go(-1);
+};
+
+const inputAddressTo = (text: string) => {
+  addressTo.value = text;
+};
+
+const inputAddressFrom = (text: string) => {
+  addressFrom.value = text;
+};
+
+const toggleSelectContactTo = (open: boolean) => {
+  isOpenSelectContactTo.value = open;
+};
+
+const toggleSelectContactFrom = (open: boolean) => {
+  isOpenSelectContactFrom.value = open;
+};
+
+const selectAccountTo = (account: string) => {
+  addressTo.value = account;
+  isOpenSelectContactTo.value = false;
+};
+
+const selectAccountFrom = (account: string) => {
+  addressFrom.value = account;
+  isOpenSelectContactFrom.value = false;
+  // Update the account balance when selecting a different account
+  updateAccountBalance();
+  // Update MAS token info for price calculation
+  updateMasTokenInfo();
+  // Reload assets for the new account
+  loadAccountAssets();
+};
+
+const inputAmount = (inputAmount: string) => {
+  if (inputAmount === '') {
+    inputAmount = '0';
+  }
+  const inputAmountBn = new BigNumber(inputAmount);
+  amount.value = inputAmountBn.lt(0) ? '0' : inputAmount;
+};
+
+const setMaxValue = () => {
+  if (!selectedAsset.value) return;
+
+  const balanceBase = selectedAsset.value.balance || '0'; // balance is already in base units
+  const feeBase = toBase(fee.value, 9); // Fee is always in MAS
+
+  const balanceNum = BigInt(balanceBase);
+  const feeNum = BigInt(feeBase);
+
+  // For MAS token, subtract fee from balance
+  if (selectedAsset.value.symbol === 'MAS') {
+    const maxAmountBase = balanceNum - feeNum;
+    if (maxAmountBase > 0n) {
+      amount.value = fromBase(
+        maxAmountBase.toString(),
+        selectedAsset.value.decimals,
+      );
+    } else {
+      amount.value = '0';
+    }
+  } else {
+    // For other tokens, use full balance (fee is paid in MAS)
+    if (balanceNum > 0n) {
+      amount.value = fromBase(
+        balanceNum.toString(),
+        selectedAsset.value.decimals,
+      );
+    } else {
+      amount.value = '0';
+    }
+  }
+};
+
+const toggleSelector = (isTokenSend: boolean) => {
+  // Massa only supports token sending for now
+};
+
+const toggleSelectToken = () => {
+  isOpenSelectToken.value = !isOpenSelectToken.value;
+};
+
+const selectToken = (token: AssetsType) => {
+  selectedAsset.value = token;
+  isOpenSelectToken.value = false;
+  // Update amount input when token changes
+  amount.value = '';
+};
+
+const sendAction = async () => {
+  if (!isInputsValid.value || !selectedAsset.value) {
+    return;
+  }
+
+  try {
+    // Create verify transaction params
+    const txVerifyInfo: VerifyTransactionParams = {
+      toToken: {
+        amount: toBase(amount.value, selectedAsset.value.decimals),
+        decimals: selectedAsset.value.decimals,
+        icon: selectedAsset.value.icon,
+        symbol: selectedAsset.value.symbol,
+        valueUSD: amountFiatValue.value,
+        name: selectedAsset.value.name,
+        price: selectedAsset.value.valuef || '0',
+      },
+      toTokenAddress: selectedAsset.value.contract,
+      fromAddress: addressFrom.value,
+      fromAddressName: account.value.name,
+      txFee: {
+        nativeValue: fee.value,
+        fiatValue: feeFiatValue.value,
+        nativeSymbol: network.value.currencyName,
+        fiatSymbol: 'USD',
+      } as TxFeeInfo,
+      toAddress: addressTo.value,
+    };
+
+    // Navigate to verify transaction component
+    const routedRoute = router.resolve({
+      name: RouterNames.verify.name, // 'verify-transaction'
+      query: {
+        id: network.value.name,
+        txData: Buffer.from(JSON.stringify(txVerifyInfo), 'utf8').toString(
+          'base64',
+        ),
+      },
+    });
+
+    router.push(routedRoute);
+  } catch (error) {}
+};
+</script>
+
+<style lang="less" scoped>
+@import '@action/styles/theme.less';
+@import '@action/styles/custom-scroll.less';
+
+.container {
+  width: 100%;
+  height: 600px;
+  background-color: @white;
+  box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.16);
+  margin: 0;
+  box-sizing: border-box;
+  position: relative;
+}
+
+.send-transaction {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  position: relative;
+  padding-bottom: 100px; // Add padding to prevent content from overlapping with buttons
+
+  &__buttons {
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    padding: 0 32px 32px 32px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    flex-direction: row;
+    width: 100%;
+    box-sizing: border-box;
+    background: @white; // Ensure buttons have a solid background
+
+    &-cancel {
+      width: 170px;
+    }
+
+    &-send {
+      width: 218px;
+    }
+  }
+}
+
+.fee-input-container {
+  margin: 0 32px 8px 32px;
+  padding: 16px;
+  background: #ffffff;
+  border: 1px solid @gray02;
+  border-radius: 10px;
+  width: calc(~'100% - 64px');
+  box-sizing: border-box;
+  position: relative;
+
+  label {
+    display: block;
+    margin-bottom: 8px;
+    font-style: normal;
+    font-weight: 400;
+    font-size: 12px;
+    line-height: 16px;
+    letter-spacing: 0.5px;
+    color: @secondaryLabel;
+  }
+
+  .fee-input {
+    width: 100%;
+    height: 24px;
+    font-style: normal;
+    font-weight: 400;
+    font-size: 16px;
+    line-height: 24px;
+    letter-spacing: 0.25px;
+    color: @primaryLabel;
+    border: 0 none;
+    outline: none;
+    padding: 0;
+    background: transparent;
+    caret-color: @primary;
+
+    &::-webkit-outer-spin-button,
+    &::-webkit-inner-spin-button {
+      -webkit-appearance: none;
+      margin: 0;
+    }
+
+    &[type='number'] {
+      -moz-appearance: textfield;
+    }
+  }
+
+  .fee-info {
+    margin-top: 8px;
+    font-style: normal;
+    font-weight: 400;
+    font-size: 12px;
+    line-height: 16px;
+    letter-spacing: 0.5px;
+    color: @tertiaryLabel;
+  }
+}
+</style>
diff --git a/packages/extension/src/providers/massa/ui/send-transaction/verify-transaction/index.vue b/packages/extension/src/providers/massa/ui/send-transaction/verify-transaction/index.vue
new file mode 100644
index 000000000..9e0517baf
--- /dev/null
+++ b/packages/extension/src/providers/massa/ui/send-transaction/verify-transaction/index.vue
@@ -0,0 +1,477 @@
+<template>
+  <div class="container" :class="{ popup: isPopup }">
+    <div v-if="!!selectedNetwork" class="verify-transaction">
+      <custom-scrollbar
+        ref="verifyScrollRef"
+        class="verify-transaction__scroll-area"
+      >
+        <div class="verify-transaction__header" :class="{ popup: isPopup }">
+          <h3>Verify Transaction</h3>
+          <a v-if="!isPopup" class="verify-transaction__close" @click="close">
+            <close-icon />
+          </a>
+        </div>
+        <hardware-wallet-msg :wallet-type="account?.walletType" />
+        <p
+          class="verify-transaction__description"
+          style="color: red"
+          :class="{ popup: isPopup }"
+        >
+          {{ errorMsg }}
+        </p>
+        <p class="verify-transaction__description" :class="{ popup: isPopup }">
+          Double check the information and confirm transaction
+        </p>
+        <div
+          class="verify-transaction__info"
+          :class="{ popup: isPopup, border: isHasScroll() }"
+        >
+          <verify-transaction-network :network="network" />
+          <verify-transaction-account
+            :name="txData.fromAddressName"
+            :address="network.displayAddress(txData.fromAddress)"
+            :from="true"
+            :network="network"
+          />
+          <verify-transaction-account
+            :address="network.displayAddress(txData.toAddress)"
+            :network="network"
+          />
+          <verify-transaction-amount :token="txData.toToken" />
+          <verify-transaction-fee :fee="txData.txFee" />
+        </div>
+      </custom-scrollbar>
+
+      <div
+        class="verify-transaction__buttons"
+        :class="{ popup: isPopup, border: isHasScroll() }"
+      >
+        <div class="verify-transaction__buttons-cancel">
+          <base-button
+            title="Back"
+            :click="close"
+            :gray="true"
+            :disabled="isProcessing"
+          />
+        </div>
+        <div class="verify-transaction__buttons-send">
+          <base-button
+            title="Confirm and send"
+            :click="sendAction"
+            :disabled="isProcessing"
+          />
+        </div>
+      </div>
+    </div>
+
+    <send-process
+      v-if="isProcessing"
+      v-model="isProcessing"
+      :is-done="isSendDone"
+      :is-nft="false"
+      :to-address="txData.toAddress"
+      :network="network"
+      :token="txData.toToken"
+      :is-window-popup="isWindowPopup"
+    />
+
+    <div v-if="showOperationId && operationIdRef" class="operation-id-success">
+      <p>
+        Transaction sent!<br />Operation ID:
+        <span class="operation-id">{{ operationIdRef }}</span>
+      </p>
+      <base-button title="Close" :click="close" />
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onBeforeMount, ref, ComponentPublicInstance } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+import CloseIcon from '@action/icons/common/close-icon.vue';
+import BaseButton from '@action/components/base-button/index.vue';
+import VerifyTransactionNetwork from '@/providers/common/ui/verify-transaction/verify-transaction-network.vue';
+import VerifyTransactionAccount from '@/providers/common/ui/verify-transaction/verify-transaction-account.vue';
+import VerifyTransactionAmount from '@/providers/common/ui/verify-transaction/verify-transaction-amount.vue';
+import VerifyTransactionFee from '@/providers/common/ui/verify-transaction/verify-transaction-fee.vue';
+import HardwareWalletMsg from '@/providers/common/ui/verify-transaction/hardware-wallet-msg.vue';
+import SendProcess from '@action/views/send-process/index.vue';
+import PublicKeyRing from '@/libs/keyring/public-keyring';
+import { MassaNetworkOptions, VerifyTransactionParams } from '../../../types';
+import { DEFAULT_MASSA_NETWORK, getNetworkByName } from '@/libs/utils/networks';
+import { EnkryptAccount } from '@enkryptcom/types';
+import CustomScrollbar from '@action/components/custom-scrollbar/index.vue';
+import { BaseNetwork } from '@/types/base-network';
+import ActivityState from '@/libs/activity-state';
+import { Activity, ActivityStatus, ActivityType } from '@/types/activity';
+import { trackSendEvents } from '@/libs/metrics';
+import { SendEventType } from '@/libs/metrics/types';
+import RateState from '@/libs/rate-state';
+import { useRateStore } from '@action/store/rate-store';
+import { bufferToHex, hexToBuffer, toBase } from '@enkryptcom/utils';
+import { getCurrentContext } from '@/libs/messenger/extension';
+import { MassaTransactionSigner } from '../../libs/signer';
+import MassaAPI from '../../../libs/api';
+import {
+  Args,
+  getAbsoluteExpirePeriod,
+  OperationType,
+  StorageCost,
+} from '@massalabs/massa-web3';
+
+/** -------------------
+ * Rate
+ -------------------*/
+const rateStore = useRateStore();
+const { toggleRatePopup } = rateStore;
+
+const isSendDone = ref(false);
+const operationIdRef = ref<string | null>(null);
+const showOperationId = ref(false);
+const account = ref<EnkryptAccount>();
+const keyRing = new PublicKeyRing();
+const rateState = new RateState();
+const route = useRoute();
+const router = useRouter();
+const selectedNetwork: string = route.query.id as string;
+const txData: VerifyTransactionParams = JSON.parse(
+  Buffer.from(route.query.txData as string, 'base64').toString('utf8'),
+);
+const errorMsg = ref('');
+const isProcessing = ref(false);
+const isPopup: boolean = getCurrentContext() === 'new-window';
+const isWindowPopup = ref(false);
+const verifyScrollRef = ref<ComponentPublicInstance<HTMLElement>>();
+defineExpose({ verifyScrollRef });
+const network = ref<BaseNetwork>(DEFAULT_MASSA_NETWORK);
+
+onBeforeMount(async () => {
+  network.value = (await getNetworkByName(selectedNetwork))!;
+  account.value = await keyRing.getAccount(txData.fromAddress);
+  isWindowPopup.value = account.value.isHardware;
+  trackSendEvents(SendEventType.SendVerify, { network: network.value.name });
+});
+
+const close = () => {
+  if (getCurrentContext() === 'popup') {
+    router.go(-1);
+  } else {
+    window.close();
+  }
+};
+
+const sendAction = async () => {
+  isProcessing.value = true;
+  try {
+    // Check if this is a native MAS transfer or MRC20 token transfer
+    const isNativeTransfer = txData.toToken.symbol === 'MAS';
+
+    // Always get expirePeriod from network
+    const massaAPI = (await network.value.api()) as MassaAPI;
+    const massaClient = massaAPI.provider.client;
+    const expirePeriod = await getAbsoluteExpirePeriod(massaClient);
+    const fee = toBase(txData.txFee.nativeValue, 9);
+
+    // Get the account from the keyring
+    const fromAccount = await keyRing.getAccount(txData.fromAddress);
+    if (!fromAccount) throw new Error('No account found in keyring');
+
+    let payload: any = {
+      fee,
+      expirePeriod,
+    };
+    if (isNativeTransfer) {
+      // Prepare the transaction payload
+      payload = {
+        ...payload,
+        type: OperationType.Transaction,
+        from: txData.fromAddress,
+        to: txData.toAddress,
+        amount: txData.toToken.amount,
+      };
+    } else {
+      if (!txData.toTokenAddress) {
+        throw new Error('toTokenAddress is required');
+      }
+      // see https://github.com/massalabs/massa-standards/blob/main/smart-contracts/assembly/contracts/MRC20/MRC20.ts
+      const data = bufferToHex(
+        new Args()
+          .addString(txData.toAddress)
+          .addU256(BigInt(txData.toToken.amount))
+          .serialize(),
+      );
+      const coins = await StorageCost.MRC20BalanceCreationCost(
+        massaAPI.provider,
+        txData.toTokenAddress,
+        txData.toAddress,
+      );
+      payload = {
+        ...payload,
+        type: OperationType.CallSmartContractFunction,
+        to: txData.toTokenAddress,
+        func: 'transfer',
+        data,
+        coins: coins.toString(),
+      };
+    }
+    // Sign the transaction
+    const signedTx = await MassaTransactionSigner({
+      account: fromAccount,
+      network: network.value,
+      payload,
+    });
+
+    const operationId = await massaClient.sendOperation({
+      data: hexToBuffer(signedTx.serializedHex),
+      publicKey: fromAccount.publicKey,
+      signature: signedTx.signature,
+    });
+    operationIdRef.value = operationId;
+    isSendDone.value = true;
+    showOperationId.value = true;
+
+    trackSendEvents(SendEventType.SendComplete, {
+      network: network.value.name,
+    });
+
+    const chainId = (network.value as MassaNetworkOptions).chainId!;
+    const txActivity: Activity = {
+      from: txData.fromAddress,
+      to: txData.toAddress,
+      isIncoming: account.value?.address === txData.toAddress,
+      network: network.value.name,
+      status: ActivityStatus.pending,
+      chainId: chainId.toString(),
+      timestamp: new Date().getTime(),
+      token: {
+        decimals: txData.toToken.decimals,
+        icon: txData.toToken.icon,
+        name: txData.toToken.name,
+        symbol: txData.toToken.symbol,
+        price: txData.toToken.price,
+      },
+      type: ActivityType.transaction,
+      value: txData.toToken.amount,
+      transactionHash: operationId,
+    };
+
+    const activityState = new ActivityState();
+
+    // Store activity for both sender and receiver addresses
+    await activityState.addActivities([txActivity], {
+      address: txData.fromAddress,
+      network: network.value.name,
+    });
+
+    // Also store for receiver if it's different from sender
+    if (txData.fromAddress !== txData.toAddress) {
+      const receiverActivity = {
+        ...txActivity,
+        isIncoming: true, // Mark as incoming for receiver
+      };
+      await activityState.addActivities([receiverActivity], {
+        address: txData.toAddress,
+        network: network.value.name,
+      });
+    }
+
+    if (getCurrentContext() === 'popup') {
+      setTimeout(() => {
+        showOperationId.value = false;
+        isProcessing.value = false;
+        callToggleRate();
+        router.push({ name: 'activity', params: { id: network.value.name } });
+      }, 4000);
+    } else {
+      setTimeout(() => {
+        showOperationId.value = false;
+        isProcessing.value = false;
+        callToggleRate();
+        window.close();
+      }, 3000);
+    }
+  } catch (error) {
+    isProcessing.value = false;
+    errorMsg.value = error instanceof Error ? error.message : String(error);
+    trackSendEvents(SendEventType.SendFailed, {
+      network: network.value.name,
+      error: errorMsg.value,
+    });
+    console.error('error', error);
+  }
+};
+
+const callToggleRate = () => {
+  /**
+   * will only show the user if they haven't rated it
+   * and never been shown before
+   */
+  rateState.showPopup(true).then(show => {
+    if (show) toggleRatePopup(true);
+  });
+};
+
+const isHasScroll = () => {
+  if (verifyScrollRef.value) {
+    return verifyScrollRef.value.$el.classList.contains('ps--active-y');
+  }
+
+  return false;
+};
+</script>
+
+<style lang="less" scoped>
+@import '@action/styles/theme.less';
+@import '@action/styles/custom-scroll.less';
+
+.container {
+  width: 100%;
+  height: 600px;
+  background-color: @white;
+  box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.16);
+  margin: 0;
+  box-sizing: border-box;
+  position: relative;
+
+  &.popup {
+    box-shadow: none;
+    padding: 0 23px;
+  }
+}
+
+.verify-transaction {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  position: relative;
+
+  &__header {
+    position: relative;
+    padding: 24px 72px 12px 32px;
+
+    &.popup {
+      padding: 24px 0 12px 0;
+    }
+
+    h3 {
+      font-style: normal;
+      font-weight: 700;
+      font-size: 24px;
+      line-height: 32px;
+      color: @primaryLabel;
+      margin: 0;
+    }
+  }
+
+  &__close {
+    position: absolute;
+    top: 20px;
+    right: 24px;
+    border-radius: 8px;
+    cursor: pointer;
+    transition: background 300ms ease-in-out;
+
+    &:hover {
+      background: @black007;
+    }
+  }
+
+  &__description {
+    font-style: normal;
+    font-weight: 400;
+    font-size: 16px;
+    line-height: 24px;
+    color: @secondaryLabel;
+    padding: 4px 141px 13px 32px;
+    margin: 0;
+
+    &.popup {
+      padding: 4px 0 16px 0;
+    }
+  }
+
+  &__info {
+    border: 1px solid @gray02;
+    box-sizing: border-box;
+    border-radius: 10px;
+    margin: 0 32px 0 32px;
+
+    &.popup {
+      margin: 0;
+      margin-bottom: 56px;
+    }
+  }
+
+  &__buttons {
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    padding: 10px 32px 14px 32px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    flex-direction: row;
+    width: 100%;
+    box-sizing: border-box;
+
+    &.popup {
+      padding: 24px 0;
+      background: @white;
+      box-shadow: none !important;
+      border-top: 1px solid rgba(0, 0, 0, 0.05);
+    }
+
+    &.border {
+      box-shadow:
+        0px 0px 6px rgba(0, 0, 0, 0.05),
+        0px 0px 1px rgba(0, 0, 0, 0.25);
+    }
+
+    &-cancel {
+      width: 170px;
+    }
+
+    &-send {
+      width: 218px;
+    }
+  }
+
+  &__scroll-area {
+    position: relative;
+    margin: auto;
+    width: calc(~'100% + 53px');
+    height: calc(~'100% - 88px');
+    margin: 0;
+    padding: 0 53px 0 0 !important;
+    margin-right: -53px;
+    box-sizing: border-box;
+
+    &.ps--active-y {
+      padding-bottom: 0 !important;
+    }
+
+    & > .ps__rail-y {
+      right: 0 !important;
+    }
+  }
+}
+
+.operation-id-success {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  margin-top: 40px;
+  p {
+    font-size: 18px;
+    color: @primaryLabel;
+    text-align: center;
+    margin-bottom: 16px;
+  }
+  .operation-id {
+    font-family: monospace;
+    color: @primary;
+    word-break: break-all;
+  }
+}
+</style>
diff --git a/packages/extension/src/types/activity.ts b/packages/extension/src/types/activity.ts
index 48eb4fe84..b13efcab1 100644
--- a/packages/extension/src/types/activity.ts
+++ b/packages/extension/src/types/activity.ts
@@ -6,6 +6,7 @@ import {
   StatusOptionsResponse,
 } from '@enkryptcom/swap';
 import { ICommandResult } from '@kadena/client';
+import { OperationStatus } from '@massalabs/massa-web3';
 
 interface BTCIns {
   address: string;
@@ -91,6 +92,8 @@ interface KadenaDBInfo {
   token: string;
 }
 
+type MassaRawInfo = OperationStatus;
+
 enum ActivityStatus {
   pending = 'pending',
   success = 'success',
@@ -128,7 +131,8 @@ interface Activity {
     | BTCRawInfo
     | SwapRawInfo
     | KadenaRawInfo
-    | SOLRawInfo;
+    | SOLRawInfo
+    | MassaRawInfo;
 }
 
 export {
@@ -143,4 +147,5 @@ export {
   KadenaRawInfo,
   KadenaDBInfo,
   SOLRawInfo,
+  MassaRawInfo,
 };
diff --git a/packages/extension/src/types/base-network.ts b/packages/extension/src/types/base-network.ts
index d876a0c99..3ca1af7a2 100644
--- a/packages/extension/src/types/base-network.ts
+++ b/packages/extension/src/types/base-network.ts
@@ -8,6 +8,7 @@ import { CoingeckoPlatform, SignerType, NetworkNames } from '@enkryptcom/types';
 import { Activity } from './activity';
 import { BaseToken } from './base-token';
 import { BNType } from '@/providers/common/types';
+import MassaAPI from '../providers/massa/libs/api';
 
 export interface SubNetworkOptions {
   id: string;
@@ -38,7 +39,8 @@ export interface BaseNetworkOptions {
     | Promise<EvmAPI>
     | Promise<BitcoinAPI>
     | Promise<KadenaAPI>
-    | Promise<SolanaAPI>;
+    | Promise<SolanaAPI>
+    | Promise<MassaAPI>;
   customTokens?: boolean;
 }
 
@@ -80,7 +82,8 @@ export abstract class BaseNetwork {
     | Promise<EvmAPI>
     | Promise<BitcoinAPI>
     | Promise<KadenaAPI>
-    | Promise<SolanaAPI>;
+    | Promise<SolanaAPI>
+    | Promise<MassaAPI>;
   public customTokens: boolean;
 
   constructor(options: BaseNetworkOptions) {
diff --git a/packages/extension/src/types/provider.ts b/packages/extension/src/types/provider.ts
index 0f831c71b..b43819ba4 100644
--- a/packages/extension/src/types/provider.ts
+++ b/packages/extension/src/types/provider.ts
@@ -23,6 +23,7 @@ import {
   SubscanExtrinsicInfo,
   KadenaRawInfo,
   SOLRawInfo,
+  MassaRawInfo,
 } from './activity';
 
 export enum ProviderName {
@@ -32,6 +33,7 @@ export enum ProviderName {
   polkadot = 'polkadot',
   kadena = 'kadena',
   solana = 'solana',
+  massa = 'massa',
 }
 export enum InternalStorageNamespace {
   keyring = 'KeyRing',
@@ -68,6 +70,7 @@ export enum ProviderType {
   bitcoin,
   kadena,
   solana,
+  massa,
 }
 
 export type SendMessageHandler = (
@@ -144,6 +147,7 @@ export abstract class ProviderAPIInterface {
     | BTCRawInfo
     | KadenaRawInfo
     | SOLRawInfo
+    | MassaRawInfo
     | null
   >;
 }
diff --git a/packages/extension/src/ui/action/App.vue b/packages/extension/src/ui/action/App.vue
index 4b1b6728e..a0efffa29 100644
--- a/packages/extension/src/ui/action/App.vue
+++ b/packages/extension/src/ui/action/App.vue
@@ -211,6 +211,8 @@ const openBuyPage = () => {
       case NetworkNames.SyscoinNEVMTest:
       case NetworkNames.RolluxTest:
         return (currentNetwork.value as EvmNetwork).options.buyLink;
+      case NetworkNames.Massa:
+        return 'https://www.massa.net/get-mas';
       default:
         return `https://ccswap.myetherwallet.com/?to=${currentNetwork.value.displayAddress(
           accountHeaderData.value.selectedAccount!.address,
@@ -316,11 +318,12 @@ const setNetwork = async (network: BaseNetwork) => {
     currentSubNetwork.value = '';
   }
   const activeAccounts = await getAccountsByNetworkName(network.name);
-
   const inactiveAccounts = await kr.getAccounts(
     getOtherSigners(network.signer),
   );
+
   const selectedAddress = await domainState.getSelectedAddress();
+
   let selectedAccount = activeAccounts[0];
   if (selectedAddress) {
     const found = activeAccounts.find(acc => acc.address === selectedAddress);
diff --git a/packages/extension/src/ui/action/views/network-activity/index.vue b/packages/extension/src/ui/action/views/network-activity/index.vue
index b2f33a951..b99514968 100644
--- a/packages/extension/src/ui/action/views/network-activity/index.vue
+++ b/packages/extension/src/ui/action/views/network-activity/index.vue
@@ -68,6 +68,7 @@ import {
   SwapRawInfo,
   KadenaRawInfo,
   SOLRawInfo,
+  MassaRawInfo,
 } from '@/types/activity';
 import NetworkActivityLoading from './components/network-activity-loading.vue';
 import { ProviderName } from '@/types/provider';
@@ -79,6 +80,7 @@ import Swap, {
 } from '@enkryptcom/swap';
 import EvmAPI from '@/providers/ethereum/libs/api';
 import type Web3Eth from 'web3-eth';
+import { OperationStatus } from '@massalabs/massa-web3';
 
 const props = defineProps({
   network: {
@@ -217,6 +219,17 @@ const handleActivityUpdate = (activity: Activity, info: any, timer: any) => {
     } else {
       return; /* Give the transaction more time to be mined */
     }
+  } else if (props.network.provider === ProviderName.massa) {
+    if (!info) return;
+    const massaInfo = info as MassaRawInfo;
+    if (isActivityUpdating) return;
+    activity.status =
+      massaInfo === OperationStatus.Success ||
+      massaInfo === OperationStatus.SpeculativeSuccess
+        ? ActivityStatus.success
+        : ActivityStatus.failed;
+    activity.rawInfo = massaInfo;
+    updateActivitySync(activity).then(() => updateVisibleActivity(activity));
   }
 
   // If we're this far in then the transaction has reached a terminal status
diff --git a/packages/extension/src/ui/action/views/network-assets/components/custom-massa-token.vue b/packages/extension/src/ui/action/views/network-assets/components/custom-massa-token.vue
new file mode 100644
index 000000000..1942251af
--- /dev/null
+++ b/packages/extension/src/ui/action/views/network-assets/components/custom-massa-token.vue
@@ -0,0 +1,492 @@
+<template>
+  <div class="container">
+    <div class="add-custom-token">
+      <div class="add-custom-token__header">
+        <h3>Add a token</h3>
+        <a class="add-custom-token__close" @click="close">
+          <close-icon />
+        </a>
+      </div>
+      <div class="add-custom-token__content">
+        <div
+          class="add-custom-token__contract-input"
+          :class="{ focus: isFocus }"
+        >
+          <div class="add-custom-token__contract-input__address">
+            <p>Contract address:</p>
+            <input
+              v-model="contractAddress"
+              :class="{ invalid: !isValidAddress }"
+              type="text"
+              placeholder="Enter Massa contract address"
+              @focus="changeFocus"
+              @blur="changeFocus"
+            />
+          </div>
+        </div>
+
+        <div v-if="isValidAddress && tokenInfo">
+          <div class="add-custom-token__token-info">
+            <div class="add-custom-token__token-info__image">
+              <img
+                :src="tokenInfo.icon"
+                alt=""
+                @error="
+                  e => {
+                    (e.target as HTMLImageElement).src = props.network.icon;
+                  }
+                "
+              />
+            </div>
+            <div class="add-custom-token__token-info__info">
+              <h5 v-if="tokenInfo.name.length <= 16">{{ tokenInfo.name }}</h5>
+              <tooltip v-else :text="tokenInfo.name"
+                ><h5>{{ `${tokenInfo.name.slice(0, 12)}...` }}</h5></tooltip
+              >
+              <p>
+                {{
+                  accountBalance
+                    ? $filters.formatFloatingPointValue(
+                        fromBase(accountBalance ?? '0', tokenInfo.decimals),
+                      ).value
+                    : '~'
+                }}
+                <span v-if="tokenInfo.symbol.length <= 16">{{
+                  tokenInfo.symbol
+                }}</span>
+                <tooltip v-else :text="tokenInfo.symbol"
+                  ><span>{{
+                    `${tokenInfo.symbol.slice(0, 12)}...`
+                  }}</span></tooltip
+                >
+              </p>
+            </div>
+          </div>
+          <div class="add-custom-token__warning">
+            <warn-icon />
+            <p>
+              Be sure to validate this is the Massa token you think it is!
+              Anyone can create a token, even one pretending to be another
+              popular token.
+            </p>
+          </div>
+        </div>
+        <div v-else-if="isValidAddress && notTokenAddress">
+          <div class="add-custom-token__error">
+            <alert-icon />
+            <p>
+              There is no Massa token deployed at this address. Make sure you
+              have the right contract address and you are connected to the
+              correct network.
+            </p>
+          </div>
+        </div>
+      </div>
+
+      <div class="add-custom-token__buttons">
+        <div class="add-custom-token__buttons-send">
+          <button
+            class="add-token-btn"
+            :disabled="!isValidAddress || !tokenInfo"
+            @click="addToken"
+          >
+            Add token
+          </button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import { computed, ref, toRaw, watch } from 'vue';
+import { fromBase } from '@enkryptcom/utils';
+import CloseIcon from '@/ui/action/icons/common/close-icon.vue';
+import AlertIcon from '@action/icons/send/alert-icon.vue';
+import WarnIcon from '@action/icons/send/warning-icon.vue';
+import { TokensState } from '@/libs/tokens-state';
+import { CustomMassaToken, TokenType } from '@/libs/tokens-state/types';
+import { AssetsType } from '@/types/provider';
+import { formatFloatingPointValue } from '@/libs/utils/number-formatter';
+import Tooltip from '@/ui/action/components/tooltip/index.vue';
+import BigNumber from 'bignumber.js';
+import { BaseNetwork } from '@/types/base-network';
+import { Address, MRC20 } from '@massalabs/massa-web3';
+import MassaAPI from '../../../../../providers/massa/libs/api';
+
+interface IProps {
+  network: BaseNetwork;
+  address: string;
+}
+
+const emits = defineEmits<{
+  (e: 'update:close'): void;
+  (e: 'update:token-added', asset: AssetsType): void;
+}>();
+
+const props = defineProps<IProps>();
+
+const tokensState = new TokensState();
+
+const contractAddress = ref<string>('');
+const tokenInfo = ref<CustomMassaToken>();
+const accountBalance = ref<string>();
+const notTokenAddress = ref(false);
+const isFocus = ref(false);
+
+const isValidAddress = computed(() => {
+  if (contractAddress.value) {
+    try {
+      Address.fromString(contractAddress.value);
+      return true;
+    } catch (error) {
+      return false;
+    }
+  }
+  return false;
+});
+
+const close = () => {
+  emits('update:close');
+};
+
+const changeFocus = (val: FocusEvent) => {
+  isFocus.value = val.type === 'focus';
+};
+
+const fetchTokenInfo = async () => {
+  if (!isValidAddress.value) {
+    tokenInfo.value = undefined;
+    accountBalance.value = undefined;
+    notTokenAddress.value = false;
+    return;
+  }
+
+  try {
+    const api = (await props.network.api()) as MassaAPI;
+    const mrc20 = new MRC20(api.provider, contractAddress.value);
+
+    // Fetch token information
+    const name = await mrc20.name();
+    const symbol = await mrc20.symbol();
+    const decimals = await mrc20.decimals();
+
+    const tokenInfos: CustomMassaToken = {
+      type: TokenType.ERC20,
+      name,
+      symbol,
+      decimals,
+      icon: props.network.icon,
+      address: contractAddress.value as `AS${string}`,
+    };
+
+    tokenInfo.value = tokenInfos;
+
+    // Get token balance
+    try {
+      const balance = await api.getBalanceMRC20(
+        props.address,
+        contractAddress.value,
+      );
+      accountBalance.value = balance;
+    } catch (balanceError) {
+      accountBalance.value = '0';
+    }
+
+    notTokenAddress.value = false;
+  } catch (error) {
+    console.error('Error fetching token info:', error);
+    tokenInfo.value = undefined;
+    accountBalance.value = undefined;
+    notTokenAddress.value = true;
+  }
+};
+
+const addToken = async () => {
+  if (!tokenInfo.value) return;
+
+  try {
+    // Add token to state
+    await tokensState.addMassaToken(props.network.name, toRaw(tokenInfo.value));
+
+    // Create asset for UI
+    const balanceFormatted = fromBase(
+      accountBalance.value ?? '0',
+      tokenInfo.value.decimals,
+    );
+    const balanceDisplayFormatted =
+      formatFloatingPointValue(balanceFormatted).value;
+
+    // For Massa tokens, we'll use default values since market data is not available
+    const price = '0';
+    const priceChangePercentage = 0;
+    const sparklineData = '';
+
+    const balanceUSD = new BigNumber(balanceDisplayFormatted)
+      .times(price)
+      .toNumber();
+    const balanceUSDf = new BigNumber(balanceDisplayFormatted)
+      .times(price)
+      .toString();
+    const priceFormatted = formatFloatingPointValue(price).value;
+
+    const asset: AssetsType = {
+      name: tokenInfo.value.name,
+      symbol: tokenInfo.value.symbol,
+      icon: tokenInfo.value.icon,
+      balance: balanceFormatted,
+      balancef: balanceDisplayFormatted,
+      balanceUSD,
+      balanceUSDf,
+      value: price,
+      valuef: priceFormatted,
+      decimals: tokenInfo.value.decimals,
+      sparkline: sparklineData,
+      priceChangePercentage,
+      contract: contractAddress.value,
+    };
+
+    emits('update:token-added', asset);
+    close();
+  } catch (error) {
+    console.error('Error adding token:', error);
+  }
+};
+
+watch(contractAddress, () => {
+  fetchTokenInfo();
+});
+</script>
+
+<style lang="less" scoped>
+@import '@action/styles/theme.less';
+
+.container {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(0, 0, 0, 0.5);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 1000;
+}
+
+.add-custom-token {
+  background: @white;
+  border-radius: 12px;
+  width: 380px;
+  max-width: 90vw;
+  max-height: 85vh;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+
+  &__header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 20px 20px 0 20px;
+    flex-shrink: 0;
+
+    h3 {
+      margin: 0;
+      font-size: 18px;
+      font-weight: 600;
+      color: @primaryLabel;
+    }
+
+    &__close {
+      cursor: pointer;
+      padding: 4px;
+    }
+  }
+
+  &__content {
+    flex: 1;
+    overflow-y: auto;
+    overflow-x: hidden;
+    padding: 20px;
+    padding-top: 20px;
+    padding-bottom: 10px;
+    min-height: 0;
+  }
+
+  &__contract-input {
+    margin-bottom: 16px;
+
+    &.focus {
+      border-color: @primary;
+    }
+
+    &__address {
+      p {
+        margin: 0 0 8px 0;
+        font-size: 14px;
+        color: @secondaryLabel;
+      }
+
+      input {
+        width: 100%;
+        box-sizing: border-box;
+        padding: 10px;
+        border: 1px solid @gray02;
+        border-radius: 8px;
+        font-size: 14px;
+        outline: none;
+
+        &.invalid {
+          border-color: @error;
+        }
+
+        &:focus {
+          border-color: @primary;
+        }
+      }
+    }
+  }
+
+  &__token-info {
+    display: flex;
+    align-items: center;
+    margin-bottom: 12px;
+    padding: 12px;
+    background: @gray01;
+    border-radius: 8px;
+    width: 100%;
+    box-sizing: border-box;
+
+    &__image {
+      width: 36px;
+      height: 36px;
+      margin-right: 10px;
+      flex-shrink: 0;
+
+      img {
+        width: 100%;
+        height: 100%;
+        border-radius: 50%;
+      }
+    }
+
+    &__info {
+      flex: 1;
+      min-width: 0;
+
+      h5 {
+        margin: 0 0 4px 0;
+        font-size: 14px;
+        font-weight: 600;
+        color: @primaryLabel;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+
+      p {
+        margin: 0;
+        font-size: 12px;
+        color: @secondaryLabel;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+    }
+  }
+
+  &__warning {
+    display: flex;
+    align-items: flex-start;
+    margin-bottom: 16px;
+    padding: 10px;
+    background: @orange01;
+    border-radius: 8px;
+    width: 100%;
+    box-sizing: border-box;
+
+    svg {
+      margin-right: 8px;
+      margin-top: 2px;
+      flex-shrink: 0;
+    }
+
+    p {
+      margin: 0;
+      font-size: 11px;
+      color: @orange;
+      line-height: 1.4;
+      flex: 1;
+      min-width: 0;
+    }
+  }
+
+  &__error {
+    display: flex;
+    align-items: flex-start;
+    margin-bottom: 16px;
+    padding: 10px;
+    background: @error01;
+    border-radius: 8px;
+    width: 100%;
+    box-sizing: border-box;
+
+    svg {
+      margin-right: 8px;
+      margin-top: 2px;
+      flex-shrink: 0;
+    }
+
+    p {
+      margin: 0;
+      font-size: 11px;
+      color: @error;
+      line-height: 1.4;
+      flex: 1;
+      min-width: 0;
+    }
+  }
+
+  &__buttons {
+    display: flex;
+    justify-content: flex-end;
+    padding: 16px 20px 20px 20px;
+    flex-shrink: 0;
+    width: 100%;
+    box-sizing: border-box;
+    background: @white;
+    border-top: 1px solid @gray02;
+    min-height: 70px;
+
+    &-send {
+      display: flex;
+      align-items: center;
+
+      .add-token-btn,
+      button {
+        min-width: 120px;
+        height: 40px;
+        background: @primary;
+        color: @white;
+        border: none;
+        border-radius: 8px;
+        font-size: 14px;
+        font-weight: 600;
+        cursor: pointer;
+        transition: background 0.2s ease;
+
+        &:hover:not(:disabled) {
+          background: darken(@primary, 10%);
+        }
+
+        &:disabled {
+          background: @gray02;
+          color: @secondaryLabel;
+          cursor: not-allowed;
+          opacity: 0.6;
+        }
+      }
+    }
+  }
+}
+</style>
diff --git a/packages/extension/src/ui/action/views/network-assets/index.vue b/packages/extension/src/ui/action/views/network-assets/index.vue
index a4dea7119..56d443572 100644
--- a/packages/extension/src/ui/action/views/network-assets/index.vue
+++ b/packages/extension/src/ui/action/views/network-assets/index.vue
@@ -59,9 +59,13 @@
       />
     </div>
     <!-- prettier-ignore -->
-    <custom-evm-token v-if="showAddCustomTokens" :address="props.accountInfo.selectedAccount?.address!"
+    <custom-evm-token v-if="showAddCustomTokens && isEvmNetwork" :address="props.accountInfo.selectedAccount?.address!"
       :network="(props.network as EvmNetwork)" @update:token-added="addCustomAsset"
       @update:close="toggleShowAddCustomTokens"></custom-evm-token>
+    <!-- prettier-ignore -->
+    <custom-massa-token v-if="showAddCustomTokens && isMassaNetwork" :address="props.accountInfo.selectedAccount?.address!"
+      :network="props.network" @update:token-added="addCustomAsset"
+      @update:close="toggleShowAddCustomTokens"></custom-massa-token>
   </div>
 </template>
 
@@ -83,7 +87,9 @@ import scrollSettings from '@/libs/utils/scroll-settings';
 import Deposit from '@action/views/deposit/index.vue';
 import BaseButton from '@action/components/base-button/index.vue';
 import CustomEvmToken from './components/custom-evm-token.vue';
+import CustomMassaToken from './components/custom-massa-token.vue';
 import { EvmNetwork } from '@/providers/ethereum/types/evm-network';
+import { ProviderName } from '@/types/provider';
 import NetworkAssetsSolanaStakingBanner from './components/network-assets-solana-staking-banner.vue';
 import BannersState from '@/libs/banners-state';
 
@@ -146,6 +152,14 @@ const showAddCustomTokens = ref(false);
 const isSolanaStakingBanner = ref(false);
 const bannersState = new BannersState();
 
+// Network type checks
+const isEvmNetwork = computed(
+  () => props.network.provider === ProviderName.ethereum,
+);
+const isMassaNetwork = computed(
+  () => props.network.provider === ProviderName.massa,
+);
+
 watch([selectedAddress, selectedNetworkName, selectedSubnetwork], updateAssets);
 onMounted(async () => {
   updateAssets();
diff --git a/packages/extension/src/ui/action/views/send-transaction/index.vue b/packages/extension/src/ui/action/views/send-transaction/index.vue
index 5e3e90ffe..4a796a729 100644
--- a/packages/extension/src/ui/action/views/send-transaction/index.vue
+++ b/packages/extension/src/ui/action/views/send-transaction/index.vue
@@ -12,6 +12,7 @@ import SendTransactionEVM from '@/providers/ethereum/ui/send-transaction/index.v
 import SendTransactionBTC from '@/providers/bitcoin/ui/send-transaction/index.vue';
 import SendTransactionKadena from '@/providers/kadena/ui/send-transaction/index.vue';
 import SendTransactionSolana from '@/providers/solana/ui/send-transaction/index.vue';
+import SendTransactionMassa from '@/providers/massa/ui/send-transaction/index.vue';
 import { useRoute } from 'vue-router';
 import { ProviderName } from '@/types/provider';
 import { getNetworkByName } from '@/libs/utils/networks';
@@ -25,6 +26,7 @@ const sendLayouts: Record<ProviderName, any> = {
   [ProviderName.bitcoin]: SendTransactionBTC,
   [ProviderName.kadena]: SendTransactionKadena,
   [ProviderName.solana]: SendTransactionSolana,
+  [ProviderName.massa]: SendTransactionMassa,
   [ProviderName.enkrypt]: null,
 };
 
diff --git a/packages/extension/src/ui/action/views/verify-transaction/index.vue b/packages/extension/src/ui/action/views/verify-transaction/index.vue
index 874fdf894..5760dbe73 100644
--- a/packages/extension/src/ui/action/views/verify-transaction/index.vue
+++ b/packages/extension/src/ui/action/views/verify-transaction/index.vue
@@ -8,6 +8,7 @@ import VerifyTransactionEVM from '@/providers/ethereum/ui/send-transaction/verif
 import VerifyTransactionBTC from '@/providers/bitcoin/ui/send-transaction/verify-transaction/index.vue';
 import VerifyTransactionKadena from '@/providers/kadena/ui/send-transaction/verify-transaction/index.vue';
 import VerifyTransactionSolana from '@/providers/solana/ui/send-transaction/verify-transaction/index.vue';
+import VerifyTransactionMassa from '@/providers/massa/ui/send-transaction/verify-transaction/index.vue';
 import { useRoute } from 'vue-router';
 import { ProviderName } from '@/types/provider';
 import { getNetworkByName } from '@/libs/utils/networks';
@@ -19,6 +20,7 @@ const sendLayouts: Record<ProviderName, any> = {
   [ProviderName.bitcoin]: VerifyTransactionBTC,
   [ProviderName.kadena]: VerifyTransactionKadena,
   [ProviderName.solana]: VerifyTransactionSolana,
+  [ProviderName.massa]: VerifyTransactionMassa,
   [ProviderName.enkrypt]: null,
 };
 const layout = shallowRef();
diff --git a/packages/extension/src/ui/provider-pages/routes.ts b/packages/extension/src/ui/provider-pages/routes.ts
index 3c50b4f49..6ca72fb7c 100644
--- a/packages/extension/src/ui/provider-pages/routes.ts
+++ b/packages/extension/src/ui/provider-pages/routes.ts
@@ -6,6 +6,7 @@ import PolkadotUI from '@/providers/polkadot/ui';
 import BitcoinUI from '@/providers/bitcoin/ui';
 import KadenaUI from '@/providers/kadena/ui';
 import SolanaUI from '@/providers/solana/ui';
+import MassaUI from '@/providers/massa/ui';
 import EnkryptUI from './enkrypt';
 const uiProviders = [
   EthereumUI,
@@ -14,6 +15,7 @@ const uiProviders = [
   EnkryptUI,
   KadenaUI,
   SolanaUI,
+  MassaUI,
 ];
 let uiRoutes: RouteRecordRaw[] = [];
 uiProviders.forEach(provider => {
diff --git a/packages/keyring/package.json b/packages/keyring/package.json
index 74f42f8f1..21dc44649 100644
--- a/packages/keyring/package.json
+++ b/packages/keyring/package.json
@@ -25,6 +25,7 @@
     "@enkryptcom/signer-bitcoin": "workspace:^",
     "@enkryptcom/signer-ethereum": "workspace:^",
     "@enkryptcom/signer-kadena": "workspace:^",
+    "@enkryptcom/signer-massa": "workspace:^",
     "@enkryptcom/signer-polkadot": "workspace:^",
     "@enkryptcom/storage": "workspace:^",
     "@enkryptcom/types": "workspace:^",
diff --git a/packages/keyring/src/index.ts b/packages/keyring/src/index.ts
index 29b8ca683..9200005a9 100644
--- a/packages/keyring/src/index.ts
+++ b/packages/keyring/src/index.ts
@@ -19,6 +19,7 @@ import { PolkadotSigner } from "@enkryptcom/signer-polkadot";
 import { EthereumSigner } from "@enkryptcom/signer-ethereum";
 import { BitcoinSigner } from "@enkryptcom/signer-bitcoin";
 import { KadenaSigner } from "@enkryptcom/signer-kadena";
+import { MassaSigner } from "@enkryptcom/signer-massa";
 import assert from "assert";
 import configs from "./configs";
 import { pathParser } from "./utils";
@@ -51,6 +52,7 @@ class KeyRing {
       [SignerType.secp256k1btc]: new BitcoinSigner(),
       [SignerType.ed25519kda]: new KadenaSigner(),
       [SignerType.ed25519sol]: new KadenaSigner(),
+      [SignerType.ed25519mas]: new MassaSigner(),
     };
   }
 
diff --git a/packages/keyring/src/utils.ts b/packages/keyring/src/utils.ts
index 9bbca8da7..779033717 100644
--- a/packages/keyring/src/utils.ts
+++ b/packages/keyring/src/utils.ts
@@ -14,5 +14,8 @@ export const pathParser = (
   if (type === SignerType.ed25519sol) {
     return `${basePath}/${index}'/0`; // Solana uses hardened paths
   }
+  if (type === SignerType.ed25519mas) {
+    return `${basePath}/${index}'/0'`; // Massa uses hardened paths with BIP-44 coin type 632
+  }
   return `${basePath}/${index}`;
 };
diff --git a/packages/signers/massa/package.json b/packages/signers/massa/package.json
new file mode 100644
index 000000000..cb4c35f97
--- /dev/null
+++ b/packages/signers/massa/package.json
@@ -0,0 +1,60 @@
+{
+  "name": "@enkryptcom/signer-massa",
+  "version": "0.0.1",
+  "description": "Massa blockchain signer",
+  "type": "module",
+  "main": "src/index.ts",
+  "module": "src/index.ts",
+  "publishConfig": {
+    "main": "dist/index.cjs",
+    "module": "dist/index.js",
+    "types": "dist/index.d.ts"
+  },
+  "files": [
+    "dist"
+  ],
+  "scripts": {
+    "build": "tsup src/index.ts --format esm,cjs --dts --clean",
+    "lint": "prettier --write .",
+    "test": "vitest run"
+  },
+  "engines": {
+    "node": ">=14.15.0"
+  },
+  "dependencies": {
+    "@enkryptcom/types": "workspace:^",
+    "@enkryptcom/utils": "workspace:^",
+    "@massalabs/massa-web3": "^5.2.1-dev",
+    "bip39": "^3.1.0",
+    "tweetnacl": "^1.0.3",
+    "varint": "^6.0.0"
+  },
+  "devDependencies": {
+    "@polkadot/util-crypto": "^13.5.1",
+    "@types/hdkey": "^2.1.0",
+    "@types/node": "^22.15.24",
+    "@types/varint": "^6",
+    "@typescript-eslint/eslint-plugin": "^8.33.0",
+    "@typescript-eslint/parser": "^8.33.0",
+    "eslint": "^9.27.0",
+    "eslint-config-airbnb-base": "^15.0.0",
+    "eslint-config-prettier": "^10.1.5",
+    "eslint-import-resolver-alias": "^1.1.2",
+    "eslint-plugin-import": "^2.31.0",
+    "eslint-plugin-module-resolver": "^1.5.0",
+    "prettier": "^3.5.3",
+    "ts-node": "^10.9.2",
+    "tsconfig-paths": "^4.2.0",
+    "tsup": "^8.5.0",
+    "typescript": "^5.8.3",
+    "typescript-eslint": "8.33.0",
+    "vitest": "^3.1.4"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enkryptcom/enKrypt/tree/main/packages/signers/massa"
+  },
+  "keywords": [],
+  "author": "ae.studio",
+  "license": "MIT"
+}
diff --git a/packages/signers/massa/src/index.ts b/packages/signers/massa/src/index.ts
new file mode 100644
index 000000000..e07093839
--- /dev/null
+++ b/packages/signers/massa/src/index.ts
@@ -0,0 +1,65 @@
+import {
+  KeyPair,
+  MnemonicWithExtraWord,
+  SignerInterface,
+} from "@enkryptcom/types";
+import { bufferToHex, hexToBuffer } from "@enkryptcom/utils";
+import { mnemonicToSeedSync } from "bip39";
+import { sign as tweetSign } from "tweetnacl";
+import { derivePath } from "./libs/ed25519";
+import {
+  Address,
+  PublicKey,
+  PrivateKey,
+  Signature,
+} from "@massalabs/massa-web3";
+
+export class MassaSigner implements SignerInterface {
+  async generate(
+    mnemonic: MnemonicWithExtraWord,
+    derivationPath = "",
+  ): Promise<KeyPair> {
+    const seed = bufferToHex(
+      mnemonicToSeedSync(mnemonic.mnemonic, mnemonic.extraWord),
+      true,
+    );
+    const keys = derivePath(derivationPath, seed);
+    const keyPair = tweetSign.keyPair.fromSeed(keys.key);
+
+    // Prefix the 32-byte private key with version bytes for Massa
+    const versionBytes = Buffer.from([0]); // KEYS_VERSION_NUMBER = 0
+    const privateKeyBytes = Buffer.concat([
+      versionBytes,
+      Buffer.from(keyPair.secretKey.slice(0, 32)),
+    ]);
+    const privateKey = PrivateKey.fromBytes(privateKeyBytes);
+    const publicKey = await PublicKey.fromPrivateKey(privateKey);
+    const address = Address.fromPublicKey(publicKey);
+    return {
+      address: address.toString(),
+      privateKey: privateKey.toString(),
+      publicKey: publicKey.toString(),
+    };
+  }
+
+  async verify(
+    msgHash: string,
+    sig: string,
+    publicKey: string,
+  ): Promise<boolean> {
+    try {
+      const massaPublicKey = PublicKey.fromString(publicKey);
+      const signature = Signature.fromBytes(hexToBuffer(sig));
+      return massaPublicKey.verify(hexToBuffer(msgHash), signature);
+    } catch (error) {
+      console.error("Massa signature verification failed:", error);
+      return false;
+    }
+  }
+
+  async sign(msgHash: string, keyPair: KeyPair): Promise<string> {
+    const privateKey = PrivateKey.fromString(keyPair.privateKey);
+    const sig = await privateKey.sign(hexToBuffer(msgHash));
+    return sig.toString();
+  }
+}
diff --git a/packages/signers/massa/src/libs/ed25519.ts b/packages/signers/massa/src/libs/ed25519.ts
new file mode 100644
index 000000000..9b63f3204
--- /dev/null
+++ b/packages/signers/massa/src/libs/ed25519.ts
@@ -0,0 +1,81 @@
+import { createHmac } from "crypto";
+import { sign } from "tweetnacl";
+
+const ED25519_CURVE = "ed25519 seed";
+const HARDENED_OFFSET = 0x80000000;
+
+type Hex = string;
+type Path = string;
+
+type Keys = {
+  key: Buffer;
+  chainCode: Buffer;
+};
+
+const getMasterKeyFromSeed = (seed: Hex): Keys => {
+  const hmac = createHmac("sha512", Buffer.from(ED25519_CURVE, "utf8"));
+  const I = hmac.update(Buffer.from(seed, "hex")).digest();
+  const IL = I.subarray(0, 32);
+  const IR = I.subarray(32);
+  return {
+    key: IL,
+    chainCode: IR,
+  };
+};
+
+const CKDPriv = ({ key, chainCode }: Keys, index: number): Keys => {
+  const indexBuffer = Buffer.allocUnsafe(4);
+  indexBuffer.writeUInt32BE(index, 0);
+
+  const data = Buffer.concat([Buffer.alloc(1, 0), key, indexBuffer]);
+
+  const I = createHmac("sha512", chainCode).update(data).digest();
+  const IL = I.subarray(0, 32);
+  const IR = I.subarray(32);
+  return {
+    key: IL,
+    chainCode: IR,
+  };
+};
+
+const getPublicKey = (privateKey: Buffer, withZeroByte = true): Buffer => {
+  const keyPair = sign.keyPair.fromSeed(privateKey);
+  const signPk = keyPair.secretKey.subarray(32);
+  const zero = Buffer.alloc(1, 0);
+  return withZeroByte
+    ? Buffer.concat([zero, Buffer.from(signPk)])
+    : Buffer.from(signPk);
+};
+
+const replaceDerive = (val: string): string => val.replace("'", "");
+
+const isValidPath = (path: string): boolean => {
+  if (!/^m(\/[0-9]+('?))*$/.test(path)) {
+    return false;
+  }
+  return !path
+    .split("/")
+    .slice(1)
+    .map(replaceDerive)
+    .some(isNaN as any);
+};
+
+const derivePath = (path: Path, seed: Hex, offset = HARDENED_OFFSET): Keys => {
+  if (!isValidPath(path)) {
+    throw new Error("Invalid derivation path");
+  }
+
+  const { key, chainCode } = getMasterKeyFromSeed(seed);
+  const segments = path
+    .split("/")
+    .slice(1)
+    .map(replaceDerive)
+    .map((el) => parseInt(el, 10));
+
+  return segments.reduce(
+    (parentKeys, segment) => CKDPriv(parentKeys, segment + offset),
+    { key, chainCode },
+  );
+};
+
+export { derivePath, getPublicKey };
diff --git a/packages/signers/massa/tests/sign.test.ts b/packages/signers/massa/tests/sign.test.ts
new file mode 100644
index 000000000..2184711fa
--- /dev/null
+++ b/packages/signers/massa/tests/sign.test.ts
@@ -0,0 +1,52 @@
+import { describe, it, expect } from "vitest";
+import { blake2AsU8a } from "@polkadot/util-crypto";
+import { bufferToHex } from "@enkryptcom/utils";
+import { MassaSigner } from "../src";
+
+describe("Massa signing", () => {
+  const MNEMONIC = {
+    mnemonic:
+      "error fish boy absent drop next ice keep meadow little air include",
+  };
+
+  const msg =
+    "Everything should be made as simple as possible, but not simpler.";
+  const msgHash = bufferToHex(blake2AsU8a(msg));
+
+  it("should generate keypair correctly", async () => {
+    const signer = new MassaSigner();
+    const keypair = await signer.generate(MNEMONIC, "m/44'/632'/0'/0'");
+
+    expect(keypair.address).toBeDefined();
+    expect(keypair.privateKey).toBeDefined();
+    expect(keypair.publicKey).toBeDefined();
+
+    // Massa addresses should start with 'AU'
+    expect(keypair.address?.startsWith("AU")).toBe(true);
+  });
+
+  it("should sign and verify correctly", async () => {
+    const signer = new MassaSigner();
+    const keypair = await signer.generate(MNEMONIC, "m/44'/632'/0'/0'");
+    const signature = await signer.sign(msgHash, keypair);
+
+    expect(signature).toBeDefined();
+    expect(signature.length).toBeGreaterThan(0);
+
+    const isValid = await signer.verify(msgHash, signature, keypair.publicKey);
+    expect(isValid).toBe(true);
+  });
+
+  it("should reject invalid signatures", async () => {
+    const signer = new MassaSigner();
+    const keypair = await signer.generate(MNEMONIC, "m/44'/632'/0'/0'");
+    const invalidSignature = "0x" + "0".repeat(128); // Invalid signature
+
+    const isValid = await signer.verify(
+      msgHash,
+      invalidSignature,
+      keypair.publicKey,
+    );
+    expect(isValid).toBe(false);
+  });
+});
diff --git a/packages/signers/massa/tsconfig.json b/packages/signers/massa/tsconfig.json
new file mode 100644
index 000000000..e8b896562
--- /dev/null
+++ b/packages/signers/massa/tsconfig.json
@@ -0,0 +1,29 @@
+{
+  "extends": "./tsconfig.paths.json",
+  "compilerOptions": {
+    "lib": ["ESNext", "dom"],
+    "moduleResolution": "node",
+    "noUnusedLocals": true,
+    "noUnusedParameters": true,
+    "removeComments": true,
+    "sourceMap": true,
+    "target": "es2015",
+    "module": "commonjs",
+    "outDir": "dist",
+    "resolveJsonModule": true,
+    "esModuleInterop": true,
+    "declaration": true,
+    "downlevelIteration": true
+  },
+  "include": ["src/**/*.ts", "tests/**/*.ts"],
+  "exclude": [
+    "node_modules/**/*",
+    "_warmup/**/*",
+    ".vscode/**/*",
+    "tests/**/*"
+  ],
+  "ts-node": {
+    "require": ["tsconfig-paths/register"],
+    "files": true
+  }
+}
diff --git a/packages/signers/massa/tsconfig.paths.json b/packages/signers/massa/tsconfig.paths.json
new file mode 100644
index 000000000..6451834c2
--- /dev/null
+++ b/packages/signers/massa/tsconfig.paths.json
@@ -0,0 +1,8 @@
+{
+  "compilerOptions": {
+    "baseUrl": ".",
+    "paths": {
+      "@src/*": ["src/*"]
+    }
+  }
+}
diff --git a/packages/types/package.json b/packages/types/package.json
index d013f70ad..8f18f5322 100644
--- a/packages/types/package.json
+++ b/packages/types/package.json
@@ -24,6 +24,7 @@
     "node": ">=14.15.0"
   },
   "devDependencies": {
+    "@massalabs/massa-web3": "^5.2.1-dev",
     "@types/node": "^22.16.5",
     "@typescript-eslint/eslint-plugin": "^8.38.0",
     "@typescript-eslint/parser": "^8.38.0",
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index a4ad09e70..5cf205151 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -50,6 +50,7 @@ enum SignerType {
   secp256k1btc = "secp256k1-btc", // bitcoin
   ed25519kda = "ed25519-kda", // kadena
   ed25519sol = "ed25519-sol", // solana
+  ed25519mas = "ed25519-mas", // massa
 }
 
 interface KeyRecordAdd {
diff --git a/packages/types/src/networks.ts b/packages/types/src/networks.ts
index fd120357e..69b39b292 100755
--- a/packages/types/src/networks.ts
+++ b/packages/types/src/networks.ts
@@ -112,6 +112,8 @@ export enum NetworkNames {
   Hemi = "Hemi",
   CoreDAO = "CORE",
   AppLayerTestnet = "AppLayerTestnet",
+  Massa = "Massa",
+  MassaBuildnet = "MassaBuildnet",
 }
 
 export enum CoingeckoPlatform {
@@ -181,4 +183,5 @@ export enum CoingeckoPlatform {
   UnitZero = "units-network",
   Conflux = "conflux",
   CoreDAO = "core",
+  Massa = "massa",
 }
diff --git a/yarn.lock b/yarn.lock
index 9b060103b..0ae842963 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1642,6 +1642,7 @@ __metadata:
     "@kadena/client": "npm:^1.18.0"
     "@kadena/pactjs-cli": "npm:^1.18.0"
     "@ledgerhq/hw-transport-webusb": "npm:^6.29.8"
+    "@massalabs/massa-web3": "npm:5.2.1-dev.20250730141858"
     "@metamask/eth-sig-util": "npm:^8.2.0"
     "@metaplex-foundation/mpl-bubblegum": "npm:^5.0.2"
     "@metaplex-foundation/umi": "npm:^1.2.0"
@@ -1797,6 +1798,7 @@ __metadata:
     "@enkryptcom/signer-bitcoin": "workspace:^"
     "@enkryptcom/signer-ethereum": "workspace:^"
     "@enkryptcom/signer-kadena": "workspace:^"
+    "@enkryptcom/signer-massa": "workspace:^"
     "@enkryptcom/signer-polkadot": "workspace:^"
     "@enkryptcom/storage": "workspace:^"
     "@enkryptcom/types": "workspace:^"
@@ -1973,6 +1975,38 @@ __metadata:
   languageName: unknown
   linkType: soft
 
+"@enkryptcom/signer-massa@workspace:^, @enkryptcom/signer-massa@workspace:packages/signers/massa":
+  version: 0.0.0-use.local
+  resolution: "@enkryptcom/signer-massa@workspace:packages/signers/massa"
+  dependencies:
+    "@enkryptcom/types": "workspace:^"
+    "@enkryptcom/utils": "workspace:^"
+    "@massalabs/massa-web3": "npm:^5.2.1-dev"
+    "@polkadot/util-crypto": "npm:^13.5.1"
+    "@types/hdkey": "npm:^2.1.0"
+    "@types/node": "npm:^22.15.24"
+    "@types/varint": "npm:^6"
+    "@typescript-eslint/eslint-plugin": "npm:^8.33.0"
+    "@typescript-eslint/parser": "npm:^8.33.0"
+    bip39: "npm:^3.1.0"
+    eslint: "npm:^9.27.0"
+    eslint-config-airbnb-base: "npm:^15.0.0"
+    eslint-config-prettier: "npm:^10.1.5"
+    eslint-import-resolver-alias: "npm:^1.1.2"
+    eslint-plugin-import: "npm:^2.31.0"
+    eslint-plugin-module-resolver: "npm:^1.5.0"
+    prettier: "npm:^3.5.3"
+    ts-node: "npm:^10.9.2"
+    tsconfig-paths: "npm:^4.2.0"
+    tsup: "npm:^8.5.0"
+    tweetnacl: "npm:^1.0.3"
+    typescript: "npm:^5.8.3"
+    typescript-eslint: "npm:8.33.0"
+    varint: "npm:^6.0.0"
+    vitest: "npm:^3.1.4"
+  languageName: unknown
+  linkType: soft
+
 "@enkryptcom/signer-polkadot@workspace:^, @enkryptcom/signer-polkadot@workspace:packages/signers/polkadot":
   version: 0.0.0-use.local
   resolution: "@enkryptcom/signer-polkadot@workspace:packages/signers/polkadot"
@@ -2071,6 +2105,7 @@ __metadata:
   version: 0.0.0-use.local
   resolution: "@enkryptcom/types@workspace:packages/types"
   dependencies:
+    "@massalabs/massa-web3": "npm:^5.2.1-dev"
     "@types/node": "npm:^22.16.5"
     "@typescript-eslint/eslint-plugin": "npm:^8.38.0"
     "@typescript-eslint/parser": "npm:^8.38.0"
@@ -2535,6 +2570,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@eslint/core@npm:^0.14.0":
+  version: 0.14.0
+  resolution: "@eslint/core@npm:0.14.0"
+  dependencies:
+    "@types/json-schema": "npm:^7.0.15"
+  checksum: 10/d9b060cf97468150675ddf4fb3db55edaa32467e0adf9f80919a5bfd15d0835ad7765456f4397ec2d16b0a1bb702af63f6d4712f94194d34fea118231ae1e2db
+  languageName: node
+  linkType: hard
+
 "@eslint/core@npm:^0.15.0, @eslint/core@npm:^0.15.1":
   version: 0.15.1
   resolution: "@eslint/core@npm:0.15.1"
@@ -2561,6 +2605,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@eslint/js@npm:9.30.1":
+  version: 9.30.1
+  resolution: "@eslint/js@npm:9.30.1"
+  checksum: 10/f32c8a42b1343b03613b92a4a7c4745d19a93e66ffb8fac18ccd066deaa200b2fc55f476bf0407d7748f663bc947ca78c0518f13f60cd9ed08d0ba8b7bb74370
+  languageName: node
+  linkType: hard
+
 "@eslint/js@npm:9.32.0":
   version: 9.32.0
   resolution: "@eslint/js@npm:9.32.0"
@@ -2575,6 +2626,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@eslint/plugin-kit@npm:^0.3.1":
+  version: 0.3.1
+  resolution: "@eslint/plugin-kit@npm:0.3.1"
+  dependencies:
+    "@eslint/core": "npm:^0.14.0"
+    levn: "npm:^0.4.1"
+  checksum: 10/ab0c4cecadc6c38c7ae5f71b9831d3521d08237444d8f327751d1133a4369ccd42093a1c06b26fd6c311015807a27d95a0184a761d1cdd264b090896dcf0addb
+  languageName: node
+  linkType: hard
+
 "@eslint/plugin-kit@npm:^0.3.4":
   version: 0.3.4
   resolution: "@eslint/plugin-kit@npm:0.3.4"
@@ -5804,6 +5865,58 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@massalabs/massa-web3@npm:5.2.1-dev.20250730141858":
+  version: 5.2.1-dev.20250730141858
+  resolution: "@massalabs/massa-web3@npm:5.2.1-dev.20250730141858"
+  dependencies:
+    "@noble/ed25519": "npm:^1.7.3"
+    "@noble/hashes": "npm:^1.2.0"
+    bs58check: "npm:^4.0.0"
+    bufferutil: "npm:^4.0.7"
+    dotenv: "npm:^16.0.3"
+    eventemitter3: "npm:^5.0.1"
+    google-protobuf: "npm:^3.21.4"
+    grpc-web: "npm:^1.5.0"
+    lodash.isequal: "npm:^4.5.0"
+    secure-random: "npm:^1.1.2"
+    tslib: "npm:^2.8.0"
+    utf-8-validate: "npm:^6.0.2"
+    varint: "npm:^6.0.0"
+  dependenciesMeta:
+    bufferutil:
+      optional: true
+    utf-8-validate:
+      optional: true
+  checksum: 10/56464249fcfbf5f66980eceecef13343b5379bf9badd779be0d6d0ce51882c15310c74d5209ff75d825058eb82ac26e1f7b2ff5fa96a7c690461577710b8e6b1
+  languageName: node
+  linkType: hard
+
+"@massalabs/massa-web3@npm:^5.2.1-dev":
+  version: 5.2.1-dev.20250611112554
+  resolution: "@massalabs/massa-web3@npm:5.2.1-dev.20250611112554"
+  dependencies:
+    "@noble/ed25519": "npm:^1.7.3"
+    "@noble/hashes": "npm:^1.2.0"
+    bs58check: "npm:^4.0.0"
+    bufferutil: "npm:^4.0.7"
+    dotenv: "npm:^16.0.3"
+    eventemitter3: "npm:^5.0.1"
+    google-protobuf: "npm:^3.21.4"
+    grpc-web: "npm:^1.5.0"
+    lodash.isequal: "npm:^4.5.0"
+    secure-random: "npm:^1.1.2"
+    tslib: "npm:^2.8.0"
+    utf-8-validate: "npm:^6.0.2"
+    varint: "npm:^6.0.0"
+  dependenciesMeta:
+    bufferutil:
+      optional: true
+    utf-8-validate:
+      optional: true
+  checksum: 10/29f69533e5b9469440c6d329824d59600448ac3de40b44340878a4f883f353de7a858ddea69091d20b5fa5d77dca96d9c39c8c994eb9c635a72c2780096126bf
+  languageName: node
+  linkType: hard
+
 "@metamask/abi-utils@npm:^3.0.0":
   version: 3.0.0
   resolution: "@metamask/abi-utils@npm:3.0.0"
@@ -7200,6 +7313,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@polkadot/networks@npm:13.5.1":
+  version: 13.5.1
+  resolution: "@polkadot/networks@npm:13.5.1"
+  dependencies:
+    "@polkadot/util": "npm:13.5.1"
+    "@substrate/ss58-registry": "npm:^1.51.0"
+    tslib: "npm:^2.8.0"
+  checksum: 10/836835ffcf58027cb450f17400c733eb84272cb7de0b1a86f72a0c1b1bb35ea3c628f8dd418e185f163ff0963ec931f41618b9405088a1d6fe2fbf5e5ab09709
+  languageName: node
+  linkType: hard
+
 "@polkadot/networks@npm:13.5.3, @polkadot/networks@npm:^13.5.3":
   version: 13.5.3
   resolution: "@polkadot/networks@npm:13.5.3"
@@ -7639,6 +7763,26 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@polkadot/util-crypto@npm:^13.5.1":
+  version: 13.5.1
+  resolution: "@polkadot/util-crypto@npm:13.5.1"
+  dependencies:
+    "@noble/curves": "npm:^1.3.0"
+    "@noble/hashes": "npm:^1.3.3"
+    "@polkadot/networks": "npm:13.5.1"
+    "@polkadot/util": "npm:13.5.1"
+    "@polkadot/wasm-crypto": "npm:^7.4.1"
+    "@polkadot/wasm-util": "npm:^7.4.1"
+    "@polkadot/x-bigint": "npm:13.5.1"
+    "@polkadot/x-randomvalues": "npm:13.5.1"
+    "@scure/base": "npm:^1.1.7"
+    tslib: "npm:^2.8.0"
+  peerDependencies:
+    "@polkadot/util": 13.5.1
+  checksum: 10/280a8fb838e8ee30da92a73c5c578977c2d0d823dd03143ebdd3a0a9dc276649a6476a1cbf0200140ed116146b7202c7cd5c0be58271e12326d4aff4a42788e4
+  languageName: node
+  linkType: hard
+
 "@polkadot/util@npm:12.6.2, @polkadot/util@npm:^12.6.2":
   version: 12.6.2
   resolution: "@polkadot/util@npm:12.6.2"
@@ -7654,6 +7798,21 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@polkadot/util@npm:13.5.1":
+  version: 13.5.1
+  resolution: "@polkadot/util@npm:13.5.1"
+  dependencies:
+    "@polkadot/x-bigint": "npm:13.5.1"
+    "@polkadot/x-global": "npm:13.5.1"
+    "@polkadot/x-textdecoder": "npm:13.5.1"
+    "@polkadot/x-textencoder": "npm:13.5.1"
+    "@types/bn.js": "npm:^5.1.6"
+    bn.js: "npm:^5.2.1"
+    tslib: "npm:^2.8.0"
+  checksum: 10/26b7c564012afec2c877dbf265021883335a28f369c84d59eeaf6bba72a9fd4e70d259cf24619332e9c44fc55093d9f51ec212a7d48fcae92e962f42f4310d6f
+  languageName: node
+  linkType: hard
+
 "@polkadot/util@npm:13.5.3, @polkadot/util@npm:^13.5.3":
   version: 13.5.3
   resolution: "@polkadot/util@npm:13.5.3"
@@ -7759,6 +7918,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@polkadot/x-bigint@npm:13.5.1":
+  version: 13.5.1
+  resolution: "@polkadot/x-bigint@npm:13.5.1"
+  dependencies:
+    "@polkadot/x-global": "npm:13.5.1"
+    tslib: "npm:^2.8.0"
+  checksum: 10/726bc63bc9a51dbfc21de3913ac546c296ca82b05a78014a9de7268a22c4db85552c6143ab058e0bf3e92defaa36a7d7a803a3deb6607e5928f408ee245dc55e
+  languageName: node
+  linkType: hard
+
 "@polkadot/x-bigint@npm:13.5.3, @polkadot/x-bigint@npm:^13.5.3":
   version: 13.5.3
   resolution: "@polkadot/x-bigint@npm:13.5.3"
@@ -7800,6 +7969,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@polkadot/x-global@npm:13.5.1":
+  version: 13.5.1
+  resolution: "@polkadot/x-global@npm:13.5.1"
+  dependencies:
+    tslib: "npm:^2.8.0"
+  checksum: 10/6db58bbed5c6506c2f6d542cd836b242750a01d93e30fb6f19543a43ca7573a96813df44344df5d9ec938a913e2ddb8af0258f51770d3aa9f9bcbb896d8e5d1b
+  languageName: node
+  linkType: hard
+
 "@polkadot/x-global@npm:13.5.3, @polkadot/x-global@npm:^13.5.3":
   version: 13.5.3
   resolution: "@polkadot/x-global@npm:13.5.3"
@@ -7822,6 +8000,19 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@polkadot/x-randomvalues@npm:13.5.1":
+  version: 13.5.1
+  resolution: "@polkadot/x-randomvalues@npm:13.5.1"
+  dependencies:
+    "@polkadot/x-global": "npm:13.5.1"
+    tslib: "npm:^2.8.0"
+  peerDependencies:
+    "@polkadot/util": 13.5.1
+    "@polkadot/wasm-util": "*"
+  checksum: 10/cadd8c7f9e7acf219c7cdc45bd3e7473e2da5577919936eb1721a297bfaeb45498e3f651200b9333aab95666d09671f915c8ac262924a922c23520ae494acf72
+  languageName: node
+  linkType: hard
+
 "@polkadot/x-randomvalues@npm:13.5.3":
   version: 13.5.3
   resolution: "@polkadot/x-randomvalues@npm:13.5.3"
@@ -7845,6 +8036,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@polkadot/x-textdecoder@npm:13.5.1":
+  version: 13.5.1
+  resolution: "@polkadot/x-textdecoder@npm:13.5.1"
+  dependencies:
+    "@polkadot/x-global": "npm:13.5.1"
+    tslib: "npm:^2.8.0"
+  checksum: 10/705b3f3b3c757cf2f7077e71f6c765c088e6636e5580408a8f95bf9b2e17c59bfa0846d89ba423131422a0bbb381fe0eff13cd7ac3d366272ebe269876789a52
+  languageName: node
+  linkType: hard
+
 "@polkadot/x-textdecoder@npm:13.5.3":
   version: 13.5.3
   resolution: "@polkadot/x-textdecoder@npm:13.5.3"
@@ -7865,6 +8066,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@polkadot/x-textencoder@npm:13.5.1":
+  version: 13.5.1
+  resolution: "@polkadot/x-textencoder@npm:13.5.1"
+  dependencies:
+    "@polkadot/x-global": "npm:13.5.1"
+    tslib: "npm:^2.8.0"
+  checksum: 10/d5309785674a034e21717236f7f2a438da77d29c514c9cfae8517c8db690e1cff55820cfbac6f2307c9e1d4dc2c4e24ad01f915b585823af5ee73737441d1766
+  languageName: node
+  linkType: hard
+
 "@polkadot/x-textencoder@npm:13.5.3":
   version: 13.5.3
   resolution: "@polkadot/x-textencoder@npm:13.5.3"
@@ -11509,6 +11720,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@types/node@npm:^22.15.24":
+  version: 22.15.32
+  resolution: "@types/node@npm:22.15.32"
+  dependencies:
+    undici-types: "npm:~6.21.0"
+  checksum: 10/10b4c106d0c512a1d35ec08142bd7fb5cf2e1df93fc5627b3c69dd843dec4be07a47f1fa7ede232ad84762d75a372ea35028b79ee1e753b6f2adecd0b2cb2f71
+  languageName: node
+  linkType: hard
+
 "@types/node@npm:^22.16.5":
   version: 22.16.5
   resolution: "@types/node@npm:22.16.5"
@@ -11737,6 +11957,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@types/varint@npm:^6":
+  version: 6.0.3
+  resolution: "@types/varint@npm:6.0.3"
+  dependencies:
+    "@types/node": "npm:*"
+  checksum: 10/cfec85c15e24becb360be6466a41c97b5b6370aec49a403ed28ae52e96b7ef692e9e5aee981ccebab3b7afdf9b84d3809e6ab5bb38cf2e926711c6aebeb8a68d
+  languageName: node
+  linkType: hard
+
 "@types/w3c-web-usb@npm:^1.0.6":
   version: 1.0.10
   resolution: "@types/w3c-web-usb@npm:1.0.10"
@@ -11822,7 +12051,28 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/eslint-plugin@npm:8.36.0":
+"@typescript-eslint/eslint-plugin@npm:8.33.0":
+  version: 8.33.0
+  resolution: "@typescript-eslint/eslint-plugin@npm:8.33.0"
+  dependencies:
+    "@eslint-community/regexpp": "npm:^4.10.0"
+    "@typescript-eslint/scope-manager": "npm:8.33.0"
+    "@typescript-eslint/type-utils": "npm:8.33.0"
+    "@typescript-eslint/utils": "npm:8.33.0"
+    "@typescript-eslint/visitor-keys": "npm:8.33.0"
+    graphemer: "npm:^1.4.0"
+    ignore: "npm:^7.0.0"
+    natural-compare: "npm:^1.4.0"
+    ts-api-utils: "npm:^2.1.0"
+  peerDependencies:
+    "@typescript-eslint/parser": ^8.33.0
+    eslint: ^8.57.0 || ^9.0.0
+    typescript: ">=4.8.4 <5.9.0"
+  checksum: 10/b728001208b28c05d024f352d61d6b707c5f9a9d1d9ada8239d3171897ac1545a54401ca340732af9f615af88dae954f7264d73ced1950e02d38225d33492f8d
+  languageName: node
+  linkType: hard
+
+"@typescript-eslint/eslint-plugin@npm:8.36.0, @typescript-eslint/eslint-plugin@npm:^8.33.0":
   version: 8.36.0
   resolution: "@typescript-eslint/eslint-plugin@npm:8.36.0"
   dependencies:
@@ -11864,7 +12114,23 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/parser@npm:8.36.0":
+"@typescript-eslint/parser@npm:8.33.0":
+  version: 8.33.0
+  resolution: "@typescript-eslint/parser@npm:8.33.0"
+  dependencies:
+    "@typescript-eslint/scope-manager": "npm:8.33.0"
+    "@typescript-eslint/types": "npm:8.33.0"
+    "@typescript-eslint/typescript-estree": "npm:8.33.0"
+    "@typescript-eslint/visitor-keys": "npm:8.33.0"
+    debug: "npm:^4.3.4"
+  peerDependencies:
+    eslint: ^8.57.0 || ^9.0.0
+    typescript: ">=4.8.4 <5.9.0"
+  checksum: 10/1a875fdb0e9d0a49cbe0f5a33da16ee95c5a1ddf08bd1a3f9481de5c6b3981aee8ef2be24570a14fbed1b53ee348ee8dac39bcc436e6479ea1ecb39b69ce7f2a
+  languageName: node
+  linkType: hard
+
+"@typescript-eslint/parser@npm:8.36.0, @typescript-eslint/parser@npm:^8.33.0":
   version: 8.36.0
   resolution: "@typescript-eslint/parser@npm:8.36.0"
   dependencies:
@@ -11896,6 +12162,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@typescript-eslint/project-service@npm:8.33.0":
+  version: 8.33.0
+  resolution: "@typescript-eslint/project-service@npm:8.33.0"
+  dependencies:
+    "@typescript-eslint/tsconfig-utils": "npm:^8.33.0"
+    "@typescript-eslint/types": "npm:^8.33.0"
+    debug: "npm:^4.3.4"
+  checksum: 10/5fdc829a67092c2b764598facaf515ec114af2fcfdaf68af321aa667e4c4962fa6c19120efbde7ca234488b2bd7299015fb6b221b22253fe4ea3eae0bb72e494
+  languageName: node
+  linkType: hard
+
 "@typescript-eslint/project-service@npm:8.36.0":
   version: 8.36.0
   resolution: "@typescript-eslint/project-service@npm:8.36.0"
@@ -11935,6 +12212,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@typescript-eslint/scope-manager@npm:8.33.0":
+  version: 8.33.0
+  resolution: "@typescript-eslint/scope-manager@npm:8.33.0"
+  dependencies:
+    "@typescript-eslint/types": "npm:8.33.0"
+    "@typescript-eslint/visitor-keys": "npm:8.33.0"
+  checksum: 10/f52075c9ab3bdc69435f3b36583d2d5eb7bc66cfc8462184c9dc6dba5d0825e4d1d0f2e473ffaab5469fcfc4dc770908c26c1623b882d283739eb8e1869ab759
+  languageName: node
+  linkType: hard
+
 "@typescript-eslint/scope-manager@npm:8.36.0":
   version: 8.36.0
   resolution: "@typescript-eslint/scope-manager@npm:8.36.0"
@@ -11965,7 +12252,16 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/tsconfig-utils@npm:8.36.0, @typescript-eslint/tsconfig-utils@npm:^8.36.0":
+"@typescript-eslint/tsconfig-utils@npm:8.33.0":
+  version: 8.33.0
+  resolution: "@typescript-eslint/tsconfig-utils@npm:8.33.0"
+  peerDependencies:
+    typescript: ">=4.8.4 <5.9.0"
+  checksum: 10/5bb139be996a16f65c012c083e4c0dc2ddafd1295940203e6c2a1ac9fa0718b1a91f74354f162d3d9614b013e062863414d4478c57ffbf78dfd7cb4f5701abde
+  languageName: node
+  linkType: hard
+
+"@typescript-eslint/tsconfig-utils@npm:8.36.0, @typescript-eslint/tsconfig-utils@npm:^8.33.0, @typescript-eslint/tsconfig-utils@npm:^8.36.0":
   version: 8.36.0
   resolution: "@typescript-eslint/tsconfig-utils@npm:8.36.0"
   peerDependencies:
@@ -11992,6 +12288,21 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@typescript-eslint/type-utils@npm:8.33.0":
+  version: 8.33.0
+  resolution: "@typescript-eslint/type-utils@npm:8.33.0"
+  dependencies:
+    "@typescript-eslint/typescript-estree": "npm:8.33.0"
+    "@typescript-eslint/utils": "npm:8.33.0"
+    debug: "npm:^4.3.4"
+    ts-api-utils: "npm:^2.1.0"
+  peerDependencies:
+    eslint: ^8.57.0 || ^9.0.0
+    typescript: ">=4.8.4 <5.9.0"
+  checksum: 10/993e7b8f2c8b6e34e175fd57077cb3ffbe9c83da66917b8bd0049e82c39f1ef18ab718a2ca1774db48311c58e4baf5b8e749e6aff5ff50c01b714e9471a673a5
+  languageName: node
+  linkType: hard
+
 "@typescript-eslint/type-utils@npm:8.36.0":
   version: 8.36.0
   resolution: "@typescript-eslint/type-utils@npm:8.36.0"
@@ -12023,7 +12334,14 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/types@npm:8.36.0, @typescript-eslint/types@npm:^8.36.0":
+"@typescript-eslint/types@npm:8.33.0":
+  version: 8.33.0
+  resolution: "@typescript-eslint/types@npm:8.33.0"
+  checksum: 10/778e812e2c3543e79168fe1072559d8bfef314a96b90da81805f9359f3b5cdfd202153c161723ccb1a4f8edb2593625aa5003f6235039bf189b39c93ff2605c2
+  languageName: node
+  linkType: hard
+
+"@typescript-eslint/types@npm:8.36.0, @typescript-eslint/types@npm:^8.33.0, @typescript-eslint/types@npm:^8.36.0":
   version: 8.36.0
   resolution: "@typescript-eslint/types@npm:8.36.0"
   checksum: 10/14ac09633d6e9947d88b8d714826bb12f4aa71874351e5c92d43fc9b5b48358cd6f58473c12e7bd583bcb3e05993bef89783e67f60746df19553d6e7ee1588af
@@ -12044,6 +12362,26 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@typescript-eslint/typescript-estree@npm:8.33.0":
+  version: 8.33.0
+  resolution: "@typescript-eslint/typescript-estree@npm:8.33.0"
+  dependencies:
+    "@typescript-eslint/project-service": "npm:8.33.0"
+    "@typescript-eslint/tsconfig-utils": "npm:8.33.0"
+    "@typescript-eslint/types": "npm:8.33.0"
+    "@typescript-eslint/visitor-keys": "npm:8.33.0"
+    debug: "npm:^4.3.4"
+    fast-glob: "npm:^3.3.2"
+    is-glob: "npm:^4.0.3"
+    minimatch: "npm:^9.0.4"
+    semver: "npm:^7.6.0"
+    ts-api-utils: "npm:^2.1.0"
+  peerDependencies:
+    typescript: ">=4.8.4 <5.9.0"
+  checksum: 10/7cad508e5cc70a1e0bc72ee0448b0cc55e195c93124a25a8330c58fc3fee4e2762cbc8039ad13d40cb0ef2953239af9dbb4d3653636f605ed3f9414995af080c
+  languageName: node
+  linkType: hard
+
 "@typescript-eslint/typescript-estree@npm:8.36.0":
   version: 8.36.0
   resolution: "@typescript-eslint/typescript-estree@npm:8.36.0"
@@ -12104,6 +12442,21 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@typescript-eslint/utils@npm:8.33.0":
+  version: 8.33.0
+  resolution: "@typescript-eslint/utils@npm:8.33.0"
+  dependencies:
+    "@eslint-community/eslint-utils": "npm:^4.7.0"
+    "@typescript-eslint/scope-manager": "npm:8.33.0"
+    "@typescript-eslint/types": "npm:8.33.0"
+    "@typescript-eslint/typescript-estree": "npm:8.33.0"
+  peerDependencies:
+    eslint: ^8.57.0 || ^9.0.0
+    typescript: ">=4.8.4 <5.9.0"
+  checksum: 10/096011772d1ba6236413b1a49b8ad4f8999c0dcad1192ab81a13a753a95bfaf18cb138db94302cb00c312d410c7f48bb35ac1521908a55967e1fbba641aebcc5
+  languageName: node
+  linkType: hard
+
 "@typescript-eslint/utils@npm:8.36.0":
   version: 8.36.0
   resolution: "@typescript-eslint/utils@npm:8.36.0"
@@ -12149,6 +12502,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@typescript-eslint/visitor-keys@npm:8.33.0":
+  version: 8.33.0
+  resolution: "@typescript-eslint/visitor-keys@npm:8.33.0"
+  dependencies:
+    "@typescript-eslint/types": "npm:8.33.0"
+    eslint-visitor-keys: "npm:^4.2.0"
+  checksum: 10/f7f030c296dd83feb144f74aa382a67e4bb521d250507ede839f762bb215036d99d191b2203ac7af9867e434e569e4071ee0737cbde41d0ec38c0197f0a8549d
+  languageName: node
+  linkType: hard
+
 "@typescript-eslint/visitor-keys@npm:8.36.0":
   version: 8.36.0
   resolution: "@typescript-eslint/visitor-keys@npm:8.36.0"
@@ -14031,6 +14394,20 @@ __metadata:
   languageName: node
   linkType: hard
 
+"array-includes@npm:^3.1.8":
+  version: 3.1.8
+  resolution: "array-includes@npm:3.1.8"
+  dependencies:
+    call-bind: "npm:^1.0.7"
+    define-properties: "npm:^1.2.1"
+    es-abstract: "npm:^1.23.2"
+    es-object-atoms: "npm:^1.0.0"
+    get-intrinsic: "npm:^1.2.4"
+    is-string: "npm:^1.0.7"
+  checksum: 10/290b206c9451f181fb2b1f79a3bf1c0b66bb259791290ffbada760c79b284eef6f5ae2aeb4bcff450ebc9690edd25732c4c73a3c2b340fcc0f4563aed83bf488
+  languageName: node
+  linkType: hard
+
 "array-includes@npm:^3.1.9":
   version: 3.1.9
   resolution: "array-includes@npm:3.1.9"
@@ -14054,6 +14431,20 @@ __metadata:
   languageName: node
   linkType: hard
 
+"array.prototype.findlastindex@npm:^1.2.5":
+  version: 1.2.5
+  resolution: "array.prototype.findlastindex@npm:1.2.5"
+  dependencies:
+    call-bind: "npm:^1.0.7"
+    define-properties: "npm:^1.2.1"
+    es-abstract: "npm:^1.23.2"
+    es-errors: "npm:^1.3.0"
+    es-object-atoms: "npm:^1.0.0"
+    es-shim-unscopables: "npm:^1.0.2"
+  checksum: 10/7c5c821f357cd53ab6cc305de8086430dd8d7a2485db87b13f843e868055e9582b1fd338f02338f67fc3a1603ceaf9610dd2a470b0b506f9d18934780f95b246
+  languageName: node
+  linkType: hard
+
 "array.prototype.findlastindex@npm:^1.2.6":
   version: 1.2.6
   resolution: "array.prototype.findlastindex@npm:1.2.6"
@@ -14069,6 +14460,18 @@ __metadata:
   languageName: node
   linkType: hard
 
+"array.prototype.flat@npm:^1.3.2":
+  version: 1.3.2
+  resolution: "array.prototype.flat@npm:1.3.2"
+  dependencies:
+    call-bind: "npm:^1.0.2"
+    define-properties: "npm:^1.2.0"
+    es-abstract: "npm:^1.22.1"
+    es-shim-unscopables: "npm:^1.0.0"
+  checksum: 10/d9d2f6f27584de92ec7995bc931103e6de722cd2498bdbfc4cba814fc3e52f056050a93be883018811f7c0a35875f5056584a0e940603a5e5934f0279896aebe
+  languageName: node
+  linkType: hard
+
 "array.prototype.flat@npm:^1.3.3":
   version: 1.3.3
   resolution: "array.prototype.flat@npm:1.3.3"
@@ -14081,6 +14484,18 @@ __metadata:
   languageName: node
   linkType: hard
 
+"array.prototype.flatmap@npm:^1.3.2":
+  version: 1.3.2
+  resolution: "array.prototype.flatmap@npm:1.3.2"
+  dependencies:
+    call-bind: "npm:^1.0.2"
+    define-properties: "npm:^1.2.0"
+    es-abstract: "npm:^1.22.1"
+    es-shim-unscopables: "npm:^1.0.0"
+  checksum: 10/33f20006686e0cbe844fde7fd290971e8366c6c5e3380681c2df15738b1df766dd02c7784034aeeb3b037f65c496ee54de665388288edb323a2008bb550f77ea
+  languageName: node
+  linkType: hard
+
 "array.prototype.flatmap@npm:^1.3.3":
   version: 1.3.3
   resolution: "array.prototype.flatmap@npm:1.3.3"
@@ -17691,7 +18106,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"dotenv@npm:^16.4.5, dotenv@npm:^16.5.0":
+"dotenv@npm:^16.0.3, dotenv@npm:^16.4.5, dotenv@npm:^16.5.0":
   version: 16.5.0
   resolution: "dotenv@npm:16.5.0"
   checksum: 10/e68a16834f1a41cc2dfb01563bc150668ad675e6cd09191211467b5c0806b6ecd6ec438e021aa8e01cd0e72d2b70ef4302bec7cc0fe15b6955f85230b62dc8a9
@@ -18239,7 +18654,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"es-shim-unscopables@npm:^1.0.2":
+"es-shim-unscopables@npm:^1.0.0, es-shim-unscopables@npm:^1.0.2":
   version: 1.0.2
   resolution: "es-shim-unscopables@npm:1.0.2"
   dependencies:
@@ -18566,7 +18981,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"eslint-config-prettier@npm:^10.0.1":
+"eslint-config-prettier@npm:^10.0.1, eslint-config-prettier@npm:^10.1.5":
   version: 10.1.5
   resolution: "eslint-config-prettier@npm:10.1.5"
   peerDependencies:
@@ -18608,6 +19023,18 @@ __metadata:
   languageName: node
   linkType: hard
 
+"eslint-module-utils@npm:^2.12.0":
+  version: 2.12.0
+  resolution: "eslint-module-utils@npm:2.12.0"
+  dependencies:
+    debug: "npm:^3.2.7"
+  peerDependenciesMeta:
+    eslint:
+      optional: true
+  checksum: 10/dd27791147eca17366afcb83f47d6825b6ce164abb256681e5de4ec1d7e87d8605641eb869298a0dbc70665e2446dbcc2f40d3e1631a9475dd64dd23d4ca5dee
+  languageName: node
+  linkType: hard
+
 "eslint-module-utils@npm:^2.12.1":
   version: 2.12.1
   resolution: "eslint-module-utils@npm:2.12.1"
@@ -18620,6 +19047,35 @@ __metadata:
   languageName: node
   linkType: hard
 
+"eslint-plugin-import@npm:^2.31.0":
+  version: 2.31.0
+  resolution: "eslint-plugin-import@npm:2.31.0"
+  dependencies:
+    "@rtsao/scc": "npm:^1.1.0"
+    array-includes: "npm:^3.1.8"
+    array.prototype.findlastindex: "npm:^1.2.5"
+    array.prototype.flat: "npm:^1.3.2"
+    array.prototype.flatmap: "npm:^1.3.2"
+    debug: "npm:^3.2.7"
+    doctrine: "npm:^2.1.0"
+    eslint-import-resolver-node: "npm:^0.3.9"
+    eslint-module-utils: "npm:^2.12.0"
+    hasown: "npm:^2.0.2"
+    is-core-module: "npm:^2.15.1"
+    is-glob: "npm:^4.0.3"
+    minimatch: "npm:^3.1.2"
+    object.fromentries: "npm:^2.0.8"
+    object.groupby: "npm:^1.0.3"
+    object.values: "npm:^1.2.0"
+    semver: "npm:^6.3.1"
+    string.prototype.trimend: "npm:^1.0.8"
+    tsconfig-paths: "npm:^3.15.0"
+  peerDependencies:
+    eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9
+  checksum: 10/6b76bd009ac2db0615d9019699d18e2a51a86cb8c1d0855a35fb1b418be23b40239e6debdc6e8c92c59f1468ed0ea8d7b85c817117a113d5cc225be8a02ad31c
+  languageName: node
+  linkType: hard
+
 "eslint-plugin-import@npm:^2.32.0":
   version: 2.32.0
   resolution: "eslint-plugin-import@npm:2.32.0"
@@ -18748,6 +19204,56 @@ __metadata:
   languageName: node
   linkType: hard
 
+"eslint@npm:^9.27.0":
+  version: 9.30.1
+  resolution: "eslint@npm:9.30.1"
+  dependencies:
+    "@eslint-community/eslint-utils": "npm:^4.2.0"
+    "@eslint-community/regexpp": "npm:^4.12.1"
+    "@eslint/config-array": "npm:^0.21.0"
+    "@eslint/config-helpers": "npm:^0.3.0"
+    "@eslint/core": "npm:^0.14.0"
+    "@eslint/eslintrc": "npm:^3.3.1"
+    "@eslint/js": "npm:9.30.1"
+    "@eslint/plugin-kit": "npm:^0.3.1"
+    "@humanfs/node": "npm:^0.16.6"
+    "@humanwhocodes/module-importer": "npm:^1.0.1"
+    "@humanwhocodes/retry": "npm:^0.4.2"
+    "@types/estree": "npm:^1.0.6"
+    "@types/json-schema": "npm:^7.0.15"
+    ajv: "npm:^6.12.4"
+    chalk: "npm:^4.0.0"
+    cross-spawn: "npm:^7.0.6"
+    debug: "npm:^4.3.2"
+    escape-string-regexp: "npm:^4.0.0"
+    eslint-scope: "npm:^8.4.0"
+    eslint-visitor-keys: "npm:^4.2.1"
+    espree: "npm:^10.4.0"
+    esquery: "npm:^1.5.0"
+    esutils: "npm:^2.0.2"
+    fast-deep-equal: "npm:^3.1.3"
+    file-entry-cache: "npm:^8.0.0"
+    find-up: "npm:^5.0.0"
+    glob-parent: "npm:^6.0.2"
+    ignore: "npm:^5.2.0"
+    imurmurhash: "npm:^0.1.4"
+    is-glob: "npm:^4.0.0"
+    json-stable-stringify-without-jsonify: "npm:^1.0.1"
+    lodash.merge: "npm:^4.6.2"
+    minimatch: "npm:^3.1.2"
+    natural-compare: "npm:^1.4.0"
+    optionator: "npm:^0.9.3"
+  peerDependencies:
+    jiti: "*"
+  peerDependenciesMeta:
+    jiti:
+      optional: true
+  bin:
+    eslint: bin/eslint.js
+  checksum: 10/bd3024f730c88a2d099455f5ec5be2d6293eaf1412eb5111427282e1060b7f87891168ccbded10b71fc7182e05151e42511ec29d4e0d4ece5e3151eaf8d54763
+  languageName: node
+  linkType: hard
+
 "eslint@npm:^9.32.0":
   version: 9.32.0
   resolution: "eslint@npm:9.32.0"
@@ -20347,6 +20853,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"google-protobuf@npm:^3.21.4":
+  version: 3.21.4
+  resolution: "google-protobuf@npm:3.21.4"
+  checksum: 10/0d87fe8ef221d105cbaa808f4024bd577638524d8e461469e3733f2e4933391ad4da86b7fcbd11e8781bee04eacf2e8ba19aaacd5f9deb336a220485841d980f
+  languageName: node
+  linkType: hard
+
 "gopd@npm:^1.0.1":
   version: 1.0.1
   resolution: "gopd@npm:1.0.1"
@@ -20459,6 +20972,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"grpc-web@npm:^1.5.0":
+  version: 1.5.0
+  resolution: "grpc-web@npm:1.5.0"
+  checksum: 10/e9791831cf9fc8762d9a832c3df9d885d7a9a5d98333e51e4920c66679cff5f015b2f286f32366eb66cf5347c0d9f02c54f195c55f5cf334c026bc0398a13ce1
+  languageName: node
+  linkType: hard
+
 "gzip-size@npm:^6.0.0":
   version: 6.0.0
   resolution: "gzip-size@npm:6.0.0"
@@ -21433,7 +21953,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-core-module@npm:^2.13.0":
+"is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1":
   version: 2.15.1
   resolution: "is-core-module@npm:2.15.1"
   dependencies:
@@ -23159,7 +23679,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"lodash.isequal@npm:4.5.0":
+"lodash.isequal@npm:4.5.0, lodash.isequal@npm:^4.5.0":
   version: 4.5.0
   resolution: "lodash.isequal@npm:4.5.0"
   checksum: 10/82fc58a83a1555f8df34ca9a2cd300995ff94018ac12cc47c349655f0ae1d4d92ba346db4c19bbfc90510764e0c00ddcc985a358bdcd4b3b965abf8f2a48a214
@@ -24961,6 +25481,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"object.values@npm:^1.2.0":
+  version: 1.2.0
+  resolution: "object.values@npm:1.2.0"
+  dependencies:
+    call-bind: "npm:^1.0.7"
+    define-properties: "npm:^1.2.1"
+    es-object-atoms: "npm:^1.0.0"
+  checksum: 10/db2e498019c354428c5dd30d02980d920ac365b155fce4dcf63eb9433f98ccf0f72624309e182ce7cc227c95e45d474e1d483418e60de2293dd23fa3ebe34903
+  languageName: node
+  linkType: hard
+
 "object.values@npm:^1.2.1":
   version: 1.2.1
   resolution: "object.values@npm:1.2.1"
@@ -26324,6 +26855,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"prettier@npm:^3.5.3":
+  version: 3.5.3
+  resolution: "prettier@npm:3.5.3"
+  bin:
+    prettier: bin/prettier.cjs
+  checksum: 10/7050c08f674d9e49fbd9a4c008291d0715471f64e94cc5e4b01729affce221dfc6875c8de7e66b728c64abc9352eefb7eaae071b5f79d30081be207b53774b78
+  languageName: node
+  linkType: hard
+
 "prettier@npm:^3.6.2":
   version: 3.6.2
   resolution: "prettier@npm:3.6.2"
@@ -28078,7 +28618,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"secure-random@npm:1.1.2":
+"secure-random@npm:1.1.2, secure-random@npm:^1.1.2":
   version: 1.1.2
   resolution: "secure-random@npm:1.1.2"
   checksum: 10/8b5d32df870346a9400a6a31c0c4da4862df0416289fef7ec8bfda1187cf2ae08a281f57d174287f9a43b5e757478d22631c7dc2582fddcd2cfafc1d92042d72
@@ -30399,6 +30939,20 @@ __metadata:
   languageName: node
   linkType: hard
 
+"typescript-eslint@npm:8.33.0":
+  version: 8.33.0
+  resolution: "typescript-eslint@npm:8.33.0"
+  dependencies:
+    "@typescript-eslint/eslint-plugin": "npm:8.33.0"
+    "@typescript-eslint/parser": "npm:8.33.0"
+    "@typescript-eslint/utils": "npm:8.33.0"
+  peerDependencies:
+    eslint: ^8.57.0 || ^9.0.0
+    typescript: ">=4.8.4 <5.9.0"
+  checksum: 10/45c3ac8859eea71171f1ffb422fa71c7f5b60ea3b01ed4e655d9604057408b144c961c52fa07c9d75c65d18ffbf3a0c433ff688a48a73b7afe5bcc4811fb401e
+  languageName: node
+  linkType: hard
+
 "typescript-eslint@npm:8.38.0":
   version: 8.38.0
   resolution: "typescript-eslint@npm:8.38.0"
@@ -30953,6 +31507,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"utf-8-validate@npm:^6.0.2":
+  version: 6.0.5
+  resolution: "utf-8-validate@npm:6.0.5"
+  dependencies:
+    node-gyp: "npm:latest"
+    node-gyp-build: "npm:^4.3.0"
+  checksum: 10/8c96d342064d3f03d7acf616fe727e484825f4f5f7a455059122787306b2df1a4e23c2d27f16bf7ba21293f4ce6ab3e683b893fe7b4c74ac9d43b871c10001a0
+  languageName: node
+  linkType: hard
+
 "utf-8-validate@npm:^6.0.3":
   version: 6.0.4
   resolution: "utf-8-validate@npm:6.0.4"
@@ -31101,6 +31665,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"varint@npm:^6.0.0":
+  version: 6.0.0
+  resolution: "varint@npm:6.0.0"
+  checksum: 10/7684113c9d497c01e40396e50169c502eb2176203219b96e1c5ac965a3e15b4892bd22b7e48d87148e10fffe638130516b6dbeedd0efde2b2d0395aa1772eea7
+  languageName: node
+  linkType: hard
+
 "varuint-bitcoin@npm:1.1.2, varuint-bitcoin@npm:^1.0.4, varuint-bitcoin@npm:^1.1.2":
   version: 1.1.2
   resolution: "varuint-bitcoin@npm:1.1.2"
@@ -31311,7 +31882,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"vitest@npm:^3.2.4":
+"vitest@npm:^3.1.4, vitest@npm:^3.2.4":
   version: 3.2.4
   resolution: "vitest@npm:3.2.4"
   dependencies:
