From 18ca58dc56ff20692991d3ad396e3a8d165de1c2 Mon Sep 17 00:00:00 2001 From: Peterjah Date: Tue, 8 Jul 2025 10:50:06 +0200 Subject: [PATCH 001/109] Support Massa in browser extension --- packages/extension/package.json | 1 + .../extension/src/libs/background/index.ts | 1 + .../extension/src/libs/background/types.ts | 5 +- .../src/libs/utils/initialize-wallet.ts | 11 + packages/extension/src/libs/utils/networks.ts | 12 +- packages/extension/src/providers/index.ts | 2 + .../extension/src/providers/massa/index.ts | 92 +++ .../extension/src/providers/massa/libs/api.ts | 49 ++ .../src/providers/massa/methods/index.ts | 19 + .../massa/methods/massa_getBalance.ts | 46 ++ .../massa/methods/massa_getNetwork.ts | 25 + .../massa/methods/massa_setNetwork.ts | 57 ++ .../src/providers/massa/networks/buildnet.ts | 19 + .../massa/networks/icons/Massa_logo.webp | Bin 0 -> 1876 bytes .../src/providers/massa/networks/index.ts | 8 + .../src/providers/massa/networks/mainnet.ts | 18 + .../providers/massa/networks/massa-base.ts | 151 +++++ .../src/providers/massa/types/index.ts | 77 +++ .../src/providers/massa/ui/accounts/index.vue | 16 + .../extension/src/providers/massa/ui/index.ts | 9 + .../src/providers/massa/ui/libs/signer.ts | 107 ++++ .../src/providers/massa/ui/routes/index.ts | 12 + .../src/providers/massa/ui/routes/names.ts | 26 + .../components/send-address-input.vue | 229 +++++++ .../massa/ui/send-transaction/index.vue | 578 +++++++++++++++++ .../verify-transaction/index.vue | 441 +++++++++++++ .../src/providers/massa/ui/settings/index.vue | 16 + packages/extension/src/scripts/inject.ts | 6 + packages/extension/src/types/activity.ts | 6 +- packages/extension/src/types/base-network.ts | 7 +- packages/extension/src/types/provider.ts | 7 +- packages/extension/src/ui/action/App.vue | 5 +- .../action/views/network-activity/index.vue | 12 + .../action/views/send-transaction/index.vue | 2 + .../action/views/verify-transaction/index.vue | 2 + .../extension/src/ui/provider-pages/routes.ts | 2 + packages/keyring/package.json | 1 + packages/keyring/src/index.ts | 2 + packages/keyring/src/utils.ts | 3 + packages/signers/massa/package.json | 60 ++ packages/signers/massa/src/index.ts | 65 ++ packages/signers/massa/src/libs/ed25519.ts | 81 +++ packages/signers/massa/tests/sign.test.ts | 52 ++ packages/signers/massa/tsconfig.json | 29 + packages/signers/massa/tsconfig.paths.json | 8 + packages/types/package.json | 1 + packages/types/src/index.ts | 1 + packages/types/src/networks.ts | 3 + yarn.lock | 593 +++++++++++++++++- 49 files changed, 2957 insertions(+), 18 deletions(-) create mode 100644 packages/extension/src/providers/massa/index.ts create mode 100644 packages/extension/src/providers/massa/libs/api.ts create mode 100644 packages/extension/src/providers/massa/methods/index.ts create mode 100644 packages/extension/src/providers/massa/methods/massa_getBalance.ts create mode 100644 packages/extension/src/providers/massa/methods/massa_getNetwork.ts create mode 100644 packages/extension/src/providers/massa/methods/massa_setNetwork.ts create mode 100644 packages/extension/src/providers/massa/networks/buildnet.ts create mode 100644 packages/extension/src/providers/massa/networks/icons/Massa_logo.webp create mode 100644 packages/extension/src/providers/massa/networks/index.ts create mode 100644 packages/extension/src/providers/massa/networks/mainnet.ts create mode 100644 packages/extension/src/providers/massa/networks/massa-base.ts create mode 100644 packages/extension/src/providers/massa/types/index.ts create mode 100644 packages/extension/src/providers/massa/ui/accounts/index.vue create mode 100644 packages/extension/src/providers/massa/ui/index.ts create mode 100644 packages/extension/src/providers/massa/ui/libs/signer.ts create mode 100644 packages/extension/src/providers/massa/ui/routes/index.ts create mode 100644 packages/extension/src/providers/massa/ui/routes/names.ts create mode 100644 packages/extension/src/providers/massa/ui/send-transaction/components/send-address-input.vue create mode 100644 packages/extension/src/providers/massa/ui/send-transaction/index.vue create mode 100644 packages/extension/src/providers/massa/ui/send-transaction/verify-transaction/index.vue create mode 100644 packages/extension/src/providers/massa/ui/settings/index.vue create mode 100644 packages/signers/massa/package.json create mode 100644 packages/signers/massa/src/index.ts create mode 100644 packages/signers/massa/src/libs/ed25519.ts create mode 100644 packages/signers/massa/tests/sign.test.ts create mode 100644 packages/signers/massa/tsconfig.json create mode 100644 packages/signers/massa/tsconfig.paths.json diff --git a/packages/extension/package.json b/packages/extension/package.json index 8218c3344..a4279826b 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.20250722105131", "@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/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.ethereum]: EthereumNetworks, @@ -20,6 +22,7 @@ const providerNetworks: Record> = { [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..9910077b2 --- /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 +{ + private 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 { + return false; + } + + async sendNotification(notif: string): Promise { + return this.toWindow(notif); + } + + request(request: ProviderRPCRequest): Promise { + 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/api.ts b/packages/extension/src/providers/massa/libs/api.ts new file mode 100644 index 000000000..481df8189 --- /dev/null +++ b/packages/extension/src/providers/massa/libs/api.ts @@ -0,0 +1,49 @@ +import { ProviderAPIInterface } from '@/types/provider'; +import { JsonRpcPublicProvider, 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 {} + + async getBalance(address: string): Promise { + const [account] = await this.provider.balanceOf([address], false); + if (!account) return '0'; + return account.balance.toString(); + } + + async getMinimalFee(): Promise { + 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 { + try { + return this.provider.getOperationStatus(opId); + } catch (error) { + return null; + } + } + + async getNodeStatus(): Promise { + 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..914d0c637 --- /dev/null +++ b/packages/extension/src/providers/massa/methods/massa_getBalance.ts @@ -0,0 +1,46 @@ +import { MiddlewareFunction } from '@enkryptcom/types'; +import { + BackgroundProviderInterface, + ProviderRPCRequest, +} from '@/types/provider'; +import { Address } from '@massalabs/massa-web3'; +import { getCustomError } from '@/libs/error'; + +const isValidMassaAddress = (address: string): boolean => { + try { + Address.fromString(address); + } catch (error) { + return false; + } + return true; +}; + +const method: MiddlewareFunction = async function ( + this: BackgroundProviderInterface, + payload: ProviderRPCRequest, + res, + next, +): Promise { + if (payload.method !== 'massa_getBalance') return next(); + else { + try { + const address = payload.params?.[0]; + if (!address || !isValidMassaAddress(address)) { + res(getCustomError('Please enter a valid Massa address')); + return; + } + + const currentNetwork = this.getCurrentNetwork(); + + const api = await currentNetwork.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..401cb849d --- /dev/null +++ b/packages/extension/src/providers/massa/methods/massa_getNetwork.ts @@ -0,0 +1,25 @@ +import { MiddlewareFunction } from '@enkryptcom/types'; +import { + BackgroundProviderInterface, + ProviderRPCRequest, +} from '@/types/provider'; +import { NetworkNames } from '@enkryptcom/types'; + +const method: MiddlewareFunction = async function ( + this: BackgroundProviderInterface, + payload: ProviderRPCRequest, + res, + next, +): Promise { + if (payload.method !== 'massa_getNetwork') return next(); + else { + try { + const currentNetwork = this.getCurrentNetwork(); + res(null, currentNetwork.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..50497b253 --- /dev/null +++ b/packages/extension/src/providers/massa/methods/massa_setNetwork.ts @@ -0,0 +1,57 @@ +import { MiddlewareFunction } from '@enkryptcom/types'; +import { + BackgroundProviderInterface, + ProviderRPCRequest, +} from '@/types/provider'; +import { getCustomError } from '@/libs/error'; +import massaNetworks from '../networks'; + +const method: MiddlewareFunction = async function ( + this: BackgroundProviderInterface, + payload: ProviderRPCRequest, + res, + next, +): Promise { + 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 0000000000000000000000000000000000000000..8ab091f596fa25457208baa0c9eded8d065ee600 GIT binary patch literal 1876 zcmV-a2dnr}Nk&FY2LJ$9MM6+kP&iCK2LJ#sKfn(V^#+2rZR7BVz3rzE5fcEJRaf+7 zc-m!I+h$18+TQ)|sypJ3$ZTH5P209@+qP}n?jH8E>u>}BAfTLW+qN&erXJ8W*__&J zTdNz5-L`GpE(UHJDRS?`jB{V0ux*J1L_VIxzNs?*n+P1A{+qP}nwr$(&z4%Clk)$;AU#bt7vk05mw&Ezj z2Q4LP7+j$OBXO`hNV_M8f!nrmqyoD)V?E#C!ZQH~1Po;8zyCY*=We9~Kvy^sNd=vZ zu*iDX3LVoMHmLeywY$fD-4J#ae`2B|)uvCL+Ro7u zS5j*Y9F6>HXK9nk;t7rUh)O=8kfgoZ8gbgbe3OKvmj7#ia{7OwCEyhD6QQ!}&S!6O z9e|b#ovR!qpoAy41n?H;i`Y)uXS06n5XGBtnsficnb`{foK!gF{0Fje1I7cuSy|Iq zXEa-5t>DaYgb=&Lk$P6~0eDsDR#{Ih3DF`EKm#X*L9sut#-Ik-3HO4mn55RratE%{Pfj^Dl zvl3y5-Fmoqk4XUBV}Is&5F&jt0oaDwyE&nnEKC#vUo0PnC}{I~PmC}O@ZV9LUf zjG#EZb^A3n&&y0I@p;+z0iCGUa!$q)1^`z+b-eO9x!Je5V_qM3Bs!o~INysON2%bw zA?)}Yys53M(R?@%=Vn*$=J|oMvKH{X&UdS>Wvi_wHNacu2YthiI5UCzyGG`^6OZW( zRDE^UI4yU|^#`G{8Xr>$$?~|?d@K4G^dccmnA;pyJt$rlea9CMhgS_pR1V5RYPNKgA@&+#D?cOow#Ce*1vgsCwRLy2ug$OB7?o63cElQy|ELCNs~C z5Tg_GUwBd~$)@^`I+R>0rzV>ZsP5Ffg&lN^VTYd6au=sX6UAku4i#4s5k^|?*4a>Z?W#^L znAGLORo4>B{)?1E0MdMv7Ok}^5omV1#XkiexTR z)0n=|Aie#>^K03sUESqq(-LmCFh(+__gwV zTDp&@1bREQUB)Sr+KMy0HRlqL3>t(NK8v1G8344OxQ5?>*u7WShnG$#g+xO)=RZ3o ze*$IZ4tJ%-83*!{SK&2*Q)9>b45!A4x$eYVcj_VIqo$3wIRwDZ z75HA4c55i}s1~~gKG{_<8-S!b7bk6GoI0{{0Dy~n7x8hp=gri+~%%+kzutC5OK zS;e2kaywB?08N_$_+{DMqj;y-y$Jv(!7@S=7XI**=F8g0qo>@MBS zhcrhft(|)s8z7)99%^RN%?A#vl8yQ2m3d5O)?UmkT|A{t_%nfS=_z-1Sz=h5 zyy8}}{%l77uM740``bAlRLIdZ@~d{8;U#CAb4JuA%&quDxC~*MVBp-@2Pp%UbmeFK zWW!XZ#(OLIsq=utl%&nhy%zr$iFW($4q|n^OKDQq!DIdojUCn*-b3yR)2N)bY^tj?P OTsQEU_}_(J;s5~XDw!t$ literal 0 HcmV?d00001 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..41c8b74e8 --- /dev/null +++ b/packages/extension/src/providers/massa/networks/massa-base.ts @@ -0,0 +1,151 @@ +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 ActivityState from '@/libs/activity-state'; +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'; + +export class MassaNetwork extends BaseNetwork { + chainId: bigint; + + constructor(options: MassaNetworkOptions) { + super(options); + this.chainId = options.chainId!; + } + + async getAllTokens(): Promise { + return []; + } + + async getAllTokenInfo(address: string): Promise { + 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: balanceFormatted, + balancef: balanceDisplayFormatted, + balanceUSD, + balanceUSDf, + value: price, + valuef: priceFormatted, + decimals: this.decimals, + sparkline: sparklineData, + priceChangePercentage, + // No contract for native token + }; + + return [nativeTokenAsset]; + } catch (error) { + return []; + } + } + + async getAllActivity(address: string): Promise { + try { + const activityState = new ActivityState(); + const activities = await activityState.getAllActivities({ + address, + network: this.name, + }); + return activities; + } catch (error) { + return []; + } + } +} + +// 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, + 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..e7b5ecd93 --- /dev/null +++ b/packages/extension/src/providers/massa/types/index.ts @@ -0,0 +1,77 @@ +import { NetworkName } from '@massalabs/massa-web3'; +import { BaseNetworkOptions } from '@/types/base-network'; +import { CHAIN_ID } from '@massalabs/massa-web3'; +import { ToTokenData } from '@/ui/action/types/token'; +import { EnkryptAccount } from '@enkryptcom/types'; +import { BaseNetwork } from '@/types/base-network'; + +export const MassaNetworks = NetworkName; + +export interface MassaNetworkOptions extends BaseNetworkOptions { + chainId?: (typeof CHAIN_ID)[keyof typeof CHAIN_ID]; +} + +export interface MassaRawInfo { + hash: string; + blockNumber: number; + timestamp: number; + from: string; + to: string; + value: string; + status: boolean; +} + +export interface MassaTransaction { + from: string; + to: string; + amount: string; + fee?: string; + data?: string; + validityStartPeriod?: number; +} + +export interface MassaSignInInput { + address: string; + privateKey: string; +} + +export interface MassaSignInOutput { + address: string; + publicKey: string; +} + +export interface MassaAccount { + address: string; + balance: string; + activeRolls: number; + candidateRolls: number; +} + +export interface TxFeeInfo { + nativeValue: string; + fiatValue: string; + nativeSymbol: string; + fiatSymbol: string; +} + +export interface SendTransactionDataType { + from: string; + value: string; + to: string; + data: `0x${string}`; +} + +export interface VerifyTransactionParams { + fromAddress: string; + fromAddressName: string; + toAddress: string; + toToken: ToTokenData; + txFee: TxFeeInfo; + TransactionData: SendTransactionDataType; +} + +export interface SignerTransactionOptions { + transaction: Buffer; + account: EnkryptAccount; + network: BaseNetwork; +} diff --git a/packages/extension/src/providers/massa/ui/accounts/index.vue b/packages/extension/src/providers/massa/ui/accounts/index.vue new file mode 100644 index 000000000..bbf565373 --- /dev/null +++ b/packages/extension/src/providers/massa/ui/accounts/index.vue @@ -0,0 +1,16 @@ + + + + + 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..827659aef --- /dev/null +++ b/packages/extension/src/providers/massa/ui/libs/signer.ts @@ -0,0 +1,107 @@ +import { InternalMethods, InternalOnMessageResponse } from '@/types/messenger'; +import { bufferToHex } from '@enkryptcom/utils'; +import sendUsingInternalMessengers from '@/libs/messenger/internal-messenger'; +import { BaseNetwork } from '@/types/base-network'; +import { EnkryptAccount } from '@enkryptcom/types'; +import { + Address, + OperationManager, + OperationType, + PublicKey, + TransferOperation, +} from '@massalabs/massa-web3'; +import { MassaNetworkOptions } from '../../types'; + +export interface MassaTransactionOptions { + account: EnkryptAccount; + network: BaseNetwork; + payload: { + from: string; + to: string; + amount: string; + fee: string; + expirePeriod: number; + }; +} + +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 => { + const { account, payload, network } = options; + + // Create the message to sign (similar to Ethereum's getHashedMessageToSign) + const operationDetails: TransferOperation = { + type: OperationType.Transaction, + amount: BigInt(payload.amount), + recipientAddress: Address.fromString(payload.to), + fee: BigInt(payload.fee), + expirePeriod: payload.expirePeriod, //3060678 + }; + 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 => { + 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..4aed65ec6 --- /dev/null +++ b/packages/extension/src/providers/massa/ui/routes/names.ts @@ -0,0 +1,26 @@ +import { RouteRecordRaw } from 'vue-router'; + +const routes: Record = { + 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'), + }, + accounts: { + path: 'accounts', + name: 'massa-accounts', + component: () => import('../accounts/index.vue'), + }, + settings: { + path: 'settings', + name: 'massa-settings', + component: () => import('../settings/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..f6fd30e55 --- /dev/null +++ b/packages/extension/src/providers/massa/ui/send-transaction/components/send-address-input.vue @@ -0,0 +1,229 @@ + + + + + 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..cd2664097 --- /dev/null +++ b/packages/extension/src/providers/massa/ui/send-transaction/index.vue @@ -0,0 +1,578 @@ + + + + + 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..7dfec69fb --- /dev/null +++ b/packages/extension/src/providers/massa/ui/send-transaction/verify-transaction/index.vue @@ -0,0 +1,441 @@ + + + + + diff --git a/packages/extension/src/providers/massa/ui/settings/index.vue b/packages/extension/src/providers/massa/ui/settings/index.vue new file mode 100644 index 000000000..399d7716e --- /dev/null +++ b/packages/extension/src/providers/massa/ui/settings/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/packages/extension/src/scripts/inject.ts b/packages/extension/src/scripts/inject.ts index 5fed1666d..c738bcc11 100644 --- a/packages/extension/src/scripts/inject.ts +++ b/packages/extension/src/scripts/inject.ts @@ -9,6 +9,7 @@ import PolkadotProvider from '@/providers/polkadot/inject'; import BitcoinProvider from '@/providers/bitcoin/inject'; import KadenaProvider from '@/providers/kadena/inject'; import SolanaProvider from '@/providers/solana/inject'; +import MassaProvider from '@/providers/massa/inject'; import { InternalMethods } from '@/types/messenger'; @@ -43,6 +44,11 @@ const loadInjectedProviders = () => { type: ProviderType.solana, sendMessageHandler: providerSendMessage, }); + MassaProvider(window, { + name: ProviderName.massa, + type: ProviderType.massa, + sendMessageHandler: providerSendMessage, + }); }; loadInjectedProviders(); diff --git a/packages/extension/src/types/activity.ts b/packages/extension/src/types/activity.ts index 48eb4fe84..c6d7f8843 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 { 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 | Promise | Promise - | Promise; + | Promise + | Promise; customTokens?: boolean; } @@ -80,7 +82,8 @@ export abstract class BaseNetwork { | Promise | Promise | Promise - | Promise; + | Promise + | Promise; public customTokens: boolean; constructor(options: BaseNetworkOptions) { diff --git a/packages/extension/src/types/provider.ts b/packages/extension/src/types/provider.ts index 0f831c71b..c33da6fa8 100644 --- a/packages/extension/src/types/provider.ts +++ b/packages/extension/src/types/provider.ts @@ -24,6 +24,7 @@ import { KadenaRawInfo, SOLRawInfo, } from './activity'; +import { OperationStatus } from '@massalabs/massa-web3'; export enum ProviderName { enkrypt = 'enkrypt', @@ -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 = ( @@ -122,6 +125,7 @@ export abstract class BackgroundProviderInterface extends EventEmitter { abstract getUIPath(page: string): string; abstract isPersistentEvent(request: ProviderRPCRequest): Promise; abstract sendNotification(notif: string): Promise; + abstract getCurrentNetwork(): BaseNetwork; } /** @@ -144,6 +148,7 @@ export abstract class ProviderAPIInterface { | BTCRawInfo | KadenaRawInfo | SOLRawInfo + | OperationStatus | null >; } @@ -169,7 +174,7 @@ export type Provider = | PolkadotProvider | BitcoinProvider | KadenaProvider - | SolanaProvider; + | SolanaProvider export interface ProviderRequestOptions { url: string; 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..ec079c17d 100644 --- a/packages/extension/src/ui/action/views/network-activity/index.vue +++ b/packages/extension/src/ui/action/views/network-activity/index.vue @@ -79,6 +79,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 +218,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 OperationStatus; + 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/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.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.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 { + 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 { + 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 { + 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..8ef586a8e 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.20250722105131" "@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.20250722105131": + version: 5.2.1-dev.20250722105131 + resolution: "@massalabs/massa-web3@npm:5.2.1-dev.20250722105131" + 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/3f6e0d4f2953f8642d1b498f0df444e5be621a282527c60e4a226308ad636e25463c9711fb70ee22a2f25bfa718dac2e935e0db2192161881e7b1f52048ba7ed + 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: From 59761a584180fd522deb05f5d010fcecb2db4200 Mon Sep 17 00:00:00 2001 From: Peterjah Date: Tue, 29 Jul 2025 12:28:27 +0200 Subject: [PATCH 002/109] add custom token support in asset view --- .../extension/src/libs/tokens-state/index.ts | 35 +- .../extension/src/libs/tokens-state/types.ts | 4 + .../extension/src/providers/massa/libs/api.ts | 8 +- .../providers/massa/networks/massa-base.ts | 141 +++++- .../src/providers/massa/types/index.ts | 5 + .../src/providers/massa/ui/accounts/index.vue | 16 - .../src/providers/massa/ui/routes/names.ts | 10 - .../components/send-address-input.vue | 37 +- .../src/providers/massa/ui/settings/index.vue | 16 - .../components/custom-massa-token.vue | 478 ++++++++++++++++++ .../ui/action/views/network-assets/index.vue | 12 +- 11 files changed, 680 insertions(+), 82 deletions(-) delete mode 100644 packages/extension/src/providers/massa/ui/accounts/index.vue delete mode 100644 packages/extension/src/providers/massa/ui/settings/index.vue create mode 100644 packages/extension/src/ui/action/views/network-assets/components/custom-massa-token.vue diff --git a/packages/extension/src/libs/tokens-state/index.ts b/packages/extension/src/libs/tokens-state/index.ts index 8feb22300..764fe6655 100644 --- a/packages/extension/src/libs/tokens-state/index.ts +++ b/packages/extension/src/libs/tokens-state/index.ts @@ -5,6 +5,7 @@ import { StorageKeys, CustomToken, CustomErc20Token, + CustomMassaToken, TokenType, } from './types'; import { NetworkNames } from '@enkryptcom/types'; @@ -17,14 +18,14 @@ export class TokensState { } /** - * Add a new custom ERC20 token for a given network. + * Add a new custom token for a given network. * Returns `true` if the token was added and false otherwise. * @param {NetworkNames} chainName - The name of the network the token is being added to. - * @param {CustomErc20Token} token - The token information being added. + * @param {CustomToken} token - The token information being added. */ - async addErc20Token( + async addCustomToken( chainName: NetworkNames, - token: CustomErc20Token, + token: CustomErc20Token | CustomMassaToken, ): Promise { let state: IState | null = await this.storage.get(StorageKeys.customTokens); @@ -54,6 +55,32 @@ export class TokensState { return true; } + /** + * Add a new custom ERC20 token for a given network. + * Returns `true` if the token was added and false otherwise. + * @param {NetworkNames} chainName - The name of the network the token is being added to. + * @param {CustomErc20Token} token - The token information being added. + */ + async addErc20Token( + chainName: NetworkNames, + token: CustomErc20Token, + ): Promise { + return this.addCustomToken(chainName, token); + } + + /** + * Add a new custom Massa token for a given network. + * Returns `true` if the token was added and false otherwise. + * @param {NetworkNames} chainName - The name of the network the token is being added to. + * @param {CustomMassaToken} token - The token information being added. + */ + async addMassaToken( + chainName: NetworkNames, + token: CustomMassaToken, + ): Promise { + return this.addCustomToken(chainName, token); + } + /** * Remove a custom ERC20 token from a given network. * Returns `true` if the token was removed and false otherwise. 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>; diff --git a/packages/extension/src/providers/massa/libs/api.ts b/packages/extension/src/providers/massa/libs/api.ts index 481df8189..50eafa8d3 100644 --- a/packages/extension/src/providers/massa/libs/api.ts +++ b/packages/extension/src/providers/massa/libs/api.ts @@ -1,5 +1,5 @@ import { ProviderAPIInterface } from '@/types/provider'; -import { JsonRpcPublicProvider, OperationStatus } from '@massalabs/massa-web3'; +import { JsonRpcPublicProvider, MRC20, OperationStatus } from '@massalabs/massa-web3'; export default class MassaAPI extends ProviderAPIInterface { public provider: JsonRpcPublicProvider; @@ -25,6 +25,12 @@ export default class MassaAPI extends ProviderAPIInterface { return account.balance.toString(); } + async getBalanceMRC20(address: string, contract: string): Promise { + const mrc20 = new MRC20(this.provider, contract); + const balance = await mrc20.balanceOf(address); + return balance.toString(); + } + async getMinimalFee(): Promise { try { const networkInfo = await this.provider.networkInfos(); diff --git a/packages/extension/src/providers/massa/networks/massa-base.ts b/packages/extension/src/providers/massa/networks/massa-base.ts index 41c8b74e8..8924f901d 100644 --- a/packages/extension/src/providers/massa/networks/massa-base.ts +++ b/packages/extension/src/providers/massa/networks/massa-base.ts @@ -4,7 +4,6 @@ import MassaAPI from '../libs/api'; import { SignerType } from '@enkryptcom/types'; import { ProviderName } from '@/types/provider'; import { MassaNetworkOptions } from '../types'; -import ActivityState from '@/libs/activity-state'; import { Activity } from '@/types/activity'; import { AssetsType } from '@/types/provider'; import { fromBase } from '@enkryptcom/utils'; @@ -13,13 +12,21 @@ 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'; export class MassaNetwork extends BaseNetwork { chainId: bigint; + private activityHandler?: ( + network: BaseNetwork, + address: string, + ) => Promise; constructor(options: MassaNetworkOptions) { super(options); this.chainId = options.chainId!; + this.activityHandler = options.activityHandler; } async getAllTokens(): Promise { @@ -92,23 +99,134 @@ export class MassaNetwork extends BaseNetwork { // No contract for native token }; - return [nativeTokenAsset]; + 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 { - try { - const activityState = new ActivityState(); - const activities = await activityState.getAllActivities({ - address, - network: this.name, - }); - return activities; - } catch (error) { - return []; + if (this.activityHandler) { + return this.activityHandler(this, address); } + return []; } } @@ -142,6 +260,7 @@ export function createMassaNetworkOptions(config: { basePath: "m/44'/632'", chainId: config.chainId, coingeckoID: config.coingeckoID, + customTokens: true, api: async () => { const api = new MassaAPI(config.node); await api.init(); diff --git a/packages/extension/src/providers/massa/types/index.ts b/packages/extension/src/providers/massa/types/index.ts index e7b5ecd93..b4f438fd2 100644 --- a/packages/extension/src/providers/massa/types/index.ts +++ b/packages/extension/src/providers/massa/types/index.ts @@ -4,11 +4,16 @@ import { CHAIN_ID } from '@massalabs/massa-web3'; import { ToTokenData } from '@/ui/action/types/token'; import { EnkryptAccount } from '@enkryptcom/types'; 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; } export interface MassaRawInfo { diff --git a/packages/extension/src/providers/massa/ui/accounts/index.vue b/packages/extension/src/providers/massa/ui/accounts/index.vue deleted file mode 100644 index bbf565373..000000000 --- a/packages/extension/src/providers/massa/ui/accounts/index.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - - - diff --git a/packages/extension/src/providers/massa/ui/routes/names.ts b/packages/extension/src/providers/massa/ui/routes/names.ts index 4aed65ec6..7ab9121ba 100644 --- a/packages/extension/src/providers/massa/ui/routes/names.ts +++ b/packages/extension/src/providers/massa/ui/routes/names.ts @@ -11,16 +11,6 @@ const routes: Record = { name: 'massa-verify', component: () => import('../send-transaction/verify-transaction/index.vue'), }, - accounts: { - path: 'accounts', - name: 'massa-accounts', - component: () => import('../accounts/index.vue'), - }, - settings: { - path: 'settings', - name: 'massa-settings', - component: () => import('../settings/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 index f6fd30e55..32ba485c0 100644 --- 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 @@ -7,20 +7,12 @@ alt="" @error="handleIdenticonError" /> -
- - - -
+

To:

@@ -118,6 +110,13 @@ const identiconSrc = computed(() => { 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 ''; @@ -215,15 +214,7 @@ const handleIdenticonError = () => { } &__avatar-placeholder { - width: 32px; - height: 32px; - border-radius: 100%; - background: @buttonBg; - box-shadow: inset 0px 0px 1px rgba(0, 0, 0, 0.16); - display: flex; - align-items: center; - justify-content: center; - color: @tertiaryLabel; + opacity: 0.6; } } diff --git a/packages/extension/src/providers/massa/ui/settings/index.vue b/packages/extension/src/providers/massa/ui/settings/index.vue deleted file mode 100644 index 399d7716e..000000000 --- a/packages/extension/src/providers/massa/ui/settings/index.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - - - 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..bcf9d38d5 --- /dev/null +++ b/packages/extension/src/ui/action/views/network-assets/components/custom-massa-token.vue @@ -0,0 +1,478 @@ + + + + \ No newline at end of file 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..5f368076f 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 @@ />
- + + @@ -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,10 @@ 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(); From 1c58e9449aaa50cb9d836090ce12b895f305e489 Mon Sep 17 00:00:00 2001 From: Peterjah Date: Thu, 31 Jul 2025 09:46:55 +0200 Subject: [PATCH 003/109] support MRC20 sending --- packages/extension/package.json | 2 +- .../extension/src/libs/tokens-state/index.ts | 34 +-- .../extension/src/providers/massa/index.ts | 2 +- .../massa/libs/activity-handlers/index.ts | 3 + .../massa/libs/activity-handlers/massa.ts | 27 ++ .../extension/src/providers/massa/libs/api.ts | 9 +- .../massa/methods/massa_getBalance.ts | 26 +- .../massa/methods/massa_getNetwork.ts | 11 +- .../massa/methods/massa_setNetwork.ts | 8 +- .../providers/massa/networks/massa-base.ts | 51 ++-- .../src/providers/massa/types/index.ts | 55 +--- .../src/providers/massa/ui/libs/signer.ts | 45 +++- .../components/send-address-input.vue | 19 +- .../components/send-token-select.vue | 118 +++++++++ .../massa/ui/send-transaction/index.vue | 237 ++++++++++++------ .../verify-transaction/index.vue | 84 +++++-- packages/extension/src/scripts/inject.ts | 6 - packages/extension/src/types/activity.ts | 1 + packages/extension/src/types/provider.ts | 7 +- .../action/views/network-activity/index.vue | 3 +- .../components/custom-massa-token.vue | 48 ++-- .../ui/action/views/network-assets/index.vue | 8 +- yarn.lock | 10 +- 23 files changed, 528 insertions(+), 286 deletions(-) create mode 100644 packages/extension/src/providers/massa/libs/activity-handlers/index.ts create mode 100644 packages/extension/src/providers/massa/libs/activity-handlers/massa.ts create mode 100644 packages/extension/src/providers/massa/ui/send-transaction/components/send-token-select.vue diff --git a/packages/extension/package.json b/packages/extension/package.json index a4279826b..ff7af2231 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -39,7 +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.20250722105131", + "@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/tokens-state/index.ts b/packages/extension/src/libs/tokens-state/index.ts index 764fe6655..b86a5ec00 100644 --- a/packages/extension/src/libs/tokens-state/index.ts +++ b/packages/extension/src/libs/tokens-state/index.ts @@ -5,8 +5,8 @@ import { StorageKeys, CustomToken, CustomErc20Token, - CustomMassaToken, TokenType, + CustomMassaToken, } from './types'; import { NetworkNames } from '@enkryptcom/types'; @@ -18,12 +18,12 @@ export class TokensState { } /** - * Add a new custom token for a given network. + * Add a new custom ERC20 token for a given network. * Returns `true` if the token was added and false otherwise. * @param {NetworkNames} chainName - The name of the network the token is being added to. - * @param {CustomToken} token - The token information being added. + * @param {CustomErc20Token} token - The token information being added. */ - async addCustomToken( + async addErc20Token( chainName: NetworkNames, token: CustomErc20Token | CustomMassaToken, ): Promise { @@ -55,32 +55,6 @@ export class TokensState { return true; } - /** - * Add a new custom ERC20 token for a given network. - * Returns `true` if the token was added and false otherwise. - * @param {NetworkNames} chainName - The name of the network the token is being added to. - * @param {CustomErc20Token} token - The token information being added. - */ - async addErc20Token( - chainName: NetworkNames, - token: CustomErc20Token, - ): Promise { - return this.addCustomToken(chainName, token); - } - - /** - * Add a new custom Massa token for a given network. - * Returns `true` if the token was added and false otherwise. - * @param {NetworkNames} chainName - The name of the network the token is being added to. - * @param {CustomMassaToken} token - The token information being added. - */ - async addMassaToken( - chainName: NetworkNames, - token: CustomMassaToken, - ): Promise { - return this.addCustomToken(chainName, token); - } - /** * Remove a custom ERC20 token from a given network. * Returns `true` if the token was removed and false otherwise. diff --git a/packages/extension/src/providers/massa/index.ts b/packages/extension/src/providers/massa/index.ts index 9910077b2..6ed5245a8 100644 --- a/packages/extension/src/providers/massa/index.ts +++ b/packages/extension/src/providers/massa/index.ts @@ -19,7 +19,7 @@ export default class MassaProvider extends EventEmitter implements BackgroundProviderInterface { - private network: BaseNetwork; + public network: BaseNetwork; requestProvider: RequestClass; middlewares: MiddlewareFunction[] = []; namespace: string; 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 => { + 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 index 50eafa8d3..03c45f4a0 100644 --- a/packages/extension/src/providers/massa/libs/api.ts +++ b/packages/extension/src/providers/massa/libs/api.ts @@ -1,5 +1,10 @@ import { ProviderAPIInterface } from '@/types/provider'; -import { JsonRpcPublicProvider, MRC20, OperationStatus } from '@massalabs/massa-web3'; +import { + JsonRpcPublicProvider, + MRC20, + NodeStatusInfo, + OperationStatus, +} from '@massalabs/massa-web3'; export default class MassaAPI extends ProviderAPIInterface { public provider: JsonRpcPublicProvider; @@ -49,7 +54,7 @@ export default class MassaAPI extends ProviderAPIInterface { } } - async getNodeStatus(): Promise { + async getNodeStatus(): Promise { return this.provider.getNodeStatus(); } } diff --git a/packages/extension/src/providers/massa/methods/massa_getBalance.ts b/packages/extension/src/providers/massa/methods/massa_getBalance.ts index 914d0c637..a7ff97509 100644 --- a/packages/extension/src/providers/massa/methods/massa_getBalance.ts +++ b/packages/extension/src/providers/massa/methods/massa_getBalance.ts @@ -1,22 +1,12 @@ import { MiddlewareFunction } from '@enkryptcom/types'; -import { - BackgroundProviderInterface, - ProviderRPCRequest, -} from '@/types/provider'; +import { ProviderRPCRequest } from '@/types/provider'; import { Address } from '@massalabs/massa-web3'; import { getCustomError } from '@/libs/error'; - -const isValidMassaAddress = (address: string): boolean => { - try { - Address.fromString(address); - } catch (error) { - return false; - } - return true; -}; +import MassaProvider from '..'; +import { MassaNetwork } from '../networks/massa-base'; const method: MiddlewareFunction = async function ( - this: BackgroundProviderInterface, + this: MassaProvider, payload: ProviderRPCRequest, res, next, @@ -25,15 +15,13 @@ const method: MiddlewareFunction = async function ( else { try { const address = payload.params?.[0]; - if (!address || !isValidMassaAddress(address)) { + const network = this.network as MassaNetwork; + if (!address || !network.isValidAddress(address)) { res(getCustomError('Please enter a valid Massa address')); return; } - const currentNetwork = this.getCurrentNetwork(); - - const api = await currentNetwork.api(); - + const api = await network.api(); const balance = await api.getBalance(address); res(null, balance); diff --git a/packages/extension/src/providers/massa/methods/massa_getNetwork.ts b/packages/extension/src/providers/massa/methods/massa_getNetwork.ts index 401cb849d..ac12aea67 100644 --- a/packages/extension/src/providers/massa/methods/massa_getNetwork.ts +++ b/packages/extension/src/providers/massa/methods/massa_getNetwork.ts @@ -1,12 +1,10 @@ import { MiddlewareFunction } from '@enkryptcom/types'; -import { - BackgroundProviderInterface, - ProviderRPCRequest, -} from '@/types/provider'; +import { ProviderRPCRequest } from '@/types/provider'; import { NetworkNames } from '@enkryptcom/types'; +import MassaProvider from '..'; const method: MiddlewareFunction = async function ( - this: BackgroundProviderInterface, + this: MassaProvider, payload: ProviderRPCRequest, res, next, @@ -14,8 +12,7 @@ const method: MiddlewareFunction = async function ( if (payload.method !== 'massa_getNetwork') return next(); else { try { - const currentNetwork = this.getCurrentNetwork(); - res(null, currentNetwork.name); + res(null, this.network.name); } catch (error) { res(null, NetworkNames.Massa); } diff --git a/packages/extension/src/providers/massa/methods/massa_setNetwork.ts b/packages/extension/src/providers/massa/methods/massa_setNetwork.ts index 50497b253..d8d895d51 100644 --- a/packages/extension/src/providers/massa/methods/massa_setNetwork.ts +++ b/packages/extension/src/providers/massa/methods/massa_setNetwork.ts @@ -1,13 +1,11 @@ import { MiddlewareFunction } from '@enkryptcom/types'; -import { - BackgroundProviderInterface, - ProviderRPCRequest, -} from '@/types/provider'; +import { ProviderRPCRequest } from '@/types/provider'; import { getCustomError } from '@/libs/error'; import massaNetworks from '../networks'; +import MassaProvider from '..'; const method: MiddlewareFunction = async function ( - this: BackgroundProviderInterface, + this: MassaProvider, payload: ProviderRPCRequest, res, next, diff --git a/packages/extension/src/providers/massa/networks/massa-base.ts b/packages/extension/src/providers/massa/networks/massa-base.ts index 8924f901d..1158a30eb 100644 --- a/packages/extension/src/providers/massa/networks/massa-base.ts +++ b/packages/extension/src/providers/massa/networks/massa-base.ts @@ -13,8 +13,15 @@ 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 { + 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; @@ -26,7 +33,8 @@ export class MassaNetwork extends BaseNetwork { constructor(options: MassaNetworkOptions) { super(options); this.chainId = options.chainId!; - this.activityHandler = options.activityHandler; + this.activityHandler = + options.activityHandler || wrapActivityHandler(MassaActivity); } async getAllTokens(): Promise { @@ -87,7 +95,7 @@ export class MassaNetwork extends BaseNetwork { name: this.currencyNameLong, symbol: this.currencyName, icon: this.icon, - balance: balanceFormatted, + balance, balancef: balanceDisplayFormatted, balanceUSD, balanceUSDf, @@ -96,7 +104,6 @@ export class MassaNetwork extends BaseNetwork { decimals: this.decimals, sparkline: sparklineData, priceChangePercentage, - // No contract for native token }; const assets = [nativeTokenAsset]; @@ -125,16 +132,18 @@ export class MassaNetwork extends BaseNetwork { 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 - }; - }); + 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 @@ -179,8 +188,9 @@ export class MassaNetwork extends BaseNetwork { }; // Check if token is a stablecoin (contains DAI or USD in symbol) - const isStablecoin = token.symbol.toUpperCase().includes('DAI') || - token.symbol.toUpperCase().includes('USD'); + const isStablecoin = + token.symbol.toUpperCase().includes('DAI') || + token.symbol.toUpperCase().includes('USD'); if (isStablecoin) { // Use $1 price for stablecoins @@ -228,6 +238,15 @@ export class MassaNetwork extends BaseNetwork { } return []; } + + isValidAddress = (address: string): boolean => { + try { + Address.fromString(address); + } catch (error) { + return false; + } + return true; + }; } // Helper function to create standard Massa network options diff --git a/packages/extension/src/providers/massa/types/index.ts b/packages/extension/src/providers/massa/types/index.ts index b4f438fd2..08d37ad26 100644 --- a/packages/extension/src/providers/massa/types/index.ts +++ b/packages/extension/src/providers/massa/types/index.ts @@ -1,8 +1,6 @@ -import { NetworkName } from '@massalabs/massa-web3'; +import { NetworkName, CHAIN_ID } from '@massalabs/massa-web3'; import { BaseNetworkOptions } from '@/types/base-network'; -import { CHAIN_ID } from '@massalabs/massa-web3'; import { ToTokenData } from '@/ui/action/types/token'; -import { EnkryptAccount } from '@enkryptcom/types'; import { BaseNetwork } from '@/types/base-network'; import { Activity } from '@/types/activity'; @@ -16,42 +14,6 @@ export interface MassaNetworkOptions extends BaseNetworkOptions { ) => Promise; } -export interface MassaRawInfo { - hash: string; - blockNumber: number; - timestamp: number; - from: string; - to: string; - value: string; - status: boolean; -} - -export interface MassaTransaction { - from: string; - to: string; - amount: string; - fee?: string; - data?: string; - validityStartPeriod?: number; -} - -export interface MassaSignInInput { - address: string; - privateKey: string; -} - -export interface MassaSignInOutput { - address: string; - publicKey: string; -} - -export interface MassaAccount { - address: string; - balance: string; - activeRolls: number; - candidateRolls: number; -} - export interface TxFeeInfo { nativeValue: string; fiatValue: string; @@ -59,24 +21,11 @@ export interface TxFeeInfo { fiatSymbol: string; } -export interface SendTransactionDataType { - from: string; - value: string; - to: string; - data: `0x${string}`; -} - export interface VerifyTransactionParams { fromAddress: string; fromAddressName: string; toAddress: string; toToken: ToTokenData; + toTokenAddress?: string; txFee: TxFeeInfo; - TransactionData: SendTransactionDataType; -} - -export interface SignerTransactionOptions { - transaction: Buffer; - account: EnkryptAccount; - network: BaseNetwork; } diff --git a/packages/extension/src/providers/massa/ui/libs/signer.ts b/packages/extension/src/providers/massa/ui/libs/signer.ts index 827659aef..69dab7896 100644 --- a/packages/extension/src/providers/massa/ui/libs/signer.ts +++ b/packages/extension/src/providers/massa/ui/libs/signer.ts @@ -1,10 +1,12 @@ import { InternalMethods, InternalOnMessageResponse } from '@/types/messenger'; -import { bufferToHex } from '@enkryptcom/utils'; +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, @@ -16,11 +18,16 @@ 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; }; } @@ -43,16 +50,34 @@ export const MassaTransactionSigner = ( ): Promise => { const { account, payload, network } = options; - // Create the message to sign (similar to Ethereum's getHashedMessageToSign) - const operationDetails: TransferOperation = { - type: OperationType.Transaction, - amount: BigInt(payload.amount), - recipientAddress: Address.fromString(payload.to), - fee: BigInt(payload.fee), - expirePeriod: payload.expirePeriod, //3060678 - }; - const chainId = (network as MassaNetworkOptions).chainId; + 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!, 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 index 32ba485c0..6ff6bd897 100644 --- 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 @@ -37,8 +37,8 @@ import { replaceWithEllipsis } from '@/ui/action/utils/filters'; import { computed, ref } from 'vue'; import { PropType } from 'vue'; -import { BaseNetwork } from '@/types/base-network'; import { Address } from '@massalabs/massa-web3'; +import { MassaNetwork } from '../../../networks/massa-base'; const isFocus = ref(false); const addressInput = ref(); @@ -58,7 +58,7 @@ const props = defineProps({ }, }, network: { - type: Object as PropType, + type: Object as PropType, default: () => ({}), }, from: { @@ -74,19 +74,12 @@ const emit = defineEmits<{ }>(); const massaAddress = computed(() => { - if (props.value && props.value.length > 66) - return props.network.displayAddress(props.value); - else return props.value; + return props.value; }); const isValidMassaAddress = computed(() => { if (!massaAddress.value || massaAddress.value.trim() === '') return false; - try { - Address.fromString(massaAddress.value.trim()); - return true; - } catch (error) { - return false; - } + return props.network.isValidAddress(massaAddress.value); }); const identiconSrc = computed(() => { @@ -112,7 +105,9 @@ const identiconSrc = computed(() => { const placeholderIdenticonSrc = computed(() => { if (props.network && props.network.identicon) { - return props.network.identicon('000000000000000000000000000000000000000000000000000000000000000000'); + return props.network.identicon( + '000000000000000000000000000000000000000000000000000000000000000000', + ); } return ''; }); 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 @@ + + + + + diff --git a/packages/extension/src/providers/massa/ui/send-transaction/index.vue b/packages/extension/src/providers/massa/ui/send-transaction/index.vue index cd2664097..81390c31b 100644 --- a/packages/extension/src/providers/massa/ui/send-transaction/index.vue +++ b/packages/extension/src/providers/massa/ui/send-transaction/index.vue @@ -46,15 +46,45 @@ @close="toggleSelectContactTo" /> + + + + + +
Minimal fee from network
- -
@@ -95,13 +115,15 @@ diff --git a/packages/signers/massa/src/crypto/ed25519.ts b/packages/signers/massa/src/crypto/ed25519.ts index 6549a75a4..8f447bf0c 100644 --- a/packages/signers/massa/src/crypto/ed25519.ts +++ b/packages/signers/massa/src/crypto/ed25519.ts @@ -1,6 +1,6 @@ -import * as ed from "@noble/ed25519"; +import { etc, utils, getPublicKey, sign, verify } from "@noble/ed25519"; import { sha512 } from "@noble/hashes/sha2"; -ed.etc.sha512Sync = sha512; // Use the sha512 implementation from noble +etc.sha512Sync = sha512; // Use the sha512 implementation from noble import Signer from "./interfaces/signer"; /** @@ -9,17 +9,17 @@ import Signer from "./interfaces/signer"; export default class Ed25519 implements Signer { // eslint-disable-next-line class-methods-use-this -- Expected by the interface. generatePrivateKey(): Uint8Array { - return ed.utils.randomPrivateKey(); + return utils.randomPrivateKey(); } // eslint-disable-next-line class-methods-use-this -- Expected by the interface. async getPublicKey(privateKey: Uint8Array): Promise { - return ed.getPublicKey(privateKey); + return getPublicKey(privateKey); } // eslint-disable-next-line class-methods-use-this -- Expected by the interface. async sign(privateKey: Uint8Array, data: Uint8Array): Promise { - return ed.sign(data, privateKey); + return sign(data, privateKey); } // eslint-disable-next-line class-methods-use-this -- Expected by the interface. @@ -28,6 +28,6 @@ export default class Ed25519 implements Signer { data: Uint8Array, signature: Uint8Array, ): Promise { - return ed.verify(signature, data, publicKey); + return verify(signature, data, publicKey); } } From 95d0f8e9c9b049738b290b2e93603983cbaa41d8 Mon Sep 17 00:00:00 2001 From: kvhnuke <10602065+kvhnuke@users.noreply.github.com> Date: Thu, 28 Aug 2025 13:56:43 -0700 Subject: [PATCH 023/109] fix: build --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index e0071d9e5..5b454ee9c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1582,7 +1582,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" + "@massalabs/massa-web3": "npm:^5.2.1-dev" "@metamask/eth-sig-util": "npm:^8.2.0" "@metaplex-foundation/mpl-bubblegum": "npm:^5.0.2" "@metaplex-foundation/umi": "npm:^1.2.0" @@ -5586,7 +5586,7 @@ __metadata: languageName: node linkType: hard -"@massalabs/massa-web3@npm:5.2.1-dev.20250730141858, @massalabs/massa-web3@npm:^5.2.1-dev": +"@massalabs/massa-web3@npm:^5.2.1-dev": version: 5.2.1-dev.20250730141858 resolution: "@massalabs/massa-web3@npm:5.2.1-dev.20250730141858" dependencies: From 450b06998b84038bbd6f3b5218ded1b9519d2146 Mon Sep 17 00:00:00 2001 From: kvhnuke <10602065+kvhnuke@users.noreply.github.com> Date: Fri, 29 Aug 2025 10:50:16 -0700 Subject: [PATCH 024/109] devop: package updates --- packages/extension/package.json | 10 +- yarn.lock | 334 +++++++++++++++----------------- 2 files changed, 166 insertions(+), 178 deletions(-) diff --git a/packages/extension/package.json b/packages/extension/package.json index 6dc57d40b..9f2c0bb0c 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -23,7 +23,7 @@ "watch:firefox": "yarn prebuild && cross-env BROWSER='firefox' vite" }, "dependencies": { - "@amplitude/analytics-browser": "^2.23.4", + "@amplitude/analytics-browser": "^2.23.5", "@enkryptcom/extension-bridge": "workspace:^", "@enkryptcom/hw-wallets": "workspace:^", "@enkryptcom/keyring": "workspace:^", @@ -41,10 +41,10 @@ "@ledgerhq/hw-transport-webusb": "^6.29.9", "@metamask/eth-sig-util": "^8.2.0", "@metaplex-foundation/mpl-bubblegum": "^5.0.2", - "@metaplex-foundation/umi": "^1.2.0", - "@metaplex-foundation/umi-bundle-defaults": "^1.2.0", + "@metaplex-foundation/umi": "^1.4.0", + "@metaplex-foundation/umi-bundle-defaults": "^1.4.0", "@polkadot/api": "^16.4.6", - "@polkadot/extension-inject": "^0.61.6", + "@polkadot/extension-inject": "^0.61.7", "@polkadot/keyring": "^13.5.6", "@polkadot/rpc-provider": "^16.4.6", "@polkadot/types": "^16.4.6", @@ -52,7 +52,7 @@ "@polkadot/ui-shared": "^3.16.1", "@polkadot/util": "^13.5.6", "@polkadot/wasm-crypto": "^7.5.1", - "@solana-developers/helpers": "2.8.0", + "@solana-developers/helpers": "2.8.1", "@solana/spl-token": "^0.4.13", "@solana/wallet-standard-features": "^1.3.0", "@solana/web3.js": "^1.98.4", diff --git a/yarn.lock b/yarn.lock index 4e4292628..105e9b0ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,18 +30,18 @@ __metadata: languageName: node linkType: hard -"@amplitude/analytics-browser@npm:^2.23.4": - version: 2.23.4 - resolution: "@amplitude/analytics-browser@npm:2.23.4" +"@amplitude/analytics-browser@npm:^2.23.5": + version: 2.23.5 + resolution: "@amplitude/analytics-browser@npm:2.23.5" dependencies: - "@amplitude/analytics-core": "npm:^2.22.0" + "@amplitude/analytics-core": "npm:^2.22.1" "@amplitude/analytics-remote-config": "npm:^0.4.0" - "@amplitude/plugin-autocapture-browser": "npm:^1.11.0" - "@amplitude/plugin-network-capture-browser": "npm:^1.5.3" - "@amplitude/plugin-page-view-tracking-browser": "npm:^2.3.44" - "@amplitude/plugin-web-vitals-browser": "npm:^0.1.0-beta.19" + "@amplitude/plugin-autocapture-browser": "npm:^1.11.1" + "@amplitude/plugin-network-capture-browser": "npm:^1.5.4" + "@amplitude/plugin-page-view-tracking-browser": "npm:^2.3.45" + "@amplitude/plugin-web-vitals-browser": "npm:^0.1.0-beta.20" tslib: "npm:^2.4.1" - checksum: 10/ce49391ea98ad83016b6d9f1a1c773bbc35829b485ee28523027b6fe7977fafab07d04ff5e2c58f4a7b6b43ebbf4101f061cba03e86161c78ec1090d882dc2f3 + checksum: 10/0be260e992145837e7dd3ec012ceb12531f5574e986b5c833295c61c834913d08263d66bcbc66b6967763834128c616aaf950fc0b2e8d8444dddc5847d82ceef languageName: node linkType: hard @@ -57,15 +57,15 @@ __metadata: languageName: node linkType: hard -"@amplitude/analytics-client-common@npm:^2.3.38": - version: 2.3.38 - resolution: "@amplitude/analytics-client-common@npm:2.3.38" +"@amplitude/analytics-client-common@npm:^2.3.39": + version: 2.3.39 + resolution: "@amplitude/analytics-client-common@npm:2.3.39" dependencies: "@amplitude/analytics-connector": "npm:^1.4.8" - "@amplitude/analytics-core": "npm:^2.22.0" + "@amplitude/analytics-core": "npm:^2.22.1" "@amplitude/analytics-types": "npm:^2.10.0" tslib: "npm:^2.4.1" - checksum: 10/20a57bb6ecbe3d9053e44f5a8bbd2e1a6321ab1db7f4f9e157824f273f7e9145513d85c297adac794cdcf57cba6e6e5cd1f35fddfc9eacee1ece4a4544c14ec7 + checksum: 10/784ecd63636a9defc19846a2a98204955520e45411088f770a2b5db9bdd130fc4ea94287266d16bbffe9f6d2ef60477e60cbe2b7517acadd0659604337ed51e6 languageName: node linkType: hard @@ -116,13 +116,13 @@ __metadata: languageName: node linkType: hard -"@amplitude/analytics-core@npm:^2.22.0": - version: 2.22.0 - resolution: "@amplitude/analytics-core@npm:2.22.0" +"@amplitude/analytics-core@npm:^2.22.1": + version: 2.22.1 + resolution: "@amplitude/analytics-core@npm:2.22.1" dependencies: "@amplitude/analytics-connector": "npm:^1.6.4" tslib: "npm:^2.4.1" - checksum: 10/d6418ee14399c7cf96f08f4f5ae7ebb376dd85381695bd85fabce971905a105dc0711795142d0143047e607a58d2a1034623681fe1cc8ffac497d10209054701 + checksum: 10/f7f0a48408651f697927e354cf2bee059e92a680a3b2e98f4d2ed22d89ee0b2b752836e6f3678ad214f2cc2a61c6db42463002d6d7dd735d227ae5ee6be5a63c languageName: node linkType: hard @@ -177,41 +177,41 @@ __metadata: languageName: node linkType: hard -"@amplitude/plugin-autocapture-browser@npm:^1.11.0": - version: 1.11.0 - resolution: "@amplitude/plugin-autocapture-browser@npm:1.11.0" +"@amplitude/plugin-autocapture-browser@npm:^1.11.1": + version: 1.11.1 + resolution: "@amplitude/plugin-autocapture-browser@npm:1.11.1" dependencies: - "@amplitude/analytics-core": "npm:^2.22.0" + "@amplitude/analytics-core": "npm:^2.22.1" "@amplitude/analytics-remote-config": "npm:^0.6.3" rxjs: "npm:^7.8.1" tslib: "npm:^2.4.1" - checksum: 10/03c5c9b84024fa304e405bcd1510a05a04bfcac328a7ed64eb8d29048e8d1f0bd7203bf0594ed1e27ea9b7d2d395c9d97d6ac549cbf833e8fae53af6507a7b01 + checksum: 10/4aa7e93baccb86fb7fff6ec82d1b20ae1eb7689a6dc4c05714a9f8cc71c6ead2cb0ef797898dcaa060d012f351e14395eff70dcfb79ccee7a3058406505320d5 languageName: node linkType: hard -"@amplitude/plugin-network-capture-browser@npm:^1.5.3": - version: 1.5.3 - resolution: "@amplitude/plugin-network-capture-browser@npm:1.5.3" +"@amplitude/plugin-network-capture-browser@npm:^1.5.4": + version: 1.5.4 + resolution: "@amplitude/plugin-network-capture-browser@npm:1.5.4" dependencies: - "@amplitude/analytics-core": "npm:^2.22.0" + "@amplitude/analytics-core": "npm:^2.22.1" rxjs: "npm:^7.8.1" tslib: "npm:^2.4.1" - checksum: 10/f8a27f0c4fe29838345d2660e289e948d3e5ef7a653c727b3b1ca1cda53d5b3dd34217561437ff56a986f6c8615226cb762ff8741523cac41e14b81f6a909167 + checksum: 10/48c9589b9ef0676839f2582a17a32750279d72275662170a07d46dfad6d337994cca747cd7af97d1df491a88b056906b4c762850d76f8658f043b78138c431b9 languageName: node linkType: hard -"@amplitude/plugin-page-view-tracking-browser@npm:^2.3.44": - version: 2.3.44 - resolution: "@amplitude/plugin-page-view-tracking-browser@npm:2.3.44" +"@amplitude/plugin-page-view-tracking-browser@npm:^2.3.45": + version: 2.3.45 + resolution: "@amplitude/plugin-page-view-tracking-browser@npm:2.3.45" dependencies: - "@amplitude/analytics-client-common": "npm:^2.3.38" + "@amplitude/analytics-client-common": "npm:^2.3.39" "@amplitude/analytics-types": "npm:^2.10.0" tslib: "npm:^2.4.1" - checksum: 10/96a472f88901b4f837023c30238631dec7ae7051b10ff8fca102a4d0c9acb2ed4e4d3d57b37733b6968e94252a174f7569416fd8390638ee0c0b5ae2f42dd8b0 + checksum: 10/32c4232ea457b624988d8ecea4cadb8fa8764439a847241eec020f46cf7619197b8550c333465ff6192deca923528ecc40e26f51a88b54219557b63d67d862b6 languageName: node linkType: hard -"@amplitude/plugin-web-vitals-browser@npm:^0.1.0-beta.19": +"@amplitude/plugin-web-vitals-browser@npm:^0.1.0-beta.20": version: 0.1.0-frustrationanalytics.0 resolution: "@amplitude/plugin-web-vitals-browser@npm:0.1.0-frustrationanalytics.0" dependencies: @@ -1672,7 +1672,7 @@ __metadata: version: 0.0.0-use.local resolution: "@enkryptcom/extension@workspace:packages/extension" dependencies: - "@amplitude/analytics-browser": "npm:^2.23.4" + "@amplitude/analytics-browser": "npm:^2.23.5" "@crxjs/vite-plugin": "npm:^2.2.0" "@enkryptcom/extension-bridge": "workspace:^" "@enkryptcom/hw-wallets": "workspace:^" @@ -1691,10 +1691,10 @@ __metadata: "@ledgerhq/hw-transport-webusb": "npm:^6.29.9" "@metamask/eth-sig-util": "npm:^8.2.0" "@metaplex-foundation/mpl-bubblegum": "npm:^5.0.2" - "@metaplex-foundation/umi": "npm:^1.2.0" - "@metaplex-foundation/umi-bundle-defaults": "npm:^1.2.0" + "@metaplex-foundation/umi": "npm:^1.4.0" + "@metaplex-foundation/umi-bundle-defaults": "npm:^1.4.0" "@polkadot/api": "npm:^16.4.6" - "@polkadot/extension-inject": "npm:^0.61.6" + "@polkadot/extension-inject": "npm:^0.61.7" "@polkadot/keyring": "npm:^13.5.6" "@polkadot/rpc-provider": "npm:^16.4.6" "@polkadot/types": "npm:^16.4.6" @@ -1709,7 +1709,7 @@ __metadata: "@rollup/plugin-replace": "npm:^6.0.2" "@rollup/plugin-terser": "npm:^0.4.4" "@rollup/plugin-typescript": "npm:^12.1.4" - "@solana-developers/helpers": "npm:2.8.0" + "@solana-developers/helpers": "npm:2.8.1" "@solana/spl-token": "npm:^0.4.13" "@solana/wallet-standard-features": "npm:^1.3.0" "@solana/web3.js": "npm:^1.98.4" @@ -5997,196 +5997,184 @@ __metadata: languageName: node linkType: hard -"@metaplex-foundation/umi-bundle-defaults@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-bundle-defaults@npm:1.2.0" - dependencies: - "@metaplex-foundation/umi-downloader-http": "npm:^1.2.0" - "@metaplex-foundation/umi-eddsa-web3js": "npm:^1.0.1" - "@metaplex-foundation/umi-http-fetch": "npm:^1.2.0" - "@metaplex-foundation/umi-program-repository": "npm:^1.2.0" - "@metaplex-foundation/umi-rpc-chunk-get-accounts": "npm:^1.2.0" - "@metaplex-foundation/umi-rpc-web3js": "npm:^1.2.0" - "@metaplex-foundation/umi-serializer-data-view": "npm:^1.2.0" - "@metaplex-foundation/umi-transaction-factory-web3js": "npm:^1.2.0" - peerDependencies: - "@metaplex-foundation/umi": ^1.2.0 +"@metaplex-foundation/umi-bundle-defaults@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-bundle-defaults@npm:1.4.0" + dependencies: + "@metaplex-foundation/umi-downloader-http": "npm:^1.4.0" + "@metaplex-foundation/umi-eddsa-web3js": "npm:^1.4.0" + "@metaplex-foundation/umi-http-fetch": "npm:^1.4.0" + "@metaplex-foundation/umi-program-repository": "npm:^1.4.0" + "@metaplex-foundation/umi-rpc-chunk-get-accounts": "npm:^1.4.0" + "@metaplex-foundation/umi-rpc-web3js": "npm:^1.4.0" + "@metaplex-foundation/umi-serializer-data-view": "npm:^1.4.0" + "@metaplex-foundation/umi-transaction-factory-web3js": "npm:^1.4.0" + peerDependencies: + "@metaplex-foundation/umi": ^1.4.0 "@solana/web3.js": ^1.72.0 - checksum: 10/ac23fe03b0327fe39a645d6de55c5d6acf12d225d18e90ffe6fcf5c7f6b3272e84bd2be74dd17e850872f680ef22c1682b58559560c026ef2f3fc59192276b8f + checksum: 10/a2ecd67e847a85ec1fbefeafae6a3cf4e5b5bb7fa6aaa701e0a17c15ab48165cd6fe184a38fabfdd381e1e5246154505c5014ef4bd54c4eacdab34ebeda427f0 languageName: node linkType: hard -"@metaplex-foundation/umi-downloader-http@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-downloader-http@npm:1.2.0" +"@metaplex-foundation/umi-downloader-http@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-downloader-http@npm:1.4.0" peerDependencies: - "@metaplex-foundation/umi": ^1.2.0 - checksum: 10/9f01eb65a8d9da79399dfaf88dfbff72962817d1a34fcc94ee35b90ccd4ca696eb7fe5c7149155a551a9b4b948c371642b332e6e747119d676e2971f9dbd3718 + "@metaplex-foundation/umi": ^1.4.0 + checksum: 10/1077cab28e7e04adf72e24d3e83d6b9c092b3e698e953f8678258d0654530c725a656f22fb8a76acb258a111c43059ec9b7ec8afdfe3d7c9afcb60e032591305 languageName: node linkType: hard -"@metaplex-foundation/umi-eddsa-web3js@npm:^1.0.1": - version: 1.1.1 - resolution: "@metaplex-foundation/umi-eddsa-web3js@npm:1.1.1" +"@metaplex-foundation/umi-eddsa-web3js@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-eddsa-web3js@npm:1.4.0" dependencies: - "@metaplex-foundation/umi-web3js-adapters": "npm:1.1.1" + "@metaplex-foundation/umi-web3js-adapters": "npm:^1.4.0" "@noble/curves": "npm:^1.0.0" yaml: "npm:^2.7.0" peerDependencies: - "@metaplex-foundation/umi": 1.1.1 + "@metaplex-foundation/umi": ^1.4.0 "@solana/web3.js": ^1.72.0 - checksum: 10/7d3f6acef50cd73a3697465f6f7ecb14909dde1ab86711b4e650c7cb39f63db27a864dd6971e4a0fce991e68d39e84aa83fee96e4cb9d519bb11bfd579aab686 + checksum: 10/a40586803e81abf54b55d36fda06cc218cacbd1be5918140f0b3fcf39d8c54d03e80105b105993298c4b4174e079bba7cb6d7a8c36ac369bb719c9ae954dc355 languageName: node linkType: hard -"@metaplex-foundation/umi-http-fetch@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-http-fetch@npm:1.2.0" +"@metaplex-foundation/umi-http-fetch@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-http-fetch@npm:1.4.0" dependencies: node-fetch: "npm:^2.6.7" peerDependencies: - "@metaplex-foundation/umi": ^1.2.0 - checksum: 10/c1bdc3ac51382638837780e3048d5e529ece345f0af722839bab9ebbd6641167a0d25ec533e75368a525a62ad7857784b86cb9e99bdde39d1b9bdbe2a6cb0601 + "@metaplex-foundation/umi": ^1.4.0 + checksum: 10/15dd00241c773bd29904fdc8c1f49c5ea8b37cc3fa0fa793ed48aa24ba671688749c53d11e12e7fa197f92d8bcb8d83a341fcb84974dafa11d3a964aded788fc languageName: node linkType: hard -"@metaplex-foundation/umi-options@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-options@npm:1.2.0" - checksum: 10/6cbc2357299e95567f6f664a77493bedd49789cdda581c99f0faaf7f42f6171de966dc9b71bd27ba8321831c475117fbc13a61677321d4f0196f02787b0648e1 +"@metaplex-foundation/umi-options@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-options@npm:1.4.0" + checksum: 10/f66566bd030f845cfd2113a43bd89fb7b6443087924d9a206bf1042ebdebd79d1ec4eb794682cbf88d73e72252fdfb180db5b1a467ce344742e34d1d1580e5e3 languageName: node linkType: hard -"@metaplex-foundation/umi-program-repository@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-program-repository@npm:1.2.0" +"@metaplex-foundation/umi-program-repository@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-program-repository@npm:1.4.0" peerDependencies: - "@metaplex-foundation/umi": ^1.2.0 - checksum: 10/f31402b13e1d6f2346c3afac7962568ea3cc4143dd694de72443b04adc1fe8f751acf80c8486dcb17117b2e5e705bd1216c619e04f1b8f2f2c375abd1b01d043 + "@metaplex-foundation/umi": ^1.4.0 + checksum: 10/70ab105ef2aecee7c06d32e962d9cedb8664592553224fe69f1469d154df2fa78c771c5090197acb2fa7a56eb52ebabbe61eb7d42eec1e05e5ab62de31830bd6 languageName: node linkType: hard -"@metaplex-foundation/umi-public-keys@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-public-keys@npm:1.2.0" +"@metaplex-foundation/umi-public-keys@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-public-keys@npm:1.4.0" dependencies: - "@metaplex-foundation/umi-serializers-encodings": "npm:^1.2.0" - checksum: 10/a6e5acf9ed0f05e18a5642524c4ad1b0bf807689c807bd2902ea35e84e38529b21b0bba4fa2675c1c77e681de4e1e3d81b9d2c7ee760014287b9151dfa5dedbd + "@metaplex-foundation/umi-serializers-encodings": "npm:^1.4.0" + checksum: 10/159daae737a1f80c29b16b2df7cbd27cc53a02bfcf8021a29e17520f32be347acfd220485247a69c5790b6189f79858dc7700058f5f75386000f4f1f8650cfb2 languageName: node linkType: hard -"@metaplex-foundation/umi-rpc-chunk-get-accounts@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-rpc-chunk-get-accounts@npm:1.2.0" +"@metaplex-foundation/umi-rpc-chunk-get-accounts@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-rpc-chunk-get-accounts@npm:1.4.0" peerDependencies: - "@metaplex-foundation/umi": ^1.2.0 - checksum: 10/0ec9da6d15fe17c274d998cac829c0da77117c1045400ab7cc7dfe69e59d4472af6bf7a209f47d309b807e239ade8bb24392aab0193056b69b6118ccee5aa555 + "@metaplex-foundation/umi": ^1.4.0 + checksum: 10/cbb07818aa99fb101270e828c1ce39a4fe8df8c054231737584a9353b379951fa99384c24be387160ff39f0d6ac5f7f45f5adf81c71aa6bdd7e83eacba74e004 languageName: node linkType: hard -"@metaplex-foundation/umi-rpc-web3js@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-rpc-web3js@npm:1.2.0" +"@metaplex-foundation/umi-rpc-web3js@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-rpc-web3js@npm:1.4.0" dependencies: - "@metaplex-foundation/umi-web3js-adapters": "npm:^1.2.0" + "@metaplex-foundation/umi-web3js-adapters": "npm:^1.4.0" peerDependencies: - "@metaplex-foundation/umi": ^1.2.0 + "@metaplex-foundation/umi": ^1.4.0 "@solana/web3.js": ^1.72.0 - checksum: 10/0fbc0ad2cc759508a3020ff74f84ee1952cbe65c9ba567662710d01e3090f2db48551746d933f667b803310ba3e33a2f30fde308cd2f1f4c934886cdffed8c9f + checksum: 10/a4b5b4ef9484679272edf28ada792d5c808c1f408a22ff4f5761ed0b689e991dee5c1a731efcfd4b7de8dfbaf776b9cddbc9d9a5caf0396b226c3e2b0cfc544c languageName: node linkType: hard -"@metaplex-foundation/umi-serializer-data-view@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-serializer-data-view@npm:1.2.0" +"@metaplex-foundation/umi-serializer-data-view@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-serializer-data-view@npm:1.4.0" peerDependencies: - "@metaplex-foundation/umi": ^1.2.0 - checksum: 10/e1b1410620a120ea10162a68d2a4dc04ce880d3160e941954f2c84b710efe9f1443b20427eb3970fddee31230b8867718fcfdb292cd1a6456106ae45407aed04 + "@metaplex-foundation/umi": ^1.4.0 + checksum: 10/d737a27cf0c8ce3aad5bfe392b14cee6cf84efd5d4f0c11eb277d28d1df4d69aaf1443af5b445c9be34270fa3551ab2fa1c03e7daa3948b62940e6e02114852d languageName: node linkType: hard -"@metaplex-foundation/umi-serializers-core@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-serializers-core@npm:1.2.0" - checksum: 10/c0a343e08a1d9782ecc6090e4a74565b2acbf385c72c2c92c27496c59a4c37d5afc1469f9f21f0279cf058239963e74d8f90118795728b42a5c284440e55f2a7 - languageName: node - linkType: hard - -"@metaplex-foundation/umi-serializers-encodings@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-serializers-encodings@npm:1.2.0" - dependencies: - "@metaplex-foundation/umi-serializers-core": "npm:^1.2.0" - checksum: 10/4d9fab3c2f03e6c93e73b4a9abc8e7a83968660b055db013cc794574cb3022cac579d31607db080a1f6a701b2c58fde1f123188b3fc4c82d7309cba7ac648eca +"@metaplex-foundation/umi-serializers-core@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-serializers-core@npm:1.4.0" + checksum: 10/bc47345a00247d425e58af96b11687943b4ccc1ba838be28755b81d8e8c95ce901cc11066341ab66a7fa42cd85f0cbc38a629f469af278da8f08666e15e2439f languageName: node linkType: hard -"@metaplex-foundation/umi-serializers-numbers@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-serializers-numbers@npm:1.2.0" +"@metaplex-foundation/umi-serializers-encodings@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-serializers-encodings@npm:1.4.0" dependencies: - "@metaplex-foundation/umi-serializers-core": "npm:^1.2.0" - checksum: 10/0a385d42c7d6d2c08c2026384b8f4ee127efbe80b60c1e7668c77d4908ea24ad06421f8a9c33cf0407932ce5d8217784379f26e088badc21fe00a2c4accb1448 + "@metaplex-foundation/umi-serializers-core": "npm:^1.4.0" + checksum: 10/85bf2552d27d08cd02ba88744b7dbfb1cb2f0e60a524b8b79e23b6b2d8015dcd69964f56ce0a43eb2403d41c428cf51da3f7531f5f86c6ac39db7f2ac2228b6c languageName: node linkType: hard -"@metaplex-foundation/umi-serializers@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-serializers@npm:1.2.0" +"@metaplex-foundation/umi-serializers-numbers@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-serializers-numbers@npm:1.4.0" dependencies: - "@metaplex-foundation/umi-options": "npm:^1.2.0" - "@metaplex-foundation/umi-public-keys": "npm:^1.2.0" - "@metaplex-foundation/umi-serializers-core": "npm:^1.2.0" - "@metaplex-foundation/umi-serializers-encodings": "npm:^1.2.0" - "@metaplex-foundation/umi-serializers-numbers": "npm:^1.2.0" - checksum: 10/dd32facea52a87b44a560d20f947a05883c1e56f27353fdcf9972f580c530dcea4ab31c25e8fc58e82076a643f37000312f73b0c7e2346a190105514bc9a40e4 + "@metaplex-foundation/umi-serializers-core": "npm:^1.4.0" + checksum: 10/26a59c8287914a89cbda01dd8d971467df32ed4c0aecfad4d83adf8aa9fbf64ab8404668fc5912a20b1ffcb883ef8a828c801152a984f7ac465e1e7e72165249 languageName: node linkType: hard -"@metaplex-foundation/umi-transaction-factory-web3js@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-transaction-factory-web3js@npm:1.2.0" +"@metaplex-foundation/umi-serializers@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-serializers@npm:1.4.0" dependencies: - "@metaplex-foundation/umi-web3js-adapters": "npm:^1.2.0" - peerDependencies: - "@metaplex-foundation/umi": ^1.2.0 - "@solana/web3.js": ^1.72.0 - checksum: 10/f4baeff00c49d6632a04aae9f7aec9b1c6c5989867ba0c5ce015e5452d7c0bc7959db14bb7578377e487ad93efa73e0dd5ad404537375acca30afbd250461fe1 + "@metaplex-foundation/umi-options": "npm:^1.4.0" + "@metaplex-foundation/umi-public-keys": "npm:^1.4.0" + "@metaplex-foundation/umi-serializers-core": "npm:^1.4.0" + "@metaplex-foundation/umi-serializers-encodings": "npm:^1.4.0" + "@metaplex-foundation/umi-serializers-numbers": "npm:^1.4.0" + checksum: 10/3f145fe550eb979194281d11d8638995bb9e82bf6d7e65bbf83fbd195bdf154ee1ef82f111221dfe4dbd4268f203783c5664260bda6f724f627749f377241e14 languageName: node linkType: hard -"@metaplex-foundation/umi-web3js-adapters@npm:1.1.1": - version: 1.1.1 - resolution: "@metaplex-foundation/umi-web3js-adapters@npm:1.1.1" +"@metaplex-foundation/umi-transaction-factory-web3js@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-transaction-factory-web3js@npm:1.4.0" dependencies: - buffer: "npm:^6.0.3" + "@metaplex-foundation/umi-web3js-adapters": "npm:^1.4.0" peerDependencies: - "@metaplex-foundation/umi": 1.1.1 + "@metaplex-foundation/umi": ^1.4.0 "@solana/web3.js": ^1.72.0 - checksum: 10/8d241cf75b0c82f5c1e838db72b4ab77c064fdaf35cccb7fa6cb6ab2386ee58743742ec372b6666ce36046102932bc0087a69910b3e2d2cff5cd29360709f649 + checksum: 10/71ce4cc3daaef72a99f9e7ceba3a0bc818c1a3acd69cfbc11475a79646c417c21fbfee6fa51d155dd3dc29ba342792057cb1020bc0e0a136c4dbff7c99454bea languageName: node linkType: hard -"@metaplex-foundation/umi-web3js-adapters@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi-web3js-adapters@npm:1.2.0" +"@metaplex-foundation/umi-web3js-adapters@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi-web3js-adapters@npm:1.4.0" dependencies: buffer: "npm:^6.0.3" peerDependencies: - "@metaplex-foundation/umi": ^1.2.0 + "@metaplex-foundation/umi": ^1.4.0 "@solana/web3.js": ^1.72.0 - checksum: 10/c250a5859241dfb21747d6d14277061a3a3ce73960d731782c47c03c59a5d8846dd0a470db8ab4024409360c9733a2cf207cdb6df9b78f249f1216d497c0a865 + checksum: 10/2ba2ac120b92907ff843c1c5c9d4d84e0eeec9ff614b69a234151d8eeda6a4db892a0df014876306f2698cb246bbbbb17c5ef7024a6d7b19e54bbe45e35cef3d languageName: node linkType: hard -"@metaplex-foundation/umi@npm:^1.2.0": - version: 1.2.0 - resolution: "@metaplex-foundation/umi@npm:1.2.0" +"@metaplex-foundation/umi@npm:^1.4.0": + version: 1.4.0 + resolution: "@metaplex-foundation/umi@npm:1.4.0" dependencies: - "@metaplex-foundation/umi-options": "npm:^1.2.0" - "@metaplex-foundation/umi-public-keys": "npm:^1.2.0" - "@metaplex-foundation/umi-serializers": "npm:^1.2.0" - checksum: 10/8d8eac8a3b3e7693b5f4fa52cfdca99c94669929cc5958d9e3588c05f38ca4927f9fdef1acc7b1ffb290dadebb8d690fd079b9eeac54de4c1affda067b988cf6 + "@metaplex-foundation/umi-options": "npm:^1.4.0" + "@metaplex-foundation/umi-public-keys": "npm:^1.4.0" + "@metaplex-foundation/umi-serializers": "npm:^1.4.0" + checksum: 10/9ba40046d97fb8b928159fcf23c3b2c5f3db7c5faf18f21e030762bae1d7899b916708387ec48011f5ba54790163b50d700e6d0b159b138891bea7d907ae7c6e languageName: node linkType: hard @@ -7110,7 +7098,7 @@ __metadata: languageName: node linkType: hard -"@polkadot/api@npm:16.4.6, @polkadot/api@npm:^16.4.4, @polkadot/api@npm:^16.4.6": +"@polkadot/api@npm:16.4.6, @polkadot/api@npm:^16.4.6": version: 16.4.6 resolution: "@polkadot/api@npm:16.4.6" dependencies: @@ -7135,21 +7123,21 @@ __metadata: languageName: node linkType: hard -"@polkadot/extension-inject@npm:^0.61.6": - version: 0.61.6 - resolution: "@polkadot/extension-inject@npm:0.61.6" +"@polkadot/extension-inject@npm:^0.61.7": + version: 0.61.7 + resolution: "@polkadot/extension-inject@npm:0.61.7" dependencies: - "@polkadot/api": "npm:^16.4.4" - "@polkadot/rpc-provider": "npm:^16.4.4" - "@polkadot/types": "npm:^16.4.4" - "@polkadot/util": "npm:^13.5.5" - "@polkadot/util-crypto": "npm:^13.5.5" - "@polkadot/x-global": "npm:^13.5.5" + "@polkadot/api": "npm:^16.4.6" + "@polkadot/rpc-provider": "npm:^16.4.6" + "@polkadot/types": "npm:^16.4.6" + "@polkadot/util": "npm:^13.5.6" + "@polkadot/util-crypto": "npm:^13.5.6" + "@polkadot/x-global": "npm:^13.5.6" tslib: "npm:^2.8.1" peerDependencies: "@polkadot/api": "*" "@polkadot/util": "*" - checksum: 10/bddf161593a35ad767b56d63f04f3d53696ef551d93e09bc9113d304194072ed91acc091bb5546ad38d948964285bb27406b9a49b269ff08678d482962be727d + checksum: 10/2250169f498d42a435fea8bd1e47f91839ab5ed34b49509d68add39d36815c892ed08dc8e1c401a27ef9ffcb623e247dd274ff524dae8c7af63602352126f793 languageName: node linkType: hard @@ -7281,7 +7269,7 @@ __metadata: languageName: node linkType: hard -"@polkadot/rpc-provider@npm:16.4.6, @polkadot/rpc-provider@npm:^16.4.4, @polkadot/rpc-provider@npm:^16.4.6": +"@polkadot/rpc-provider@npm:16.4.6, @polkadot/rpc-provider@npm:^16.4.6": version: 16.4.6 resolution: "@polkadot/rpc-provider@npm:16.4.6" dependencies: @@ -7437,7 +7425,7 @@ __metadata: languageName: node linkType: hard -"@polkadot/types@npm:16.4.6, @polkadot/types@npm:^16.4.4, @polkadot/types@npm:^16.4.6": +"@polkadot/types@npm:16.4.6, @polkadot/types@npm:^16.4.6": version: 16.4.6 resolution: "@polkadot/types@npm:16.4.6" dependencies: @@ -7486,7 +7474,7 @@ __metadata: languageName: node linkType: hard -"@polkadot/util-crypto@npm:13.5.6, @polkadot/util-crypto@npm:^13.5.5, @polkadot/util-crypto@npm:^13.5.6": +"@polkadot/util-crypto@npm:13.5.6, @polkadot/util-crypto@npm:^13.5.6": version: 13.5.6 resolution: "@polkadot/util-crypto@npm:13.5.6" dependencies: @@ -7521,7 +7509,7 @@ __metadata: languageName: node linkType: hard -"@polkadot/util@npm:13.5.6, @polkadot/util@npm:^13.5.5, @polkadot/util@npm:^13.5.6": +"@polkadot/util@npm:13.5.6, @polkadot/util@npm:^13.5.6": version: 13.5.6 resolution: "@polkadot/util@npm:13.5.6" dependencies: @@ -7747,7 +7735,7 @@ __metadata: languageName: node linkType: hard -"@polkadot/x-global@npm:13.5.6, @polkadot/x-global@npm:^13.5.5, @polkadot/x-global@npm:^13.5.6": +"@polkadot/x-global@npm:13.5.6, @polkadot/x-global@npm:^13.5.6": version: 13.5.6 resolution: "@polkadot/x-global@npm:13.5.6" dependencies: @@ -8686,9 +8674,9 @@ __metadata: languageName: node linkType: hard -"@solana-developers/helpers@npm:2.8.0": - version: 2.8.0 - resolution: "@solana-developers/helpers@npm:2.8.0" +"@solana-developers/helpers@npm:2.8.1": + version: 2.8.1 + resolution: "@solana-developers/helpers@npm:2.8.1" dependencies: "@coral-xyz/anchor": "npm:^0.30.1" "@solana/spl-token": "npm:^0.4.8" @@ -8697,7 +8685,7 @@ __metadata: bn.js: "npm:^5.2.1" bs58: "npm:^6.0.0" dotenv: "npm:^16.4.5" - checksum: 10/d73bf3d6fd0ec2fe166dcbf79c791aec87ef4ae4b5a44bf97d405c36e0228de53c0a03ba2fb506dceb103f44e7155619e1edf95516e69c099b7a297e7a0b999c + checksum: 10/857ccac4606f431b793c58fb562ea34b578a78e3a82085ec10187ebc6b9d5bcba020b871ecd5df5d88f686b05225b09d4496660d350f3e6df0d9e24585f1881c languageName: node linkType: hard From 5a61a0246375cfb0ed6aa438d3c4f26fa79573cf Mon Sep 17 00:00:00 2001 From: Suhail Kakar Date: Mon, 1 Sep 2025 10:39:58 +0530 Subject: [PATCH 025/109] feat: add TAC mainnet --- .../ethereum/networks/icons/tac.webp | Bin 0 -> 9880 bytes .../src/providers/ethereum/networks/index.ts | 2 ++ .../src/providers/ethereum/networks/tac.ts | 27 ++++++++++++++++++ packages/types/src/networks.ts | 1 + 4 files changed, 30 insertions(+) create mode 100644 packages/extension/src/providers/ethereum/networks/icons/tac.webp create mode 100644 packages/extension/src/providers/ethereum/networks/tac.ts diff --git a/packages/extension/src/providers/ethereum/networks/icons/tac.webp b/packages/extension/src/providers/ethereum/networks/icons/tac.webp new file mode 100644 index 0000000000000000000000000000000000000000..f4673fafeb4b4b985a24c41527d391db5b96ce05 GIT binary patch literal 9880 zcmeHNXH*nTm+nc-Fawfv&PkA*b94kr5(Gg&a)u#;L~$f4AUT6b5CjCtL85>H0umLF zAW4uUNK_Vd&%XQZ*`MFpKTDnNuBUF@b8mIss?*Q8)w*a^)i`zlFjP_0HqaKojRXLI z@%(-Qy139vO4>-8^Cm!pbh32z0P_QYvx_H2S51-ewvjO-d=x+c_y8V24B%K;dbr)Z zrK)$KeW80%|7-a<4uCEsA9?@x{(sf}A1yp9XBR5~0Fj={9jvT9EYESsIkvNMwz`n7 zUSJDw;MxAc$g&H3?++%f zzrdDu7-s;W?mE|JwRFRr+o!(p#q@U!=Li4@FW!gI*4o7yW8rCS#rQ|~?|l3>UoemJ z$^UoS{_nQ_ul!uBoxgs6$oyFoAoA3IWUh$-AifCzkhp(jtXTj+@Bjd6TmO;Wdkz3~ zaR5L$Yw3mY{%a3eQ~*7|0&oJnfFK|SNCEPI3UC9^0`veQ;4WYZ*a6M} z2Jivy1EByGhz8<-Bp@Bg0SbT;pd6?I>VRgT9e4}82Zn$#;4?4>ECK7lHt-WT0f9hp z5I%?mLoRiN(beENV zA7~gf1)2w~fp$U1UbI;CyfyxE9BG2x0|sf=h_YhAWAyg=>ZD zhx-J#0JjnM1MU*;36coOfs{e&AsvvR$W&xGvKu*#{DDHDm{Afa9h5yP1eJ=aMD?QP zQAc>hc-(kOcqVvWc#rXl@Y?XE@P6RqIljFo-aNuz_%baG!{TNPtL- z$eAdH=mk+9(JC>Vn4MUK*oruu_!)60@gfO?goQ+j#FFFzNdZYW$r33JDF-Q<)PXdb z^d;#a={6ZLnJ}3FnJ-xeSqs@5IfR^@98K;-{)D`We4PB4f{sFg!kQwIqMTxc;((Hd zQl8S9GK#W-a*Xnrijhi%%8@Fbs*Y-g8cNMgtwZfYolV_My+K1tBSm9L6Gc-+^NAKr z%T23G8$kPvwx4#Nj-F19&W$dOu9I$qo}6Bu-hn=mzLkEBfrLSp!JZ+J;SIw#MlwbP zMkmHp#xBNfCR(QJOkPZROoL1(%pA=6%wfzG%rh)V7I79EmPD2gmTguB)|;&NSxZ?z zvEj0bv)Qqwu=TJVuye2*vOi+4V_)T<{ad9rwhufncMTy?pce|3Tvk5_@$o41sAo{yYQgD;G)j&JiC z>owzR@z;8;{pJ_pcj7PL|13Z(a6=$Wpiy8~kXz7FFhg)u2wzB5C|IaoXh)bw*jhMS zcv6H!F;+2iu}rZEaZ+(@@fh)537CYUM6g7&#F3<^q^D$+ zl0`?v?aO(y?sOMM&OMubv*T3>gnnW8r&KfjmDecn>TJgy*aJPrs<+trv+%C zwVrCtXme=0Yd7iO=xFO?=q&3B=-$`uxkYlz?AD80KlK##p6Gqn=hXMo?=T=RFfk}G zI51Q;Ofa0geeHJO?e|91M)pSa#&BZ;<3i*8J1TdQ?kt&zm|#uDO*u?`P5bUr-*vj% zVn$$QVODJpGdDDUVSZ|%Wsz^Oe-C{x^WL_ll4XkJx|O_DqSczUjCF$bij9m-g3YR} zjO|m~H9I-GWV;P}CHr*y9f#`4IXHJGr70w7}bLR#ZVi!l3E?0V2U)Nzb z9yhGpoV%oZlKVDB9aHE5@-X$N_ar_4NcVejdOh@-_m=g}@ILf0@TvAC@^$g;_v7}9 z^jq;)^?x1!4X_O8xX*My^!|LHLSSAHDCk~LM=(opc<@q)T1asyGSo42AdEjOA#Cq~ z;e*C-y6}+j#fNGSOR-n580^F&sYf{x&2+X{YIS>0=p+85NndnUR?XSyovi+49-tIdnPEImfy7xs!QndA0fM`N_|4 zo_Rl8E-)zQc`p9Eq>#EWy6{(#OVM1hZgE$MSV_qX+80ks!KGfMYh@;7LobzI)|c~^ z=T(qbL{|cpUX|ZonZFvZQm^W$7OyUU&GtI8hNLE{7F6q3yIp5jH&<^|KiqJmp`%f% zv8IWysi>K$IirQFSat z>`~}>(<{^4+$Y)B@J{?)-FwmZwf!RfH3K38HG`sqwI9Sj)DKAvH4aM;w~ok-w0~6o z_;wUM`hHAvYr)DVWnhMaJ6|&b#3U|oo`F)ZtEu-*zZK&GdDRm zUvJ58^>5$aUfRLzobAT^p!!j?C%o6Ouf0F})A{GgLDV7DVeygpQO~jA@ydzMDf~3` z7uT=G-|D}o&z#TBF1f%Z7r5jCmt5eI3tV!6OD=H91upXfmwAE9yuf8%;4&|8nHRXs z3;aLM3;a39IcEcq3r6s40s!;^06=2^0MgO{fZgW&e8I%i+V}i?2LN1L87*Di{4n;m zcAi%my*#WLZ7|l>PJRIL{EUpz90dTC+CUbFI}Q{FlGWi%P<@u4m&a^)z1IziYwI%a z!Dr%l49zJ0g?&R|ep+{$_U-f7@3jD6H(OG+B|zrz%q}>WeoVSeE<9M^m*TqIGR5zM zeY4vH=(B|ug*S0$b!X?L=JU|4v$JPf$B!H3#+!QN26m?cbbc^SeW@|4JWV}npSrsv zCz=xWivTP&;?}1Pc^7b!!_J_7g5w!a;3ZKr4bQtDRwUXKvUe>`Z+XIv{^2e%^V23| zs8!)shH0BWMK8CT^ECfnsWK{aMHln8ucg|)PeG;0F#fSfgW|%N+efjy0Jn$mKIR6c zIO?bWY3D7W$L*cMr~e2VsNOwFS~4<{&cEGBd<4^U_5m%UrPJ1^lq$Au{70Xs3U0jn znrZShnm*8@@!Zk(>ABb#T6r1!6Md!Fez}h7;AcAnF83#X3>(zjXY^~>z_0oyfwr>R zL^x>JkcU>I^}85k;#1)rqF*JxaS3_U(^+aeHk{^n`FAmpXA+@heWUA;cwl;cs1f!ZRz0ntq+nii;+@>iP;yli~}47MFhV+d8Ue z2^Fmsa#(UjUwW!@>V1PK#K4m!R%$jm(E%r|1?A&JBu7&|j;rLl*8IeOLs2ud?X0-* zRN^EIp4I(gzDR15s#J8*pyyq9zd80?|J-@aGEhi#pHE-IFwDi=ZU<7yBZ~e}(SFcN5`(RWrttf$}+- zKQ8_WFkLS2dvEQ_8c`?i3WDJ54&Uyi`_GGI3;?*VUKdA>-1_i4j`+medKm~H;j~Dvpy*@a5E*aJmXZ05>u3`4 zDl+csMK_09DfPoP{^w)@H1^UG5Mu)!s@Lv*G29q!Xr_)1>!!*HT<9gfMoQL06aKGO z)nT3(;s=nL<*76z-sdq@mRd4TI4bV5HOw};A>s5S|_gnA3!1?~b zRE)z7QbkmAAo^;l%twDk?WU&VSB`$3H+~s&4#oF02NTg8&A>xfd%2UUnz63XVrMWs z{a}4m7t0WpMABnC!EHROpbH~Lm?304>CINPRIl0=aDOjSnL=;9O|cioy!U4q-&0!r zc6EGu&R^Pwe2+TMO8PNAYsVrm$4uB=U3dp}RS2xy_v!T_CHhUbm3V0nPmHSlx}G*9 zJ*LF7YP_@64bsakra09>uOD^jh$x>inb4o6&$V9b44VlG8QC0G`x=jzKQ={e>Tf8x z%ok`yGx#-ZuQG|F2KvfVt@5!$;2vE?^s1D40`F+Y-iLdzuTIzvh}JcFtKA2l#lAbv zY~f32i)DfDG+NX%W4cHQW$^Yv=v>(7J=4v7?Y__?^!kCCQJOOz z_i~?Ne04b&!4hh;g2hR6Qu!zF9-_=u5DOZKaT8D9SvXcAiysKAQ$@wTEY?!wrHFTp z7Sz%V&hL>me%<_YfxO-}DM)@6y>^&!zWxF&p@#-+Lx8UDOP$$K4U1l)hFG|#bq14{ zQX^eY^=~w9JMF89nf2=-Mzea@SL!pj$(E9fEEJ0KmR>^#ztGAF9=+uySnE5rj0a zt}Gwowp5UG^pk&DF81m*yN(=9YL&THV=$ciCKIooz%xhPfFqJ- z1Cg}>g}f;5-B$jBxDCqmQGC-LR0xs;!FgIp!Q;a8TQ3+GNvCO5(TVK=ZcZ7gAF7_Z zk7=y+^zeRd?3Jf}?O#a}+CDGunC4B3xMLHQ;4On5*Xu1aGU_2= zFP1H1xbM6emX{Zoo6AjW8d6V+Ls?l##GhNF@^JY&om_d!~;pm&OH*P z_9^h~=fTCQ%_eqo`gf?UbGhulEm-)qGS8V`EqPr2KE2&E@+`4AEa&}!NLW)o+ZEmo zqUlF^8>0$qLdTzegU*(Ehc)|rHfwfI33)}rh|gHJg{|jVhWoBi>!id-J2{OCSCYZgk~_ z+00YN)IY44q^Ci3zt3lxZh$=Z`+&DJ z#V|v4+<-D9=mk}Vr*|0I)tqDwXf`6oTgk?5ec4}i$?D56@hA#;4>qIBrpYVDo)SbY z{Lp$xwDtbZtTnBV>b$wK(FcF51=GPt$!xQ$U3m}QD0d#r-DPb!V-$!I3}*1P)UNx$ z5)B=K-+Af&J%K&_G_+WIO~%I2BAoh0p1rFuE<-^5W>gL*{V&o$Qo&s0N`yO}%_14f zb=QAnDo84;H0#6NR|Q8hQe>Y{ApqDEy_V4u^hV20V)J|ptUSEyEjr`0bBjx_FH(zr zuQ==`zM^d9N=fB&PXW99SD$dBIf9|K2Jp|2pE Date: Mon, 1 Sep 2025 18:47:01 +0530 Subject: [PATCH 026/109] update chain id --- packages/extension/src/providers/ethereum/networks/tac.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/extension/src/providers/ethereum/networks/tac.ts b/packages/extension/src/providers/ethereum/networks/tac.ts index 48f03ff26..e1732a2ce 100644 --- a/packages/extension/src/providers/ethereum/networks/tac.ts +++ b/packages/extension/src/providers/ethereum/networks/tac.ts @@ -11,7 +11,7 @@ const ethOptions: EvmNetworkOptions = { homePage: 'https://tac.build', blockExplorerTX: 'https://explorer.tac.build/tx/[[txHash]]', blockExplorerAddr: 'https://explorer.tac.build/address/[[address]]', - chainID: '0x239', + chainID: '0xef', isTestNetwork: false, currencyName: 'TAC', currencyNameLong: 'TAC', From 321d6595b0929af4abe99cf7d6e085edc9998114 Mon Sep 17 00:00:00 2001 From: Peterjah Date: Tue, 2 Sep 2025 10:41:42 +0200 Subject: [PATCH 027/109] fix chrome extension build --- packages/extension/vite.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/extension/vite.config.ts b/packages/extension/vite.config.ts index 9293d40e6..7521ab0b6 100644 --- a/packages/extension/vite.config.ts +++ b/packages/extension/vite.config.ts @@ -56,7 +56,7 @@ export default defineConfig({ __BUILD_TIME__: BROWSER === 'firefox' ? JSON.stringify('FF-build') - : new Date().toLocaleString().replace(/\D/g, ''), + : JSON.stringify(new Date().toLocaleString().replace(/\D/g, '')), }, plugins: [ visualizer() as PluginOption, From 0900c8c6c5563d296b2ca57e6608baaaab95f55b Mon Sep 17 00:00:00 2001 From: Peterjah Date: Tue, 2 Sep 2025 12:17:47 +0200 Subject: [PATCH 028/109] add invalid address error message --- .../components/send-address-input.vue | 1 - .../massa/ui/send-transaction/index.vue | 91 +++++++++++++------ 2 files changed, 61 insertions(+), 31 deletions(-) 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 index 6ff6bd897..5f0163fed 100644 --- 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 @@ -37,7 +37,6 @@ 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(false); diff --git a/packages/extension/src/providers/massa/ui/send-transaction/index.vue b/packages/extension/src/providers/massa/ui/send-transaction/index.vue index a16fa17f4..bdb4b82bd 100644 --- a/packages/extension/src/providers/massa/ui/send-transaction/index.vue +++ b/packages/extension/src/providers/massa/ui/send-transaction/index.vue @@ -69,7 +69,7 @@ @update:input-set-max="setMaxValue" /> -
- - -
Minimal fee from network
+
+
Fee (MAS)
+ +
+
+ Minimal fee from network: + {{ minimalFee }} +
+ +
@@ -125,7 +132,8 @@ import SendInputAmount from '@/providers/common/ui/send-transaction/send-input-a 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 SendAlert from '@/providers/solana/ui/send-transaction/components/send-alert.vue'; +import SendBalanceAlert 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'; @@ -157,6 +165,7 @@ const addressInputTo = ref(); const addressInputFrom = ref(); const amount = ref(''); const fee = ref('0.01'); +const minimalFee = ref('0.01'); const addressTo = ref(''); const addressFrom = ref(''); const isOpenSelectContactTo = ref(false); @@ -306,6 +315,19 @@ const sendButtonTitle = computed(() => { return title; }); +const errorMsg = computed(() => { + // Check if address is invalid + if ( + addressTo.value && + addressTo.value.trim() !== '' && + !(network.value as MassaNetwork).isValidAddress(addressTo.value) + ) { + return 'Invalid to address.'; + } + + return ''; +}); + const isInputsValid = computed(() => { // First check if address is provided if (!addressTo.value || addressTo.value.trim() === '') { @@ -313,9 +335,7 @@ const isInputsValid = computed(() => { } // Check if address is valid - try { - Address.fromString(addressTo.value); - } catch { + if (!(network.value as MassaNetwork).isValidAddress(addressTo.value)) { return false; } @@ -362,8 +382,9 @@ onMounted(async () => { try { const api = (await network.value.api()) as MassaAPI; const minimalFeeBase = await api.getMinimalFee(); - const minimalFee = formatMas(BigInt(minimalFeeBase)); - fee.value = minimalFee; + const minFee = formatMas(BigInt(minimalFeeBase)); + fee.value = minFee; + minimalFee.value = minFee; } catch { // Keep default fee of 0.01 if API call fails } @@ -607,33 +628,42 @@ const sendAction = async () => { } .fee-input-container { - margin: 0 32px 8px 32px; - padding: 16px; + min-height: 40px; + height: auto; background: #ffffff; + margin: 0 32px 8px 32px; border: 1px solid @gray02; border-radius: 10px; width: calc(~'100% - 64px'); box-sizing: border-box; position: relative; + padding: 10px 16px; + + .fee-input-content { + display: flex; + justify-content: space-between; + align-items: center; + flex-direction: row; + margin-bottom: 4px; + } - label { - display: block; - margin-bottom: 8px; + .fee-label { font-style: normal; font-weight: 400; - font-size: 12px; - line-height: 16px; - letter-spacing: 0.5px; + font-size: 14px; + line-height: 20px; + letter-spacing: 0.25px; color: @secondaryLabel; + margin: 0; } .fee-input { - width: 100%; - height: 24px; + width: 120px; + height: 20px; font-style: normal; font-weight: 400; - font-size: 16px; - line-height: 24px; + font-size: 14px; + line-height: 20px; letter-spacing: 0.25px; color: @primaryLabel; border: 0 none; @@ -641,6 +671,7 @@ const sendAction = async () => { padding: 0; background: transparent; caret-color: @primary; + text-align: right; &::-webkit-outer-spin-button, &::-webkit-inner-spin-button { @@ -654,13 +685,13 @@ const sendAction = async () => { } .fee-info { - margin-top: 8px; font-style: normal; font-weight: 400; font-size: 12px; line-height: 16px; letter-spacing: 0.5px; color: @tertiaryLabel; + margin: 0; } } From 4b2b6944cc659b8fd2d6852c770a04530ac83714 Mon Sep 17 00:00:00 2001 From: Peterjah Date: Tue, 2 Sep 2025 12:41:03 +0200 Subject: [PATCH 029/109] ensure network is initialized before checking address --- .../src/providers/massa/ui/send-transaction/index.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/extension/src/providers/massa/ui/send-transaction/index.vue b/packages/extension/src/providers/massa/ui/send-transaction/index.vue index bdb4b82bd..511af2024 100644 --- a/packages/extension/src/providers/massa/ui/send-transaction/index.vue +++ b/packages/extension/src/providers/massa/ui/send-transaction/index.vue @@ -320,6 +320,7 @@ const errorMsg = computed(() => { if ( addressTo.value && addressTo.value.trim() !== '' && + network.value && !(network.value as MassaNetwork).isValidAddress(addressTo.value) ) { return 'Invalid to address.'; @@ -335,7 +336,10 @@ const isInputsValid = computed(() => { } // Check if address is valid - if (!(network.value as MassaNetwork).isValidAddress(addressTo.value)) { + if ( + !network.value || + !(network.value as MassaNetwork).isValidAddress(addressTo.value) + ) { return false; } From f2f84103d98e919ad5ab33fe43585d0e4c21272c Mon Sep 17 00:00:00 2001 From: kvhnuke <10602065+kvhnuke@users.noreply.github.com> Date: Tue, 2 Sep 2025 13:25:36 -0700 Subject: [PATCH 030/109] fix: polkadot signing issue and name resolver --- packages/name-resolution/src/index.ts | 8 ++++---- packages/name-resolution/tests/resolver.test.ts | 3 ++- packages/name-resolution/tests/sid.test.ts | 2 +- packages/signers/polkadot/src/index.ts | 1 + 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/name-resolution/src/index.ts b/packages/name-resolution/src/index.ts index eed7268c6..347fcdde6 100644 --- a/packages/name-resolution/src/index.ts +++ b/packages/name-resolution/src/index.ts @@ -24,7 +24,7 @@ class NameResolver { this.ens.init(), this.rns.init(), this.ud.init(), - this.sid.init(), + // this.sid.init(), ]); } @@ -32,7 +32,7 @@ class NameResolver { return this.initDone.then(() => Promise.all([ this.ens.resolveReverseName(address), - this.sid.resolveReverseName(address), + // this.sid.resolveReverseName(address), this.rns.resolveReverseName(address), this.ud.resolveReverseName(address), ]).then((results) => { @@ -55,8 +55,8 @@ class NameResolver { return this.rns.resolveAddress(name, coin); if (this.ud.isSupportedName(name)) return this.ud.resolveAddress(name, coin); - if (this.sid.isSupportedName(name)) - return this.sid.resolveAddress(name, paymentIdChain); + // if (this.sid.isSupportedName(name)) + // return this.sid.resolveAddress(name, paymentIdChain); if (this.ens.isSupportedName(name)) return this.ens.resolveAddress(name, coin); diff --git a/packages/name-resolution/tests/resolver.test.ts b/packages/name-resolution/tests/resolver.test.ts index 968fd3658..e9f26c36f 100644 --- a/packages/name-resolution/tests/resolver.test.ts +++ b/packages/name-resolution/tests/resolver.test.ts @@ -20,7 +20,8 @@ describe("Name Resolver resolving", () => { address = await resolver.resolveAddress("brad.crypto", "ETH"); expect(address).to.be.eq("0x8aaD44321A86b170879d7A244c1e8d360c99DdA8"); address = await resolver.resolveAddress("spaceid.arb", "ARB1"); - expect(address).to.be.eq("0xb5932a6B7d50A966AEC6C74C97385412Fb497540"); + // expect(address).to.be.eq("0xb5932a6B7d50A966AEC6C74C97385412Fb497540"); + expect(address).to.be.eq(null); }); it("it should properly reverse resolve", { timeout: 20_000 }, async () => { diff --git a/packages/name-resolution/tests/sid.test.ts b/packages/name-resolution/tests/sid.test.ts index d515d417f..6e1709219 100644 --- a/packages/name-resolution/tests/sid.test.ts +++ b/packages/name-resolution/tests/sid.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect } from "vitest"; import SIDResolver from "../src/sid"; -describe("SID Name resolving", () => { +describe.skip("SID Name resolving", () => { // the tests container it("it should properly resolve address", { timeout: 10_000 }, async () => { const resolver = new SIDResolver({ diff --git a/packages/signers/polkadot/src/index.ts b/packages/signers/polkadot/src/index.ts index 45973a92a..7d3e6577d 100644 --- a/packages/signers/polkadot/src/index.ts +++ b/packages/signers/polkadot/src/index.ts @@ -51,6 +51,7 @@ export class PolkadotSigner implements SignerInterface { password, undefined, options.onlyJS, + 2048, ); let pair: KeyPair; switch (this.type) { From 6dce76c7a169d7689050711893b85dd518cbfa6c Mon Sep 17 00:00:00 2001 From: kvhnuke <10602065+kvhnuke@users.noreply.github.com> Date: Tue, 2 Sep 2025 13:29:55 -0700 Subject: [PATCH 031/109] fix: build --- packages/name-resolution/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/name-resolution/src/index.ts b/packages/name-resolution/src/index.ts index 347fcdde6..9956e7835 100644 --- a/packages/name-resolution/src/index.ts +++ b/packages/name-resolution/src/index.ts @@ -48,7 +48,7 @@ class NameResolver { public async resolveAddress( name: string, coin: CoinType = "ETH", - paymentIdChain?: string, + _paymentIdChain?: string, ): Promise { return this.initDone.then(() => { if (this.rns.isSupportedName(name)) From 7e462434d2f6b133e207f6f8ea65cf09b0c4ccff Mon Sep 17 00:00:00 2001 From: kvhnuke <10602065+kvhnuke@users.noreply.github.com> Date: Tue, 2 Sep 2025 13:38:06 -0700 Subject: [PATCH 032/109] devop: add TAC network --- packages/extension/package.json | 2 +- .../extension/src/providers/common/libs/new-features.ts | 2 +- .../libs/activity-handlers/providers/etherscan/configs.ts | 1 + packages/extension/src/providers/ethereum/networks/tac.ts | 8 +++----- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/extension/package.json b/packages/extension/package.json index 9f2c0bb0c..a294a5806 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -1,6 +1,6 @@ { "name": "@enkryptcom/extension", - "version": "2.10.0", + "version": "2.11.0", "private": true, "type": "module", "scripts": { diff --git a/packages/extension/src/providers/common/libs/new-features.ts b/packages/extension/src/providers/common/libs/new-features.ts index 93cfa09a6..11112ff69 100644 --- a/packages/extension/src/providers/common/libs/new-features.ts +++ b/packages/extension/src/providers/common/libs/new-features.ts @@ -1,6 +1,6 @@ import { NetworkNames } from '@enkryptcom/types'; -const newNetworks: NetworkNames[] = [NetworkNames.CoreDAO]; +const newNetworks: NetworkNames[] = [NetworkNames.TAC]; const newSwaps: NetworkNames[] = []; export { newNetworks, newSwaps }; diff --git a/packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts b/packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts index c476ed94e..01fed86f0 100644 --- a/packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts +++ b/packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts @@ -68,6 +68,7 @@ const NetworkEndpoints: Record = { [NetworkNames.Hemi]: 'https://explorer.hemi.xyz/', [NetworkNames.AppLayerTestnet]: 'https://testnet-explorer.applayer.com/api/', [NetworkNames.EthereumClassic]: 'https://etc.blockscout.com/', + [NetworkNames.TAC]: 'https://explorer.tac.build/', }; export { NetworkEndpoints }; diff --git a/packages/extension/src/providers/ethereum/networks/tac.ts b/packages/extension/src/providers/ethereum/networks/tac.ts index e1732a2ce..db8711788 100644 --- a/packages/extension/src/providers/ethereum/networks/tac.ts +++ b/packages/extension/src/providers/ethereum/networks/tac.ts @@ -1,11 +1,10 @@ import icon from './icons/tac.webp'; import { NetworkNames } from '@enkryptcom/types'; import { EvmNetwork, EvmNetworkOptions } from '../types/evm-network'; -import assetsInfoHandler from '@/providers/ethereum/libs/assets-handlers/assetinfo-mew'; import { EtherscanActivity } from '../libs/activity-handlers'; import wrapActivityHandler from '@/libs/activity-state/wrap-activity-handler'; -const ethOptions: EvmNetworkOptions = { +const tacOptions: EvmNetworkOptions = { name: NetworkNames.TAC, name_long: 'TAC', homePage: 'https://tac.build', @@ -18,10 +17,9 @@ const ethOptions: EvmNetworkOptions = { node: 'https://rpc.ankr.com/tac', icon, coingeckoID: 'tac', - assetsInfoHandler, activityHandler: wrapActivityHandler(EtherscanActivity), }; -const eth = new EvmNetwork(ethOptions); +const tac = new EvmNetwork(tacOptions); -export default eth; +export default tac; From 48a072da535ef5f59d6ab1ef4b2a346ca87246b2 Mon Sep 17 00:00:00 2001 From: kvhnuke <10602065+kvhnuke@users.noreply.github.com> Date: Tue, 2 Sep 2025 13:45:08 -0700 Subject: [PATCH 033/109] devop: add tac network --- packages/extension/package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/extension/package.json b/packages/extension/package.json index a294a5806..6d29efee2 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -52,7 +52,7 @@ "@polkadot/ui-shared": "^3.16.1", "@polkadot/util": "^13.5.6", "@polkadot/wasm-crypto": "^7.5.1", - "@solana-developers/helpers": "2.8.1", + "@solana-developers/helpers": "2.8.0", "@solana/spl-token": "^0.4.13", "@solana/wallet-standard-features": "^1.3.0", "@solana/web3.js": "^1.98.4", diff --git a/yarn.lock b/yarn.lock index 105e9b0ef..a2616a16d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1709,7 +1709,7 @@ __metadata: "@rollup/plugin-replace": "npm:^6.0.2" "@rollup/plugin-terser": "npm:^0.4.4" "@rollup/plugin-typescript": "npm:^12.1.4" - "@solana-developers/helpers": "npm:2.8.1" + "@solana-developers/helpers": "npm:2.8.0" "@solana/spl-token": "npm:^0.4.13" "@solana/wallet-standard-features": "npm:^1.3.0" "@solana/web3.js": "npm:^1.98.4" @@ -8674,9 +8674,9 @@ __metadata: languageName: node linkType: hard -"@solana-developers/helpers@npm:2.8.1": - version: 2.8.1 - resolution: "@solana-developers/helpers@npm:2.8.1" +"@solana-developers/helpers@npm:2.8.0": + version: 2.8.0 + resolution: "@solana-developers/helpers@npm:2.8.0" dependencies: "@coral-xyz/anchor": "npm:^0.30.1" "@solana/spl-token": "npm:^0.4.8" @@ -8685,7 +8685,7 @@ __metadata: bn.js: "npm:^5.2.1" bs58: "npm:^6.0.0" dotenv: "npm:^16.4.5" - checksum: 10/857ccac4606f431b793c58fb562ea34b578a78e3a82085ec10187ebc6b9d5bcba020b871ecd5df5d88f686b05225b09d4496660d350f3e6df0d9e24585f1881c + checksum: 10/d73bf3d6fd0ec2fe166dcbf79c791aec87ef4ae4b5a44bf97d405c36e0228de53c0a03ba2fb506dceb103f44e7155619e1edf95516e69c099b7a297e7a0b999c languageName: node linkType: hard From da80eafd007bf2348673790951b91ea142a9c672 Mon Sep 17 00:00:00 2001 From: Peterjah Date: Thu, 4 Sep 2025 12:40:57 +0200 Subject: [PATCH 034/109] rework sent input amount --- .../components/send-address-input.vue | 7 +- .../massa/ui/send-transaction/index.vue | 126 +++++++++--------- 2 files changed, 65 insertions(+), 68 deletions(-) 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 index 5f0163fed..df422e02c 100644 --- 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 @@ -35,7 +35,7 @@ + + diff --git a/packages/extension/src/ui/action/components/app-menu/index.vue b/packages/extension/src/ui/action/components/app-menu/index.vue index 108431c3a..c572f7d27 100644 --- a/packages/extension/src/ui/action/components/app-menu/index.vue +++ b/packages/extension/src/ui/action/components/app-menu/index.vue @@ -158,10 +158,19 @@
- + + + + +
@@ -207,6 +216,7 @@ import SearchIcon from '@action/icons/common/search.vue'; import { useMenuStore } from '@action/store/menu-store'; import SolanaStakingBanner from './components/solana-staking-banner.vue'; import BannersState from '@/libs/banners-state'; +import surveyPopup from './components/survey-popup.vue'; const appMenuRef = ref(null); @@ -268,8 +278,9 @@ onMounted(async () => { newNetworksWithTags.value.swap = newSwaps.filter( net => !usedNetworks.swap.includes(net), ); - if (await bannersState.showSolanaStakingBanner()) { - isSolanaStakingBanner.value = true; + isSolanaStakingBanner.value = await bannersState.showSolanaStakingBanner(); + if (!isSolanaStakingBanner.value) { + openSurveyPopup(); } }); @@ -542,17 +553,47 @@ const updateGradient = (newGradient: string) => { * Banners ------------------*/ const isSolanaStakingBanner = ref(false); +const isSurveyPopup = ref(false); + const bannersState = new BannersState(); const closeSolanaStakingBanner = () => { isSolanaStakingBanner.value = false; bannersState.hideSolanaStakingBanner(); + openSurveyPopup(); +}; + +const openSurveyPopup = async () => { + if (await bannersState.showSurveyPopup()) { + setTimeout(() => { + isSurveyPopup.value = true; + }, 4000); + } +}; + +const closeSurveyPopup = () => { + isSurveyPopup.value = false; + bannersState.hideSurveyPopup(); }; diff --git a/packages/extension/src/ui/action/views/restricted/index.vue b/packages/extension/src/ui/action/views/restricted/index.vue new file mode 100644 index 000000000..6660c94f8 --- /dev/null +++ b/packages/extension/src/ui/action/views/restricted/index.vue @@ -0,0 +1,265 @@ + + + + diff --git a/packages/extension/src/ui/action/views/settings/components/settings-inner-header.vue b/packages/extension/src/ui/action/views/settings/components/settings-inner-header.vue index 4e95041d2..91ed4a748 100644 --- a/packages/extension/src/ui/action/views/settings/components/settings-inner-header.vue +++ b/packages/extension/src/ui/action/views/settings/components/settings-inner-header.vue @@ -1,6 +1,6 @@ @@ -112,7 +171,7 @@ import { Connection } from '@solana/web3.js'; import { SwapType } from '@enkryptcom/swap/src/types'; // eslint-disable-next-line @typescript-eslint/no-unused-vars -const debug = (..._args: any[]) => { }; +const debug = (..._args: any[]) => {}; // Use this debug instead to enable debug logging // const debug = console.debug.bind(console); @@ -256,10 +315,10 @@ onMounted(async () => { if (props.network.name === net) { thisNetwork = swapToTokens.all[net as unknown as SupportedNetworkName].length === - 1 + 1 ? getNetworkInfoByName( - NetworkNames.Ethereum as unknown as SupportedNetworkName, - ) + NetworkNames.Ethereum as unknown as SupportedNetworkName, + ) : netInfo; } toNetworks.value.push(netInfo); @@ -550,7 +609,7 @@ const updateQuote = () => { } catch (err) { console.warn( `Failed to convert amount to raw: ${err}` + - ` fromAmount.value=${fromAmount.value} (${typeof fromAmount.value})`, + ` fromAmount.value=${fromAmount.value} (${typeof fromAmount.value})`, ); throw err; } @@ -737,8 +796,8 @@ const sendAction = async () => { if (!fromToken.value!.cgId) { console.warn( `Source token ${fromToken.value!.symbol} (${fromToken.value!.name})` + - ` ${fromToken.value!.address} has no CoinGecko ID, setting price` + - ` to 0`, + ` ${fromToken.value!.address} has no CoinGecko ID, setting price` + + ` to 0`, ); fromPrice = 0; } else { @@ -750,8 +809,8 @@ const sendAction = async () => { if (!toToken.value!.cgId) { console.warn( `Destination token ${toToken.value!.symbol} (${toToken.value!.name})` + - ` ${toToken.value!.address} has no CoinGecko ID, setting price` + - ` to 0`, + ` ${toToken.value!.address} has no CoinGecko ID, setting price` + + ` to 0`, ); toPrice = 0; } else { diff --git a/packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-list-item.vue b/packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-list-item.vue index 36ae02b38..4e3dc5533 100644 --- a/packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-list-item.vue +++ b/packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-list-item.vue @@ -1,7 +1,10 @@