![line](https://github.com/nano-currency/node-cli/raw/main/.github/line.png)

<h1 align="center">Enterprise Nano Wallet</h1>

<p align="center">Zero dependency Nano currency wallet for Browser, Node.js & CLI</p>

<p align="center">
  <a href="https://github.com/fwd/nano-js/actions/workflows/test.yml"><img src="https://github.com/fwd/nano-js/actions/workflows/test.yml/badge.svg" alt="Tests"></a>
  <a href="https://www.npmjs.com/package/@nano/wallet"><img src="https://img.shields.io/npm/v/@nano/wallet.svg?color=blue" alt="npm version"></a>
  <a href="https://www.npmjs.com/package/@nano/wallet"><img src="https://img.shields.io/npm/dm/@nano/wallet.svg?color=blue" alt="npm downloads"></a>
  <a href="https://github.com/fwd/nano-js"><img src="https://img.shields.io/badge/dependencies-0-brightgreen" alt="Zero Dependencies"></a>
  <a href="https://github.com/fwd/nano-js/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/@nano/wallet.svg?color=blue" alt="License"></a>
  <a href="https://github.com/fwd/nano-js"><img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen" alt="Node.js"></a>
  <a href="https://github.com/fwd/nano-js"><img src="https://img.shields.io/badge/ESM%20%7C%20CJS%20%7C%20Browser-universal-blue" alt="Universal"></a>
</p>

![line](https://github.com/nano-currency/node-cli/raw/main/.github/line.png)

## Install

**NPM:**
```bash
npm install @nano/wallet
```

**Browser (CDN):**
```html
<script src="https://unpkg.com/@nano/wallet"></script>
```

**CLI (global):**
```bash
npm install -g @nano/wallet
```

## Import

```js
// CommonJS (require)
const nano = require('@nano/wallet')

// ESM (import)
import nano from '@nano/wallet'

// ESM named imports
import { generate, convert, send, receive, change_rep } from '@nano/wallet'

// Browser (global)
// <script src="https://unpkg.com/@nano/wallet"></script>
// Available as window.nano
```

![line](https://github.com/nano-currency/node-cli/raw/main/.github/line.png)

## Quick Start

```js
const nano = require('@nano/wallet')

nano.app({
    node: 'https://rpc.nano.to',
    rpc_key: 'YOUR_API_KEY', // free key @ rpc.nano.to
    database: 'encrypted_wallet.txt',
    secret: 'SUPER_SECRET_PASSWORD'
})

;(async () => {

    // Create checkout
    var payment = await nano.checkout({ amount: '0.00133' })

    console.log(payment.browser)

    // Wait for payment
    var success = await nano.waitFor(payment)

    // Receive pending
    var receive = await nano.receive()

    // Send payment
    var send = await nano.send({
        to: 'YOUR_FRIENDS_ADDRESS',
        amount: '0.00133'
    })

    console.log(send)

})()
```

![line](https://github.com/nano-currency/node-cli/raw/main/.github/line.png)

## RPC (rpc.nano.to)

This wallet works seamlessly with [rpc.nano.to](https://rpc.nano.to), a free and paid RPC-as-a-Service for the Nano network.

```js
// Free RPC
nano.app({ node: 'https://rpc.nano.to' })

// With API key (higher limits)
nano.app({
    node: 'https://rpc.nano.to',
    rpc_key: 'YOUR_API_KEY'
})

// Raw RPC calls
await nano.rpc({ action: "block_count" })
// { "count": "215474654", "unchecked": "4", "cemented": "215474654" }

await nano.rpc({ action: "account_info", account: "nano_1abc..." })

await nano.rpc({ action: "process", json_block: "true", subtype: "send", block: signedBlock })
```

![line](https://github.com/nano-currency/node-cli/raw/main/.github/line.png)

## CLI

```bash
npm install -g @nano/wallet
```

**Quick Start — 5 commands to send your first Nano:**

```bash
# 1. Create a wallet (encrypted locally)
nano-wallet generate --secret mypassword
# Wallet saved to ./nano-wallet.dat
# Address: nano_3abc...
# Mnemonic: word1 word2 word3 ...

# 2. Print your address (easy copy/paste + browser receive link)
nano-wallet address --secret mypassword
# Address: nano_3abc...
# Receive: https://nano.to/nano_3abc...

# 3. Claim free Nano from the built-in faucet
nano-wallet faucet --secret mypassword
# Faucet claimed! 0.001 NANO is on the way.
#   hash: ABC123...
#   to:   nano_3abc...

# 4. Receive the pending Nano
nano-wallet receive --secret mypassword
# Received 1 block(s):
#   0.001 NANO — hash: ABC123...

# 5. Check your balance
nano-wallet balance --secret mypassword

# 6. Change representative (auto-picks a good one)
nano-wallet change_rep --secret mypassword
# or specify one:
# nano-wallet change_rep nano_1anr... --secret mypassword

# 7. Send Nano to anyone
nano-wallet send nano_1to... 0.00005 --secret mypassword
# Sent 0.00005 NANO
#   to:   nano_1to...
#   hash: DEF456...
#   view: https://nanobrowse.com/block/DEF456...
```

**With environment variables (even cleaner):**

```bash
export NANO_SECRET=mypassword

nano-wallet generate
nano-wallet receive
nano-wallet send nano_1to... 0.001
nano-wallet balance
```

**Utility commands (no wallet needed):**

```bash
# Convert units
nano-wallet convert 1.5 NANO RAW
nano-wallet convert 1000000000000000000000000000000 RAW NANO

# Raw RPC calls
nano-wallet rpc block_count
nano-wallet rpc account_info account=nano_1abc...

# Check any address (no wallet required)
nano-wallet balance nano_1abc...
nano-wallet account_info nano_1abc...

# Print your address and nano.to receive link
nano-wallet address --secret mypassword

# Claim free test Nano (requires NANO_RPC_KEY)
nano-wallet faucet --secret mypassword
nano-wallet faucet nano_3abc... --secret mypassword   # or pass address directly

# Encrypt / decrypt files
nano-wallet encrypt myfile.json mypassword
nano-wallet decrypt encrypted.txt mypassword

# Sign a block manually
nano-wallet sign '{"walletBalanceRaw":"1000...","toAddress":"nano_1..."}' PRIVATE_KEY
```

**All options:**

```
Options:
  --secret <password>     Wallet password (encrypts/decrypts wallet file)
  --wallet <file>         Wallet file path (default: ./nano-wallet.dat)
  --node <url>            RPC endpoint (default: https://rpc.nano.to)
  --key <api_key>         RPC API key for rpc.nano.to
  --json                  Output raw JSON

Environment Variables:
  NANO_SECRET             Wallet password
  NANO_WALLET             Wallet file path
  NANO_RPC                RPC endpoint
  NANO_RPC_KEY            API key for rpc.nano.to
```

![line](https://github.com/nano-currency/node-cli/raw/main/.github/line.png)

## Offline API

```js
nano.generate()
```
```js
nano.import( nano.generate() )
```
```js
nano.accounts()
```
```js
nano.add_account()
```
```js
nano.sign(block)
```
```js
nano.convert('421.70', 'NANO', 'RAW') // 421700000000000000000000000000000
```
```js
nano.encrypt('any_string', process.env.PASSWORD) // AES-256
```
```js
nano.decrypt('any_string', process.env.PASSWORD) // UTF-8
```
```js
nano.export()
```

## Wallet Management

> Build non-custodial Nano applications with AES-256 encrypted wallet persistence.

```js
nano.app({ 
    node: 'https://rpc.nano.to',
    rpc_key: 'RPC_API_KEY', // get free key @ rpc.nano.to
    database: 'aes_string.txt', 
    secret: 'SUPER_SECRET_PASSWORD'
})

console.log( nano.accounts() )

await nano.receive()

await nano.send({ to: '@faucet', amount: 0.001 })
```

## Multi-Account (Metadata)

```js
nano.app({ 
    node: 'https://rpc.nano.to',
    rpc_key: 'RPC_API_KEY',
    database: 'aes_string.txt', 
    secret: 'SUPER_SECRET_PASSWORD'
})

const user = { userId: 'JoeDoe' }

console.log( nano.add_account(user) )

await nano.receive(user)

var balance = await nano.balance(user)

console.log( balance )

await nano.send({ 
    to: user, 
    from: 0,
    amount: '0.0000133'
})
```

## Balances

```js
// get all balances
await nano.balances()

// get balance of specific address
await nano.balance({ userId: 'johnDoe' })
// {
//     "balance": "325586539664609129644855132177",
//     "pending": "2309372510769300000000000000000000",
//     "receivable": "2309372510769300000000000000000000",
//     "balance_nano": "0.32558653966460912964",
//     "pending_nano": "2309.3725107693",
//     "receivable_nano": "2309.3725107693"
// }
```

## Send

```js
// send to globally known accounts
await nano.send({ to: '@fosse', amount: 0.1 })

// send to multiple accounts
await nano.send({ to: [ '@fosse', '@bank' ], amount: 0.1 })

// send all funds on address
await nano.send({ to: '@fosse', amount: 'all' })

// transfer between your own accounts
await nano.send({ to: 1, from: 0, amount: 0.1 })

// transfer between your own users
await nano.send({ to: { userId: 'johnDoe' }, from: { userId: 'janeDoe' }, amount: 0.1 })
```

## Receive

```js
// receive all
await nano.receive()

// receive all for specific address
await nano.receive({ userId: 'johnDoe' })
```

## Change Representative

```js
// auto-pick a good rep from rpc.nano.to
await nano.change_rep()

// specify a rep address
await nano.change_rep('nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs')

// with config object
await nano.change_rep({ rep: 'nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs' })
// {
//     "hash": "BLOCK_HASH",
//     "representative": "nano_1anr...",
//     "account": "nano_3abc...",
//     "browser": "https://nanobrowse.com/block/BLOCK_HASH"
// }
```

When no representative address is provided, the wallet fetches a list of available representatives from `rpc.nano.to` (via the `reps` RPC action) and automatically picks one at random.

## Checkout

```js
var checkout = await nano.checkout({ address: 0, amount: '0.133' })
console.log( checkout )
// {
//     "id": "CHECKOUT_ID",
//     "browser": "https://nano.to/id_CHECKOUT_ID",
//     "json": "https://api.nano.to/checkout/CHECKOUT_ID",
//     "check": "https://api.nano.to/check/CHECKOUT_ID",
//     "address": "YOUR_ADDRESS",
//     "qrcode": "data:image/png;base64"
// }

var payment = await nano.waitFor(checkout)
console.log( payment )
// {
//     id: 'b06a8127',
//     success: true,
//     block: '3C0D9A50649C6BE...',
//     amount: '0.133',
//     amount_raw: '1330000000000000000000000'
// }
```

## Manual Signing

**SEND**

```js
var send = nano.sign({
    walletBalanceRaw: '18618869000000000000000000000000',
    toAddress: 'nano_3kyb49tqpt39ekc49kbej51ecsjqnimnzw1swxz4boix4ctm93w517umuiw8',
    representativeAddress: 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou',
    frontier: '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D',
    transactionHash: 'CBC911F57B6827649423C92C88C0C56637A4274FF019E77E24D61D12B5338783',
    amountRaw: '7000000000000000000000000000000',
}, process.env.PRIVATE_KEY) 
```

**RECEIVE**

```js
var receive = nano.sign({
    walletBalanceRaw: '18618869000000000000000000000000',
    toAddress: 'nano_3kyb49tqpt39ekc49kbej51ecsjqnimnzw1swxz4boix4ctm93w517umuiw8',
    representativeAddress: 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou',
    frontier: '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D',
    transactionHash: 'CBC911F57B6827649423C92C88C0C56637A4274FF019E77E24D61D12B5338783',
    amountRaw: '7000000000000000000000000000000',
    work: 'c5cf86de24b24419',
}, process.env.PRIVATE_KEY) 

var hash = await nano.process( receive )
```

**CHANGE_REP**

```js
var change_rep = nano.sign({
    walletBalanceRaw: '3000000000000000000000000000000',
    address: 'nano_3igf8hd4sjshoibbbkeitmgkp1o6ug4xads43j6e4gqkj5xk5o83j8ja9php',
    representativeAddress: 'nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs',
    frontier: '128106287002E595F479ACD615C818117FCB3860EC112670557A2467386249D4',
    work: '0000000000000000',
}, process.env.PRIVATE_KEY) 

var hash = await nano.process( change_rep )
```

## Export Wallet

> JSON object, stringified and encrypted with AES-256

```js
nano.offline({ 
    filename: 'aes_string.txt', 
    password: process.env.PASSWORD
})

console.log( nano.export() )
```

![line](https://github.com/nano-currency/node-cli/raw/main/.github/line.png)

## Zero Dependencies

This package has **zero external npm dependencies**. All cryptographic libraries are vendored and sandboxed directly in the source:

- [nanocurrency-web-js](https://github.com/numsu/nanocurrency-web-js) — Wallet generation, block signing, Ed25519, Blake2b
- [crypto-js](https://github.com/brix/crypto-js) — AES-256 encryption (unified across Browser & Node.js)

This eliminates supply chain attack vectors while keeping the package fully self-contained.

![line](https://github.com/nano-currency/node-cli/raw/main/.github/line.png)

## Upgrading from v1.x

v3 replaced the `aes256` npm dependency with the vendored CryptoJS library for encryption. **Existing v1.x wallets are automatically migrated** when loaded — no action is required in most cases.

### Automatic Migration

When `nano.offline()` or `nano.import()` detects a legacy wallet, it:
1. Decrypts with the old format (AES-256-CTR)
2. Re-encrypts with the new format (AES-256-CBC)
3. Saves the updated file

```js
// Just load your wallet as usual — migration happens automatically
nano.offline({ database: 'my_old_wallet.txt', secret: 'my_password' })
// Console: @nano/wallet: Migrated wallet from legacy format to AES-256-CBC.
```

### Manual Migration

```js
// Migrate a wallet file without loading it
nano.migrate({ database: 'my_old_wallet.txt', secret: 'my_password' })
// { migrated: true, accounts: 1, file: 'my_old_wallet.txt' }
```

### CLI Migration

```bash
# Decrypt legacy wallet and inspect
nano-wallet decrypt my_old_wallet.txt my_password

# Re-encrypt in new format
nano-wallet encrypt decrypted_output.json my_password > my_new_wallet.txt
```

> **Note:** Browser wallets are unaffected — they always used CryptoJS.

![line](https://github.com/nano-currency/node-cli/raw/main/.github/line.png)

## Faucet

Claim 0.001 free test NANO in one step. Requires an RPC key from [rpc.nano.to](https://rpc.nano.to).

```js
nano.app({
    node: 'https://rpc.nano.to',
    rpc_key: 'YOUR_RPC_KEY',
    database: 'nano-wallet.dat',
    secret: 'mypassword'
})

// Auto-detect address from loaded wallet
var result = await nano.faucet()

// Or pass an address explicitly
var result = await nano.faucet('nano_3abc...')

console.log(result)
// {
//   success: true,
//   message: '0.001 NANO sent to nano_3abc...',
//   claim: {
//     id: 42,
//     nano_address: 'nano_3abc...',
//     amount: '0.001',
//     status: 'sent',
//     tx_hash: 'ABC123...',
//     created_at: '2026-02-18T12:00:00.000Z'
//   }
// }
```

## GET FREE NANO

- Built-in faucet: `nano-wallet faucet --secret mypassword` (requires RPC key)
- https://nanodrop.io/
- https://freenanofaucet.com/
- https://getnano.ovh/faucet

## License

MIT

![line](https://github.com/nano-currency/node-cli/raw/main/.github/line.png)

## Sponsor (DigitalOcean)

<a align="center" target="_blank" href="https://m.do.co/c/f139acf4ddcb"><img style="object-fit: contain;
    max-width: 100%;" src="https://github.com/fwd/fwd/raw/master/ads/digitalocean_new.png" width="970" /></a>

![line](https://github.com/nano-currency/node-cli/raw/main/.github/line.png)

## Stargazers

[![Stargazers over time](https://starchart.cc/fwd/nano-js.svg)](https://github.com/fwd/nano-js)
