Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a410cbc
wip: multiversx integration
popenta Jun 18, 2025
9b4d6e8
add MultiversX Signer
popenta Jun 20, 2025
2ad75f1
add tests for multiversx signer
popenta Jun 25, 2025
f174495
wip: integration
popenta Jun 26, 2025
ba30e5a
wip: mvx provider
popenta Jun 27, 2025
288e59e
fix mvx icon
popenta Jul 1, 2025
8d5b0b2
fix typo
popenta Jul 1, 2025
f0b5ea8
account state and token balance
popenta Jul 3, 2025
2fd06be
fix display transaction age
popenta Jul 3, 2025
8a7ceae
activity handler
popenta Jul 3, 2025
0c66cc3
wip: send transaction flow
popenta Jul 11, 2025
104935c
transaction timestamp fix
popenta Jul 22, 2025
856300c
Merge branch 'main' into multiversx-integration
popenta Jul 30, 2025
4e85dd0
update mvx sdk and fixes
popenta Jul 30, 2025
0ed3504
small fixes
popenta Jul 30, 2025
01d99e2
wip: nft/esdt integration
popenta Aug 1, 2025
8bee4ad
add support for esdt & nft tokens
popenta Aug 26, 2025
a49a6aa
esdt token integration
popenta Aug 29, 2025
1421b8b
Merge branch 'main' into multiversx-integration
popenta Aug 29, 2025
a9f9d4f
small fixes
popenta Aug 29, 2025
85968fc
update readme
popenta Aug 29, 2025
e59c3e4
fix displaying incorrect transaction status after sending tx
popenta Sep 1, 2025
37e6dc1
set token when sending from token details
popenta Sep 1, 2025
b4a2ada
Merge pull request #754 from enkryptcom/develop
kvhnuke Sep 16, 2025
6cfc45f
Merge branch 'main' into multiversx-integration
popenta Sep 17, 2025
e9558d9
change api and explorer url for mainnet
popenta Sep 17, 2025
3127bb2
small fixes
popenta Sep 22, 2025
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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Enkrypt is a web3 wallet built from the ground up to support the multi-chain fut
- Ethereum
- Bitcoin
- Solana
- MultiversX
- Acala
- Amplitude
- Arbitrum
Expand Down
2 changes: 2 additions & 0 deletions packages/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"@metaplex-foundation/mpl-bubblegum": "^5.0.2",
"@metaplex-foundation/umi": "^1.4.1",
"@metaplex-foundation/umi-bundle-defaults": "^1.4.1",
"@multiversx/sdk-core": "^15.0.0",
"@multiversx/sdk-transaction-decoder": "^2.0.0",
"@polkadot/api": "^16.4.7",
"@polkadot/extension-inject": "^0.61.7",
"@polkadot/keyring": "^13.5.6",
Expand Down
35 changes: 18 additions & 17 deletions packages/extension/src/libs/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
import DomainState from '@/libs/domain-state';
import { sendToWindow } from '@/libs/messenger/extension';
import PersistentEvents from '@/libs/persistent-events';
import TabInfo from '@/libs/utils/tab-info';
import Providers from '@/providers';
import {
InternalMethods,
InternalOnMessageResponse,
Message,
} from '@/types/messenger';
import { RPCRequestType, OnMessageResponse } from '@enkryptcom/types';
import { ProviderName } from '@/types/provider';
import { OnMessageResponse, RPCRequestType } from '@enkryptcom/types';
import { v4 as randomUUID } from 'uuid';
import Browser from 'webextension-polyfill';
import { getCustomError } from '../error';
import KeyRingBase from '../keyring/keyring';
import { sendToWindow } from '@/libs/messenger/extension';
import { ProviderName } from '@/types/provider';
import Providers from '@/providers';
import Browser from 'webextension-polyfill';
import TabInfo from '@/libs/utils/tab-info';
import PersistentEvents from '@/libs/persistent-events';
import DomainState from '@/libs/domain-state';
import { TabProviderType, ProviderType, ExternalMessageOptions } from './types';
import SettingsState from '../settings-state';
import { getProviderNetworkByName } from '../utils/networks';
import { handlePersistentEvents } from './external';
import {
sign,
getEthereumPubKey,
ethereumDecrypt,
unlock,
changeNetwork,
sendToTab,
newAccount,
ethereumDecrypt,
getEthereumPubKey,
lock,
newAccount,
sendToTab,
sign,
unlock,
} from './internal';
import { handlePersistentEvents } from './external';
import SettingsState from '../settings-state';
import { ExternalMessageOptions, ProviderType, TabProviderType } from './types';

