# Wallets

This guide covers two perspectives: connecting your **dApp** to the Armchain Wallet, and building **custom wallet** support for Armchain.

## Armchain Wallet

The **Armchain Wallet** is the official browser extension wallet for the Armchain network. It is a fork of Wigwam wallet, customized for ML-DSA44 post-quantum cryptography.

### Key Features

* **ML-DSA44 key management**: Generates and stores post-quantum keys
* **HD wallet derivation**: BIP-39 mnemonic with Armchain coin type (`65536`)
* **Hardened derivation only**: All child keys use hardened paths for security
* **Type 3 transactions**: Signs PQC transactions natively
* **EIP-1559 gas pricing**: Dynamic fee support
* **Multi-account support**: Derive multiple accounts from a single seed phrase
* **ARM token support**: Native token balance display and transfers

### Network Configuration

The wallet ships with built-in Armchain network configurations:

```typescript
// Devnet
{
  chainId: 55,
  name: "Armchain Devnet",
  rpcUrls: ["https://www.armchain.org/devnet"],
  nativeCurrency: { symbol: "ARM", name: "Armchain", decimals: 18 },
}

// Local Development
{
  chainId: 55,
  name: "Armchain Local",
  rpcUrls: ["http://localhost:4000"],
  nativeCurrency: { symbol: "ARM", name: "Armchain", decimals: 18 },
}
```

## For dApp Developers

### Connecting to the Wallet

The Armchain Wallet injects a provider into the browser, similar to MetaMask:

```typescript
// Check if wallet is available
if (typeof window.ethereum !== "undefined") {
  // Armchain Wallet detected
}

// Request account access
const accounts = await window.ethereum.request({
  method: "eth_requestAccounts"
});
console.log("Connected account:", accounts[0]);
```

### Using with Armchain Ethers SDK

```typescript
import { BrowserProvider, Contract } from "@armchain-ethersv6/ethers";

// Connect to injected wallet
const provider = new BrowserProvider(window.ethereum);
const signer = await provider.getSigner();

console.log("Connected:", await signer.getAddress());
console.log("Balance:", await provider.getBalance(signer.address));

// Interact with contracts
const contract = new Contract(contractAddress, abi, signer);
const tx = await contract.someFunction(arg1, arg2);
await tx.wait();
```

### Handling Chain Switching

```typescript
// Switch to Armchain devnet
try {
  await window.ethereum.request({
    method: "wallet_switchEthereumChain",
    params: [{ chainId: "0x37" }],  // 55 in hex
  });
} catch (switchError) {
  // Chain not added - request to add it
  if (switchError.code === 4902) {
    await window.ethereum.request({
      method: "wallet_addEthereumChain",
      params: [{
        chainId: "0x37",
        chainName: "Armchain Devnet",
        rpcUrls: ["https://www.armchain.org/devnet"],
        nativeCurrency: {
          name: "Armchain",
          symbol: "ARM",
          decimals: 18,
        },
        blockExplorerUrls: ["https://www.armchain.org/explorer"],
      }],
    });
  }
}
```

### Listening for Events

```typescript
// Account changed
window.ethereum.on("accountsChanged", (accounts) => {
  console.log("Account switched to:", accounts[0]);
  // Refresh account-dependent UI
});

// Chain changed
window.ethereum.on("chainChanged", (chainId) => {
  console.log("Chain switched to:", parseInt(chainId, 16));
  // Reload the page or refresh state
  window.location.reload();
});

// Disconnected
window.ethereum.on("disconnect", () => {
  console.log("Wallet disconnected");
});
```

### Signing Messages

```typescript
const signer = await provider.getSigner();

// Personal sign (EIP-191)
const message = "Sign this message to verify your identity";
const signature = await signer.signMessage(message);

// The signature is an ML-DSA44 signature (3,732 bytes)
console.log("Signature:", signature);
```

### EIP-712 Typed Data Signing

```typescript
const domain = {
  name: "My dApp",
  version: "1",
  chainId: 55,
  verifyingContract: "0xCONTRACT_ADDRESS",
};

const types = {
  Order: [
    { name: "maker", type: "address" },
    { name: "amount", type: "uint256" },
    { name: "nonce", type: "uint256" },
  ],
};

const value = {
  maker: await signer.getAddress(),
  amount: parseEther("100"),
  nonce: 1,
};

const signature = await signer.signTypedData(domain, types, value);
```

## For Wallet Developers

If you're building a wallet that supports Armchain, here are the key requirements. The recommended approach is to use the `@armchain-ethersv6/ethers` SDK, which handles all cryptographic operations internally.

