Skip to content

Latest commit

 

History

History
462 lines (335 loc) · 13.7 KB

File metadata and controls

462 lines (335 loc) · 13.7 KB

Node.js SDK

Native bindings for Node.js via NAPI. No CLI, no server, no subprocess — the Rust core runs in-process.

This document is non-normative reference implementation documentation. Package names and function signatures here do not define the OWS standard.

npm

Install

npm install @open-wallet-standard/core

The package includes prebuilt native binaries for macOS (arm64, x64) and Linux (x64, arm64). No Rust toolchain required.

Quick Start

import {
  generateMnemonic,
  createWallet,
  listWallets,
  signMessage,
  signTypedData,
  deleteWallet,
} from "@open-wallet-standard/core";

const mnemonic = generateMnemonic(12);
const wallet = createWallet("my-wallet");
const sig = signMessage("my-wallet", "evm", "hello");
console.log(sig.signature);

API Reference

Types

interface AccountInfo {
  chainId: string;        // CAIP-2 chain ID (e.g. "eip155:1")
  address: string;        // Chain-native address
  derivationPath: string; // BIP-44 path (e.g. "m/44'/60'/0'/0/0")
}

interface WalletInfo {
  id: string;             // UUID v4
  name: string;
  accounts: AccountInfo[];
  createdAt: string;      // ISO 8601
}

interface SignResult {
  signature: string;      // Hex-encoded signature
  recoveryId?: number;    // EVM/Tron recovery ID (v value)
}

interface SendResult {
  txHash: string;         // Transaction hash
}

Mnemonic

generateMnemonic(words?)

Generate a new BIP-39 mnemonic phrase.

const phrase = generateMnemonic(12);  // or 24
// => "goose puzzle decorate much stable beach ..."
Param Type Default Description
words number 12 Word count (12 or 24)

Returns: string

deriveAddress(mnemonic, chain, index?)

Derive an address from a mnemonic without creating a wallet.

const addr = deriveAddress(mnemonic, "evm");
// => "0xCc1e2c3D077b7c0f5301ef400bDE30d0e23dF1C6"

const solAddr = deriveAddress(mnemonic, "solana");
// => "DzkqyvQrBvLqKSMhCoXoGK65e9PvyWjb6YjS4BqcxN2i"
Param Type Default Description
mnemonic string BIP-39 mnemonic phrase
chain string "evm", "solana", "sui", "bitcoin", "cosmos", "tron", "filecoin"
index number 0 Account index in derivation path

Returns: string

Wallet Management

createWallet(name, passphrase?, words?, vaultPath?)

Create a new wallet. Generates a mnemonic and derives addresses for the current auto-derived chain set.

const wallet = createWallet("agent-treasury");
console.log(wallet.accounts);
// => [
//   { chainId: "eip155:1", address: "0x...", derivationPath: "m/44'/60'/0'/0/0" },
//   { chainId: "solana:5eykt4...", address: "7Kz9...", derivationPath: "m/44'/501'/0'/0'" },
//   { chainId: "bip122:000...", address: "bc1q...", derivationPath: "m/84'/0'/0'/0/0" },
//   { chainId: "cosmos:cosmoshub-4", address: "cosmos1...", derivationPath: "m/44'/118'/0'/0/0" },
//   { chainId: "tron:mainnet", address: "TKLm...", derivationPath: "m/44'/195'/0'/0/0" },
//   { chainId: "ton:mainnet", address: "UQ...", derivationPath: "m/44'/607'/0'" },
//   { chainId: "sui:mainnet", address: "0x...", derivationPath: "m/44'/784'/0'/0'/0'" },
//   { chainId: "fil:mainnet", address: "f1...", derivationPath: "m/44'/461'/0'/0/0" },
// ]
Param Type Default Description
name string Wallet name
passphrase string undefined Encryption passphrase
words number 12 Mnemonic word count
vaultPath string ~/.ows Custom vault directory root

Returns: WalletInfo

listWallets(vaultPath?)

List all wallets in the vault.

const wallets = listWallets();
console.log(wallets.length); // => 1

Returns: WalletInfo[]

getWallet(nameOrId, vaultPath?)

Look up a wallet by name or UUID.