class BackgroundHandler {
#keyring: KeyRingBase;
Expand All @@ -48,6 +48,7 @@ class BackgroundHandler {
[ProviderName.bitcoin]: {},
[ProviderName.kadena]: {},
[ProviderName.solana]: {},
[ProviderName.multiversx]: {},
[ProviderName.massa]: {},
};
this.#providers = Providers;
Expand Down
7 changes: 5 additions & 2 deletions packages/extension/src/libs/background/types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import BitcoinProvider from '@/providers/bitcoin';
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';
import MultiversXProvider from '@/providers/multiversx';
import type PolkadotProvider from '@/providers/polkadot';
import SolanaProvider from '@/providers/solana';

export interface TabProviderType {
[key: string]: Record<
Expand All @@ -13,6 +14,7 @@ export interface TabProviderType {
| BitcoinProvider
| KadenaProvider
| SolanaProvider
| MultiversXProvider
| MassaProvider
>;
}
Expand All @@ -23,6 +25,7 @@ export interface ProviderType {
| typeof BitcoinProvider
| typeof KadenaProvider
| typeof SolanaProvider
| typeof MultiversXProvider
| typeof MassaProvider;
}
export interface ExternalMessageOptions {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 15 additions & 4 deletions packages/extension/src/libs/utils/initialize-wallet.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import KeyRing from '@/libs/keyring/keyring';
import EthereumNetworks from '@/providers/ethereum/networks';
import PolkadotNetworks from '@/providers/polkadot/networks';
import { getAccountsByNetworkName } from '@/libs/utils/accounts';
import BitcoinNetworks from '@/providers/bitcoin/networks';
import EthereumNetworks from '@/providers/ethereum/networks';
import KadenaNetworks from '@/providers/kadena/networks';
import SolanaNetworks from '@/providers/solana/networks';
import MassaNetworks from '@/providers/massa/networks';
import MultiversXNetworks from '@/providers/multiversx/networks';
import PolkadotNetworks from '@/providers/polkadot/networks';
import SolanaNetworks from '@/providers/solana/networks';
import { NetworkNames, WalletType } from '@enkryptcom/types';
import { getAccountsByNetworkName } from '@/libs/utils/accounts';
import BackupState from '../backup-state';
export const initAccounts = async (keyring: KeyRing) => {
const secp256k1btc = (
Expand All @@ -24,6 +25,9 @@ export const initAccounts = async (keyring: KeyRing) => {
const ed25519sol = (
await getAccountsByNetworkName(NetworkNames.Solana)
).filter(acc => !acc.isTestWallet);
const ed25519mvx = (
await getAccountsByNetworkName(NetworkNames.MultiversX)
).filter(acc => !acc.isTestWallet);
const ed25519massa = (
await getAccountsByNetworkName(NetworkNames.Massa)
).filter(acc => !acc.isTestWallet);
Expand Down Expand Up @@ -62,6 +66,13 @@ export const initAccounts = async (keyring: KeyRing) => {
signerType: SolanaNetworks.solana.signer[0],
walletType: WalletType.mnemonic,
});
if (ed25519mvx.length == 0)
await keyring.saveNewAccount({
basePath: MultiversXNetworks.multiversx.basePath,
name: 'MultiversX Account 1',
signerType: MultiversXNetworks.multiversx.signer[0],
walletType: WalletType.mnemonic,
});
if (ed25519massa.length == 0)
await keyring.saveNewAccount({
basePath: MassaNetworks.Massa.basePath,
Expand Down
53 changes: 31 additions & 22 deletions packages/extension/src/libs/utils/networks.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
import { ProviderName } from '@/types/provider';
import { NetworkNames } from '@enkryptcom/types';
import EthereumNetworks from '@/providers/ethereum/networks';
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 { BaseNetwork } from '@/types/base-network';
import CustomNetworksState from '../custom-networks-state';
import { CustomEvmNetwork } from '@/providers/ethereum/types/custom-evm-network';
import Ethereum from '@/providers/ethereum/networks/eth';
import Polkadot from '@/providers/polkadot/networks/polkadot';
import Bitcoin from '@/providers/bitcoin/networks/bitcoin';
import EthereumNetworks from '@/providers/ethereum/networks';
import Ethereum from '@/providers/ethereum/networks/eth';
import { CustomEvmNetwork } from '@/providers/ethereum/types/custom-evm-network';
import KadenaNetworks from '@/providers/kadena/networks';
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';
import MultiversXNetworks from '@/providers/multiversx/networks';
import MultiversX from '@/providers/multiversx/networks/multiversx';
import PolkadotNetworks from '@/providers/polkadot/networks';
import Polkadot from '@/providers/polkadot/networks/polkadot';
import SolanaNetworks from '@/providers/solana/networks';
import Solana from '@/providers/solana/networks/solana';
import { BaseNetwork } from '@/types/base-network';
import { ProviderName } from '@/types/provider';
import { NetworkNames } from '@enkryptcom/types';
import CustomNetworksState from '../custom-networks-state';

const providerNetworks: Record<ProviderName, Record<string, BaseNetwork>> = {
[ProviderName.ethereum]: EthereumNetworks,
[ProviderName.polkadot]: PolkadotNetworks,
[ProviderName.bitcoin]: BitcoinNetworks,
[ProviderName.kadena]: KadenaNetworks,
[ProviderName.solana]: SolanaNetworks,
[ProviderName.multiversx]: MultiversXNetworks,
[ProviderName.massa]: MassaNetworks,
[ProviderName.enkrypt]: {},
};
Expand All @@ -38,6 +41,7 @@ const getAllNetworks = async (
.concat(Object.values(BitcoinNetworks) as BaseNetwork[])
.concat(Object.values(KadenaNetworks) as BaseNetwork[])
.concat(Object.values(SolanaNetworks) as BaseNetwork[])
.concat(Object.values(MultiversXNetworks) as BaseNetwork[])
.concat(Object.values(MassaNetworks) as BaseNetwork[]);

if (!includeCustom) {
Expand Down Expand Up @@ -72,13 +76,15 @@ 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_MULTIVERSX_NETWORK_NAME = NetworkNames.MultiversX;
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_MULTIVERSX_NETWORK = MultiversX;
const DEFAULT_MASSA_NETWORK = Massa;

const POPULAR_NAMES = [
Expand All @@ -92,22 +98,25 @@ const POPULAR_NAMES = [
NetworkNames.Rootstock,
NetworkNames.Optimism,
NetworkNames.Arbitrum,
NetworkNames.MultiversX,
];
export {
getAllNetworks,
getNetworkByName,
getProviderNetworkByName,
DEFAULT_EVM_NETWORK_NAME,
DEFAULT_SUBSTRATE_NETWORK_NAME,
DEFAULT_BTC_NETWORK,
DEFAULT_BTC_NETWORK_NAME,
POPULAR_NAMES,
DEFAULT_EVM_NETWORK,
DEFAULT_SUBSTRATE_NETWORK,
DEFAULT_BTC_NETWORK,
DEFAULT_EVM_NETWORK_NAME,
DEFAULT_KADENA_NETWORK,
DEFAULT_KADENA_NETWORK_NAME,
DEFAULT_SOLANA_NETWORK,
DEFAULT_SOLANA_NETWORK_NAME,
DEFAULT_MASSA_NETWORK,
DEFAULT_MASSA_NETWORK_NAME,
DEFAULT_MULTIVERSX_NETWORK,
DEFAULT_MULTIVERSX_NETWORK_NAME,
DEFAULT_SOLANA_NETWORK,
DEFAULT_SOLANA_NETWORK_NAME,
DEFAULT_SUBSTRATE_NETWORK,
DEFAULT_SUBSTRATE_NETWORK_NAME,
getAllNetworks,
getNetworkByName,
getProviderNetworkByName,
POPULAR_NAMES,
};
8 changes: 5 additions & 3 deletions packages/extension/src/providers/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import EthereumProvider from '@/providers/ethereum';
import PolkadotProvider from '@/providers/polkadot';
import BitcoinProvider from '@/providers/bitcoin';
import EthereumProvider from '@/providers/ethereum';
import KadenaProvider from '@/providers/kadena';
import SolanaProvider from '@/providers/solana';
import MassaProvider from '@/providers/massa';
import MultiversXProvider from '@/providers/multiversx';
import PolkadotProvider from '@/providers/polkadot';
import SolanaProvider from '@/providers/solana';
import { ProviderName } from '@/types/provider';

export default {
Expand All @@ -12,5 +13,6 @@ export default {
[ProviderName.bitcoin]: BitcoinProvider,
[ProviderName.kadena]: KadenaProvider,
[ProviderName.solana]: SolanaProvider,
[ProviderName.multiversx]: MultiversXProvider,
[ProviderName.massa]: MassaProvider,
};
83 changes: 83 additions & 0 deletions packages/extension/src/providers/multiversx/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import PublicKeyRing from '@/libs/keyring/public-keyring';

import getUiPath from '@/libs/utils/get-ui-path';
import {
BackgroundProviderInterface,
ProviderName,
ProviderRPCRequest,
} from '@/types/provider';
import getRequestProvider from '@enkryptcom/request';
import { MiddlewareFunction, OnMessageResponse } from '@enkryptcom/types';
import EventEmitter from 'events';
import Middlewares from './methods';
import Networks from './networks/index';
import { MultiversXNetwork } from './types/mvx-network';
import UIRoutes from './ui/routes/names';

class MultiversXProvider
extends EventEmitter
implements BackgroundProviderInterface
{
override listeners(event: string | symbol): ((...args: any[]) => void)[] {
// Cast each Function to the expected type
return super.listeners(event) as ((...args: any[]) => void)[];
}

UIRoutes = UIRoutes;
toWindow: (message: string) => void;
network: MultiversXNetwork;
requestProvider: any;
middlewares: MiddlewareFunction[] = [];
namespace: ProviderName;
KeyRing: PublicKeyRing;

constructor(
toWindow: (message: string) => void,
network: MultiversXNetwork = Networks.multiversx,
) {
super();
this.network = network;
this.toWindow = toWindow;
this.setMiddleWares();
this.requestProvider = getRequestProvider('', this.middlewares);
this.requestProvider.on('notification', (notif: any) => {
Comment on lines +42 to +43
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Initialize RequestProvider with the active network node.

Creating it with an empty string may route requests incorrectly until a later network change. Initialize with network.node up front.

-    this.requestProvider = getRequestProvider('', this.middlewares);
+    this.requestProvider = getRequestProvider(network.node, this.middlewares);
🤖 Prompt for AI Agents
In packages/extension/src/providers/multiversx/index.ts around lines 42-43, the
RequestProvider is being initialized with an empty string which can route
requests incorrectly; replace the empty string with the active network node
(e.g., network.node or this.network.node as appropriate in scope) when calling
getRequestProvider, ensuring the provider is created with the current node
upfront and keeping any existing logic that reinitializes the provider on
network changes.

this.sendNotification(JSON.stringify(notif));
});
this.namespace = ProviderName.multiversx;
this.KeyRing = new PublicKeyRing();
}

private setMiddleWares(): void {
this.middlewares = Middlewares.map(mw => mw.bind(this));
}

setRequestProvider(network: MultiversXNetwork): void {
this.network = network;
this.requestProvider.changeNetwork(network.node);
}

request(request: ProviderRPCRequest): Promise<OnMessageResponse> {
return this.requestProvider
.request(request)
.then((res: any) => ({
result: JSON.stringify(res),
}))
.catch((e: { message: any }) => ({
error: JSON.stringify(e.message),
}));
}

async sendNotification(notif: string): Promise<void> {
return this.toWindow(notif);
}

async isPersistentEvent(): Promise<boolean> {
return false;
}

getUIPath(page: string): string {
return getUiPath(page, this.namespace);
}
}

export default MultiversXProvider;
Loading