### Key Generation

Armchain uses ML-DSA44 (NIST FIPS 204) for all key operations. Key pairs are generated from a 32-byte random seed.

| Component   | Size        |
| ----------- | ----------- |
| Private Key | 2,560 bytes |
| Public Key  | 1,312 bytes |

The SDK's `Wallet.createRandom()` and `HDNodeWallet.fromPhrase()` handle key generation automatically. If implementing from scratch, use a FIPS 204-compliant ML-DSA44 library.

### HD Wallet Derivation

Armchain uses a BIP-44 compatible derivation path with all hardened indices:

```
m/44'/65536'/account'/0/address'
```

> **Critical**: Non-hardened derivation is NOT supported with ML-DSA44. All path components must use hardened derivation.

Since ML-DSA44 key generation takes a 32-byte seed (unlike ECDSA's scalar), the HD derivation chain produces child seeds rather than child keys directly. See the `@armchain-ethersv6/ethers` SDK source for the reference implementation.

```typescript
// Derive accounts using the SDK
import { HDNodeWallet } from "@armchain-ethersv6/ethers";

const wallet = HDNodeWallet.fromPhrase(mnemonic);
const child = wallet.derivePath("m/44'/65536'/0'/0/0'");
console.log("Address:", child.address);
```

### Transaction Signing

All Armchain transactions must be Type 3 (PQC). The SDK handles transaction construction and signing:

```typescript
import { Wallet, JsonRpcProvider } from "@armchain-ethersv6/ethers";

const provider = new JsonRpcProvider("https://www.armchain.org/devnet");
const wallet = new Wallet(privateKey, provider);

// The SDK automatically creates Type 3 transactions and signs with ML-DSA44
const tx = await wallet.sendTransaction({
  to: recipient,
  value: amount,
  // type: 3 is auto-set
});
```

For custom implementations, the signing process involves computing a transaction hash and producing an ML-DSA44 signature blob that includes both the raw signature and the public key (since ML-DSA44 does not support public key recovery). Refer to the [Transaction Types](/pqc/transaction-types.md) page for the wire format specification.

### Address Computation

Armchain addresses are derived from ML-DSA44 public keys using `keccak256`, producing standard 20-byte Ethereum-format addresses. The SDK handles this automatically via `SigningKey.computeAddress()`.

### Key Storage Considerations

ML-DSA44 private keys are **2,560 bytes** (vs 32 bytes for ECDSA). This affects:

| Aspect              | ECDSA       | ML-DSA44        | Impact                             |
| ------------------- | ----------- | --------------- | ---------------------------------- |
| Private key storage | 32 bytes    | 2,560 bytes     | \~80× more storage                 |
| Key encryption time | Fast        | Slightly slower | Negligible                         |
| Key backup size     | Small       | Larger          | QR codes may not work for raw keys |
| Mnemonic backup     | 12/24 words | 12/24 words     | Same: mnemonic derives the key     |

> **Recommendation**: Always support mnemonic-based backup. The 12/24 word seed phrase is the same size regardless of the underlying key type.

## Common Integration Patterns

### Connect Wallet Button

```typescript
async function connectWallet() {
  if (!window.ethereum) {
    alert("Please install Armchain Wallet");
    return;
  }

  try {
    const accounts = await window.ethereum.request({
      method: "eth_requestAccounts"
    });
    
    const chainId = await window.ethereum.request({
      method: "eth_chainId"
    });

    if (parseInt(chainId, 16) !== 55) {
      // Not on Armchain - request switch
      await switchToArmchain();
    }

    return accounts[0];
  } catch (error) {
    console.error("Connection failed:", error);
  }
}
```

### Transaction Helper

```typescript
import { BrowserProvider, parseEther } from "@armchain-ethersv6/ethers";

async function sendARM(to: string, amount: string) {
  const provider = new BrowserProvider(window.ethereum);
  const signer = await provider.getSigner();

  const tx = await signer.sendTransaction({
    to,
    value: parseEther(amount),
  });

  // Instant finality means one confirmation is enough
  const receipt = await tx.wait();
  return receipt;
}
```

## Further Reading

* [Armchain Ethers SDK](/developers/overview-1.md) for the full SDK reference
* [PQC Overview](/pqc/overview.md) to understand post-quantum cryptography
* [Transaction Types](/pqc/transaction-types.md) for the Type 3 transaction format
* [Network Configuration](/get-started/network-configuration.md) for RPC endpoints and chain details


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.armchain.org/developers/overview-2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
