Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions packages/extension/src/libs/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class BackgroundHandler {
[ProviderName.bitcoin]: {},
[ProviderName.kadena]: {},
[ProviderName.solana]: {},
[ProviderName.massa]: {},
};
this.#providers = Providers;
}
Expand Down
5 changes: 4 additions & 1 deletion packages/extension/src/libs/background/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<
Expand All @@ -12,6 +13,7 @@ export interface TabProviderType {
| BitcoinProvider
| KadenaProvider
| SolanaProvider
| MassaProvider
>;
}
export interface ProviderType {
Expand All @@ -20,7 +22,8 @@ export interface ProviderType {
| typeof PolkadotProvider
| typeof BitcoinProvider
| typeof KadenaProvider
| typeof SolanaProvider;
| typeof SolanaProvider
| typeof MassaProvider;
}
export interface ExternalMessageOptions {
savePersistentEvents: boolean;
Expand Down
3 changes: 2 additions & 1 deletion packages/extension/src/libs/tokens-state/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
CustomToken,
CustomErc20Token,
TokenType,
CustomMassaToken,
} from './types';
import { NetworkNames } from '@enkryptcom/types';

Expand All @@ -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);

Expand Down
4 changes: 4 additions & 0 deletions packages/extension/src/libs/tokens-state/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[]>>;
11 changes: 11 additions & 0 deletions packages/extension/src/libs/utils/initialize-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
12 changes: 11 additions & 1 deletion packages/extension/src/libs/utils/networks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ 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,
[ProviderName.polkadot]: PolkadotNetworks,
[ProviderName.bitcoin]: BitcoinNetworks,
[ProviderName.kadena]: KadenaNetworks,
[ProviderName.solana]: SolanaNetworks,
[ProviderName.massa]: MassaNetworks,
[ProviderName.enkrypt]: {},
};
const getAllNetworks = async (
Expand All @@ -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;
}
Expand Down Expand Up @@ -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,
Expand All @@ -100,4 +108,6 @@ export {
DEFAULT_KADENA_NETWORK_NAME,
DEFAULT_SOLANA_NETWORK,
DEFAULT_SOLANA_NETWORK_NAME,
DEFAULT_MASSA_NETWORK,
DEFAULT_MASSA_NETWORK_NAME,
};
2 changes: 2 additions & 0 deletions packages/extension/src/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -11,4 +12,5 @@ export default {
[ProviderName.bitcoin]: BitcoinProvider,
[ProviderName.kadena]: KadenaProvider,
[ProviderName.solana]: SolanaProvider,
[ProviderName.massa]: MassaProvider,
};
92 changes: 92 additions & 0 deletions packages/extension/src/providers/massa/index.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import MassaActivity from './massa';

export { MassaActivity };
Original file line number Diff line number Diff line change
@@ -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;
60 changes: 60 additions & 0 deletions packages/extension/src/providers/massa/libs/api.ts
Original file line number Diff line number Diff line change
@@ -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();
}
}
19 changes: 19 additions & 0 deletions packages/extension/src/providers/massa/methods/index.ts
Original file line number Diff line number Diff line change
@@ -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();
},
];
};
Loading