Package Exports
- node-arweave-wallet
- node-arweave-wallet/package.json
Readme
node-arweave-wallet
Use Arweave browser wallets (Wander or any other compatible wallet) from Node.js applications. Perfect for CLI tools and scripts that need secure wallet interactions without exposing private keys.
✨ Features
- 🔐 Full Arweave Wallet API Support - Complete implementation of the arweaveWallet API
- 🌐 Browser-Based Security - Uses your existing browser wallet (Wander or any other compatible wallet), keeping keys secure
- 🔌 @permaweb/aoconnect Compatible - Works seamlessly with
@permaweb/aoconnect
📦 Installation
npm install node-arweave-wallet
# or
pnpm add node-arweave-wallet
# or
yarn add node-arweave-wallet🚀 Quick Start
import { NodeArweaveWallet } from 'node-arweave-wallet'
// Create wallet instance
const wallet = new NodeArweaveWallet({
port: 3737 // Optional: defaults to 3737, use 0 for random port
})
// Initialize - opens browser for wallet connection
await wallet.initialize()
// Connect with required permissions
await wallet.connect([
'ACCESS_ADDRESS',
'SIGN_TRANSACTION'
])
// Get wallet address
const address = await wallet.getActiveAddress()
console.log('Connected wallet:', address)
// Sign a transaction
const tx = await arweave.createTransaction({ data: 'Hello Arweave!' })
await wallet.sign(tx)
// Submit the transaction
const response = await arweave.transactions.post(tx)
console.log(response.status)
// Clean up when done
await wallet.close('success')📖 API Reference
Initialization & Connection
new NodeArweaveWallet(config?)
Creates a new wallet instance.
const wallet = new NodeArweaveWallet({
port: 3737 // Optional: port number (default: 3737, use 0 for random)
})wallet.initialize()
Starts the local server and opens the browser for wallet connection.
await wallet.initialize()wallet.connect(permissions, appInfo?, gateway?)
Programmatically connects to the wallet with specified permissions.
await wallet.connect(
['ACCESS_ADDRESS', 'SIGN_TRANSACTION'],
{
name: 'My App',
logo: 'https://example.com/logo.png'
}
)Available Permissions:
ACCESS_ADDRESS- Get active wallet addressACCESS_PUBLIC_KEY- Get public keyACCESS_ALL_ADDRESSES- Get all wallet addressesSIGN_TRANSACTION- Sign Arweave transactionsENCRYPT- Encrypt dataDECRYPT- Decrypt dataSIGNATURE- Sign arbitrary dataACCESS_ARWEAVE_CONFIG- Get Arweave gateway configDISPATCH- Sign and dispatch transactionsACCESS_TOKENS- Access tokens & token balances
wallet.disconnect()
Disconnects from the wallet.
await wallet.disconnect()wallet.close(status?)
Closes the wallet connection and server. Optionally marks completion status.
await wallet.close('success') // or 'failed'Wallet Information
wallet.getActiveAddress()
Gets the currently active wallet address.
const address = await wallet.getActiveAddress()
// Returns: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"wallet.getAllAddresses()
Gets all addresses in the wallet.
const addresses = await wallet.getAllAddresses()
// Returns: ["address1", "address2", ...]wallet.getWalletNames()
Gets wallet names mapped to addresses.
const names = await wallet.getWalletNames()
// Returns: { "address1": "Wallet 1", "address2": "Wallet 2" }wallet.getActivePublicKey()
Gets the public key of the active wallet.
const publicKey = await wallet.getActivePublicKey()
// Returns: base64 encoded public keywallet.getPermissions()
Gets currently granted permissions.
const permissions = await wallet.getPermissions()
// Returns: ["ACCESS_ADDRESS", "SIGN_TRANSACTION", ...]wallet.getArweaveConfig()
Gets the Arweave gateway configuration.
const config = await wallet.getArweaveConfig()
// Returns: { host: "arweave.net", port: 443, protocol: "https" }Transaction Signing
wallet.sign(transaction, options?)
Signs an Arweave transaction.
import Arweave from 'arweave'
const arweave = new Arweave({
host: 'arweave.net',
port: 443,
protocol: 'https'
})
const tx = await arweave.createTransaction({
data: 'Hello Arweave!'
})
await wallet.sign(tx)wallet.dispatch(transaction, options?)
Signs and dispatches a transaction to the network.
const tx = await arweave.createTransaction({
data: 'Hello Arweave!'
})
tx.addTag('Content-Type', 'text/plain')
const result = await wallet.dispatch(tx)
console.log('Transaction ID:', result.id)
// Returns: { id: "transaction_id", type?: "BASE" | "BUNDLED" }Data Item Signing (ANS-104)
wallet.signDataItem(dataItem, options?)
Signs a single data item for ANS-104 bundling.
const signedDataItem = await wallet.signDataItem({
data: 'Hello from data item!',
tags: [
{ name: 'Content-Type', value: 'text/plain' },
{ name: 'App-Name', value: 'MyApp' }
],
target: 'target_address',
anchor: 'anchor'
})
// Returns: Uint8Array of signed data itemwallet.batchSignDataItem(dataItems, options?)
Signs multiple data items in a batch.
const results = await wallet.batchSignDataItem([
{
data: 'First item',
tags: [{ name: 'Type', value: 'Test1' }]
},
{
data: 'Second item',
tags: [{ name: 'Type', value: 'Test2' }]
}
])
// Returns: Array<{ id: string, raw: Uint8Array }>wallet.getDataItemSigner() or createDataItemSigner(wallet)
Creates a signer compatible with @permaweb/aoconnect.
import { message } from '@permaweb/aoconnect'
import { createDataItemSigner } from 'node-arweave-wallet'
const signer = createDataItemSigner(wallet)
const messageId = await message({
process: 'PROCESS_ID',
signer,
tags: [{ name: 'Action', value: 'Hello' }],
data: 'Hello from browser wallet!'
})Encryption & Decryption
wallet.encrypt(data, options)
Encrypts data using the wallet's public key.
const encrypted = await wallet.encrypt('Secret message', {
algorithm: 'RSA-OAEP',
hash: 'SHA-256'
})
// Returns: Uint8Arraywallet.decrypt(data, options)
Decrypts data using the wallet's private key.
const decrypted = await wallet.decrypt(encrypted, {
algorithm: 'RSA-OAEP',
hash: 'SHA-256'
})
const text = new TextDecoder().decode(decrypted)
// Returns: "Secret message"Message Signing & Verification
wallet.signMessage(data, options?)
Signs a message with the wallet's private key.
const data = new TextEncoder().encode('Message to sign')
const signature = await wallet.signMessage(data, {
hashAlgorithm: 'SHA-256' // or 'SHA-384', 'SHA-512'
})
// Returns: Uint8Array signaturewallet.verifyMessage(data, signature, publicKey?, options?)
Verifies a message signature.
const isValid = await wallet.verifyMessage(
data,
signature,
publicKey, // optional
{ hashAlgorithm: 'SHA-256' }
)
// Returns: booleanwallet.signature(data, algorithm)
Signs arbitrary data with custom algorithm.
const data = new TextEncoder().encode('Data to sign')
const signature = await wallet.signature(data, {
name: 'RSA-PSS',
saltLength: 32
})
// Returns: Uint8Arraywallet.privateHash(data, options?)
Creates a hash using the wallet's private key.
const data = new TextEncoder().encode('Data to hash')
const hash = await wallet.privateHash(data, {
hashAlgorithm: 'SHA-256'
})
// Returns: Uint8Array🛠️ Configuration
Port Configuration
The package uses a local HTTP server to communicate with the browser. You can configure the port:
// Default port (3737)
const wallet = new NodeArweaveWallet()
// Custom port
const wallet = new NodeArweaveWallet({ port: 8080 })
// Random available port (useful for testing or avoiding conflicts)
const wallet = new NodeArweaveWallet({ port: 0 })💡 Usage Examples
CLI Tool Example
#!/usr/bin/env node
import Arweave from 'arweave'
import { NodeArweaveWallet } from 'node-arweave-wallet'
async function deployFile(filePath: string) {
const wallet = new NodeArweaveWallet()
try {
console.log('🚀 Initializing wallet...')
await wallet.initialize()
await wallet.connect(['ACCESS_ADDRESS', 'SIGN_TRANSACTION', 'DISPATCH'])
const address = await wallet.getActiveAddress()
console.log(`✅ Connected: ${address}`)
const arweave = new Arweave({
host: 'arweave.net',
port: 443,
protocol: 'https'
})
const data = fs.readFileSync(filePath)
const tx = await arweave.createTransaction({ data })
tx.addTag('Content-Type', 'text/plain')
console.log('📝 Signing and deploying...')
const result = await wallet.dispatch(tx)
console.log(`✅ Deployed! TX: ${result.id}`)
console.log(`🔗 https://arweave.net/${result.id}`)
await wallet.close('success')
}
catch (error) {
console.error('❌ Error:', error.message)
await wallet.close('failed')
process.exit(1)
}
}
deployFile(process.argv[2])AO Process Example
import { message, result } from '@permaweb/aoconnect'
import { createDataItemSigner, NodeArweaveWallet } from 'node-arweave-wallet'
async function sendAOMessage() {
const wallet = new NodeArweaveWallet()
await wallet.initialize()
await wallet.connect(['ACCESS_ADDRESS', 'SIGN_TRANSACTION'])
const signer = createDataItemSigner(wallet)
const messageId = await message({
process: 'PROCESS_ID',
signer,
tags: [
{ name: 'Action', value: 'Balance' }
]
})
console.log('Message sent:', messageId)
const { Messages } = await result({
message: messageId,
process: 'PROCESS_ID'
})
console.log('Response:', Messages[0].Data)
await wallet.close('success')
}Batch Data Item Example
import { NodeArweaveWallet } from 'node-arweave-wallet'
async function batchUpload(files: string[]) {
const wallet = new NodeArweaveWallet()
await wallet.initialize()
await wallet.connect(['ACCESS_ADDRESS', 'SIGN_TRANSACTION'])
const dataItems = files.map(file => ({
data: fs.readFileSync(file),
tags: [
{ name: 'Content-Type', value: 'application/octet-stream' },
{ name: 'File-Name', value: path.basename(file) }
]
}))
console.log(`📝 Signing ${files.length} files...`)
const signed = await wallet.batchSignDataItem(dataItems)
console.log('✅ All files signed!')
signed.forEach((item, i) => {
console.log(` ${i + 1}. ${item.id}`)
})
await wallet.close('success')
}🔒 Security
- No Private Keys in Node.js - Your private keys never leave the browser wallet
- Browser Extension Security - Leverages battle-tested browser wallet security
- Local-Only Server - Server only listens on
127.0.0.1(localhost) - Permission-Based - Request only the permissions you need
🤝 Browser Wallet Compatibility
Works with any arweaveWallet compatible browser wallet:
- ✅ Wander (Recommended)
- ✅ Any wallet implementing the arweaveWallet API
🐛 Troubleshooting
Port Already in Use
If port 3737 is already in use:
// Use a different port
const wallet = new NodeArweaveWallet({ port: 8080 })
// Or let the system choose an available port
const wallet = new NodeArweaveWallet({ port: 0 })Browser Doesn't Open Automatically
The URL will be printed to the console. Open it manually:
http://localhost:3737Connection Timeout
Keep the browser tab open while signing transactions. The package has a generous 5-minute timeout, but closing the tab will interrupt operations.
📄 License
MIT License © Pawan Paudel