const wallet = getWallet("agent-treasury");

Returns: WalletInfo

deleteWallet(nameOrId, vaultPath?)

Delete a wallet from the vault.

deleteWallet("agent-treasury");

renameWallet(nameOrId, newName, vaultPath?)

Rename a wallet.

renameWallet("old-name", "new-name");

exportWallet(nameOrId, passphrase?, vaultPath?)

Export a wallet's secret.

  • Mnemonic wallets return the phrase string.
  • Private key wallets return a JSON string with both curve keys:
// Mnemonic wallet
const phrase = exportWallet("mn-wallet");
// => "goose puzzle decorate much ..."

// Private key wallet
const keysJson = exportWallet("pk-wallet");
const keys = JSON.parse(keysJson);
// => { secp256k1: "4c0883a6...", ed25519: "9d61b19d..." }

Returns: string

Import

importWalletMnemonic(name, mnemonic, passphrase?, index?, vaultPath?)

Import a wallet from a BIP-39 mnemonic. Derives all 8 chain accounts via HD paths.

const wallet = importWalletMnemonic("imported", "goose puzzle decorate ...");

Returns: WalletInfo

importWalletPrivateKey(name, privateKeyHex, passphrase?, vaultPath?, chain?, secp256k1Key?, ed25519Key?)

Import a wallet from a hex-encoded private key. All 8 chains are supported: the provided key is used for its curve's chains, and a random key is generated for the other curve.

The optional chain parameter specifies which chain the key originates from to determine the curve. Defaults to "evm" (secp256k1).

Alternatively, provide explicit keys for each curve via secp256k1Key and ed25519Key. When both are given, privateKeyHex and chain are ignored.

// Import an EVM private key — generates a random Ed25519 key for Solana/Sui/TON
const wallet = importWalletPrivateKey("from-evm", "4c0883a691...");
console.log(wallet.accounts.length); // => 8

// Import a Solana private key — generates a random secp256k1 key for EVM/BTC/etc.
const wallet2 = importWalletPrivateKey(
  "from-solana", "9d61b19d...", undefined, undefined, "solana"
);
console.log(wallet2.accounts.length); // => 8

// Import explicit keys for both curves
const wallet3 = importWalletPrivateKey(
  "both-keys", "", undefined, undefined, undefined,
  "4c0883a691...",  // secp256k1 key
  "9d61b19d..."     // ed25519 key
);
console.log(wallet3.accounts.length); // => 8
Param Type Default Description
name string Wallet name
privateKeyHex string Hex-encoded private key (with or without 0x prefix). Ignored when both curve keys are provided.
passphrase string undefined Encryption passphrase
vaultPath string ~/.ows Custom vault directory root
chain string "evm" Source chain: "evm", "bitcoin", "cosmos", "tron", "filecoin" (secp256k1) or "solana", "sui", "ton" (Ed25519)
secp256k1Key string undefined Explicit secp256k1 private key (hex). Overrides random generation for secp256k1 chains.
ed25519Key string undefined Explicit Ed25519 private key (hex). Overrides random generation for Ed25519 chains.

Returns: WalletInfo

Signing

signMessage(wallet, chain, message, passphrase?, encoding?, index?, vaultPath?)

Sign a message with chain-specific formatting.

const result = signMessage("agent-treasury", "evm", "hello world");
console.log(result.signature);  // hex string
console.log(result.recoveryId); // 0 or 1
Param Type Default Description
wallet string Wallet name or ID
chain string Chain family
message string Message to sign
passphrase string undefined Decryption passphrase
encoding string "utf8" "utf8" or "hex"
index number 0 Account index
vaultPath string ~/.ows Custom vault directory root

Returns: SignResult

signTypedData(wallet, chain, typedDataJson, passphrase?, index?, vaultPath?)

Sign EIP-712 typed structured data (EVM only).

Current implementations support typed-data signing for owner-mode credentials. API-token typed-data signing is not yet supported.

const typedData = JSON.stringify({
  types: {
    EIP712Domain: [
      { name: "name", type: "string" },
      { name: "chainId", type: "uint256" },
    ],
    Transfer: [
      { name: "to", type: "address" },
      { name: "amount", type: "uint256" },
    ],
  },
  primaryType: "Transfer",
  domain: { name: "MyDApp", chainId: "1" },
  message: { to: "0xabc...", amount: "1000" },
});

