home / skills / multiversx / mx-ai-skills / mvx_sdk_js_wallets

mvx_sdk_js_wallets skill

/antigravity/skills/mvx_sdk_js_wallets

This skill helps manage accounts, derive keys, and sign transactions securely using the MultiversX JS SDK.

npx playbooks add skill multiversx/mx-ai-skills --skill mvx_sdk_js_wallets

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
2.6 KB
---
name: mvx_sdk_js_wallets
description: Wallet and key management for MultiversX TypeScript/JavaScript SDK.
---

# MultiversX SDK-JS Wallets & Signing

This skill covers account management, key derivation, and transaction signing.

## Account Creation

```typescript
import { Account, Address, Mnemonic, UserWallet, UserPem } from "@multiversx/sdk-core";

// From PEM file (testing only - not secure)
const account = await Account.newFromPem("wallet.pem");

// From keystore (production)
const account = await Account.newFromKeystore("wallet.json", "password");

// From entrypoint (generates new)
const account = entrypoint.createAccount();
```

## Mnemonic Operations

```typescript
// Generate new mnemonic (24 words)
const mnemonic = Mnemonic.generate();
const words = mnemonic.getWords();

// Derive keys
const secretKey = mnemonic.deriveKey(0);  // First account
const publicKey = secretKey.generatePublicKey();
const address = publicKey.toAddress();
```

## Wallet Storage

```typescript
// Save mnemonic to keystore
const wallet = UserWallet.fromMnemonic({
    mnemonic: mnemonic.toString(),
    password: "secure-password"
});
wallet.save("wallet.json");

// Save secret key to keystore
const wallet = UserWallet.fromSecretKey({
    secretKey: secretKey,
    password: "secure-password"
});
wallet.save("wallet.json");

// Save to PEM (testing only)
const pem = new UserPem(address.toBech32(), secretKey);
pem.save("wallet.pem");
```

## Transaction Signing

```typescript
// Controller-created transactions are auto-signed
const tx = await controller.createTransactionForTransfer(account, nonce, options);
// tx.signature is already set

// Factory-created transactions need manual signing
const tx = await factory.createTransactionForTransfer(sender, options);
tx.nonce = account.getNonceThenIncrement();
tx.signature = await account.signTransaction(tx);
```

## Message Signing

```typescript
// Sign arbitrary message
const message = new SignableMessage({ message: Buffer.from("Hello") });
const signature = await account.signMessage(message);

// Verify signature
import { MessageSigner } from "@multiversx/sdk-core";
const isValid = MessageSigner.verify(message, signature, publicKey);
```

## Ledger Device

```typescript
// Ledger requires MultiversX app installed
import { LedgerAccount } from "@multiversx/sdk-hw-provider";

const ledger = new LedgerAccount();
await ledger.init();
const address = await ledger.getAddress(0);
```

## Security Best Practices

| Practice | Reason |
|----------|--------|
| Use keystore files | Encrypted with password |
| Never commit PEM files | Plain text private keys |
| Use Ledger for mainnet | Hardware security |
| Validate addresses | Prevent typos |

Overview

This skill provides wallet and key management utilities for the MultiversX TypeScript/JavaScript SDK. It covers account creation, mnemonic generation and derivation, keystore and PEM storage, transaction and message signing, and Ledger hardware integration. The focus is on practical APIs for secure account handling and signing flows in client and server environments.

How this skill works

The skill exposes routines to create accounts from PEM, keystore, or freshly generated mnemonics and secret keys. It supports deriving secret and public keys from BIP-style mnemonics, converting public keys to addresses, and saving keys into encrypted keystore files or PEMs (for testing). It also provides signing helpers for transactions and arbitrary messages, plus a LedgerAccount integration for hardware-backed keys.

When to use it

  • Create new wallets and accounts in JS/TS apps
  • Derive keys and addresses from a mnemonic for user wallets
  • Sign transactions programmatically in backend or frontend flows
  • Verify signed messages or transaction signatures
  • Integrate Ledger devices for hardware-backed signing

Best practices

  • Prefer keystore (encrypted JSON) over PEM files for production to avoid plain-text private keys
  • Use hardware wallets like Ledger for mainnet or high-value accounts
  • Keep mnemonics and secret keys offline whenever possible and never commit them to version control
  • Validate addresses and use nonces from the account object to avoid replay or nonce conflicts
  • Only sign controller-generated transactions automatically; manually set nonce and signature for factory-created transactions

Example use cases

  • Create a new user wallet: generate mnemonic, derive secret key, save to keystore with password
  • Recover an account: load keystore.json with password or import mnemonic to regenerate keys and address
  • Sign a transfer transaction: set nonce, sign transaction with Account.signTransaction, then broadcast
  • Sign and verify an arbitrary message: use SignableMessage and MessageSigner.verify for authentication flows
  • Ledger integration: initialize LedgerAccount, read address for index 0, and use it for signing without exposing private key

FAQ

Can I use PEM files in production?

No. PEM files contain private keys in plain text and are suitable only for testing. Use keystore files encrypted with a strong password for production.

How do I avoid nonce conflicts when signing transactions manually?

Use account.getNonceThenIncrement() to fetch the current nonce and increment it locally before signing to ensure unique nonces for sequential transactions.