const result = signTypedData("agent-treasury", "evm", typedData);
console.log(result.signature);  // hex string
console.log(result.recoveryId); // 27 or 28
Param Type Default Description
wallet string Wallet name or ID
chain string Must be an EVM chain
typedDataJson string JSON string of EIP-712 typed data
passphrase string undefined Decryption passphrase
index number 0 Account index
vaultPath string ~/.ows Custom vault directory root

Returns: SignResult

signTransaction(wallet, chain, txHex, passphrase?, index?, vaultPath?)

Sign a raw transaction (hex-encoded bytes).

const result = signTransaction("agent-treasury", "evm", "02f8...");
console.log(result.signature);

Returns: SignResult

signAndSend(wallet, chain, txHex, passphrase?, index?, rpcUrl?, vaultPath?)

Sign and broadcast a transaction. If rpcUrl is omitted, OWS resolves it from explicit config overrides or built-in defaults.

const result = signAndSend(
  "agent-treasury", "evm", "02f8...",
  undefined, undefined, "https://mainnet.infura.io/v3/..."
);
console.log(result.txHash);

Returns: SendResult

Policy Management

createPolicy(policyJson, vaultPath?)

Register a policy from a JSON string.

const policy = JSON.stringify({
  id: "base-only",
  name: "Base only until April",
  version: 1,
  created_at: "2026-03-22T00:00:00Z",
  rules: [
    { type: "allowed_chains", chain_ids: ["eip155:8453"] },
    { type: "expires_at", timestamp: "2026-04-01T00:00:00Z" },
  ],
  action: "deny",
});

createPolicy(policy);
Param Type Default Description
policyJson string JSON string of the policy definition
vaultPath string ~/.ows Custom vault directory root

listPolicies(vaultPath?)

List all registered policies.

const policies = listPolicies();
console.log(policies); // => [{ id: "base-only", name: "Base only until April", ... }]

Returns: object[]

getPolicy(id, vaultPath?)

Get a single policy by ID.

const policy = getPolicy("base-only");
console.log(policy.name); // => "Base only until April"
Param Type Default Description
id string Policy ID
vaultPath string ~/.ows Custom vault directory root

Returns: object

deletePolicy(id, vaultPath?)

Delete a policy by ID.

deletePolicy("base-only");
Param Type Default Description
id string Policy ID
vaultPath string ~/.ows Custom vault directory root

API Key Management

createApiKey(name, walletIds, policyIds, passphrase, expiresAt?, vaultPath?)

Create an API key for agent access to wallets. Returns the raw token (shown once — caller must save it) and key metadata.

const key = createApiKey(
  "claude-agent",
  ["my-wallet"],
  ["base-only"],
  "my-passphrase",
);
console.log(key.token); // => "ows_key_a1b2c3d4..." (save this)
console.log(key.id);
console.log(key.name);
Param Type Default Description
name string Human-readable key name
walletIds string[] Wallet names or IDs this key can access
policyIds string[] Policy IDs to enforce on this key
passphrase string Vault passphrase (needed to re-encrypt wallet secrets for the key)
expiresAt string undefined ISO 8601 expiry timestamp
vaultPath string ~/.ows Custom vault directory root

Returns: ApiKeyResult{ token: string, id: string, name: string }

listApiKeys(vaultPath?)

List all API keys. Tokens are never returned.

const keys = listApiKeys();
keys.forEach((k) => console.log(k.id, k.name));

Returns: object[]

revokeApiKey(id, vaultPath?)

Revoke (delete) an API key by ID.

revokeApiKey("key-id");
Param Type Default Description
id string API key ID
vaultPath string ~/.ows Custom vault directory root

Custom Vault Path

Every function accepts an optional vaultPath parameter. When omitted, the default vault root at ~/.ows/ is used. This is useful for testing or running isolated environments:

import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";

const tmpVault = mkdtempSync(join(tmpdir(), "ows-test-"));

const wallet = createWallet("test-wallet", undefined, 12, tmpVault);
// ... use wallet ...

rmSync(tmpVault, { recursive: true, force: true });