npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@asichain/asi-wallet-sdk

v2.0.0

Published

ASI Wallet SDK

Downloads

197

Readme

ASI Chain: Wallet SDK

Status License Docs npm

Part of the Artificial Superintelligence Alliance ecosystem

Uniting Fetch.ai, SingularityNET, and CUDOS


Table of Contents

  1. Overview
  2. Key Features
  3. Installation
  4. Quick Start
  5. Architecture
  6. Project Structure
  7. Documentation
  8. Security
  9. Development
  10. License

Overview

ASI Chain Wallet SDK is a modular TypeScript library designed to simplify wallet integration and key management for ASI Chain applications. It is organized around a high-level Client facade that manages multi-account HD wallets, secure encrypted storage, multi-network access, and reservation-aware transfers, while keeping secret material behind a strict signing boundary.


Key Features

  • Client Facade - Single entry point for wallet lifecycle, networks, balances, and transfers via Client
  • Multi-Account HD Wallets - Private-key and BIP-39/BIP-44 HD wallets with on-demand account derivation via Wallet and Account
  • Separate Open and Unlocked States - Wallets are loaded into memory independently of the signing session that holds the decrypted secret, via Client and SigningSession
  • Event Subscriptions - Typed, isolated listeners attachable at any time through client.getEventBus() via ClientEventBus
  • Duplicate Protection - Wallets and accounts are matched on non-reversible key fingerprints, so re-importing the same secret is refused even while everything is locked, via KeyFingerprintService
  • Encrypted Wallet Keyfiles - Password-protected export and import of a whole wallet, with a preview that reports which accounts are new before anything is written, via Client
  • Versioned Storage with Migrations - Persisted data carries a schema version; incompatible or interrupted state is refused up front instead of being silently rewritten, via StorageMigrationRunner
  • Secure Key Handling - PBKDF2 + AES-GCM encryption with key zeroization and a no-raw-export signing boundary via CryptoService and Signer
  • Cross-Environment Storage - IndexedDB (browser) and node-persist (Node.js) behind a shared table abstraction via storage layer
  • Pending-Transaction Reservations - Persistent, reservation-aware available balance with deploy-status polling via ReservationAdapter
  • External Reservation Management - Deploys submitted outside the SDK can lock funds too: reservations can be added, updated, and removed directly, with validation and concurrency guards, via Client
  • Detached Deploy Signing - signDeploy builds and signs a deploy and returns the signed envelope for callers that submit it themselves, via Client
  • Explicit Account Targeting - No active-account state: every call names its wallet and account, so concurrent operations on one wallet cannot sign for the wrong account, via Client
  • Typed Failures - Decryption, storage, and node errors carry a machine-readable code and structured fields instead of an assembled message string, via CustomError
  • Multi-Network Access - Runtime network switching over validator, read-only, and GraphQL indexer clients via ApiClientManager
  • Per-Network Node Profiles - Legacy Scala and new Rust f1r3node request contracts behind one interface via NodeApiAdapter
  • Transaction History - Indexed transfer history through a GraphQL anti-corruption layer via AccountDataService

Installation

npm install @asichain/asi-wallet-sdk

Quick Start

Create the Client

The Client is the single entry point. Provide a per-network configuration and (optionally) a default network.

import {
    Client,
    NodeApiProfile,
    type TNetworksConfig,
} from "@asichain/asi-wallet-sdk";

const networksConfig: TNetworksConfig = {
    DevNet: {
        ValidatorURL: "http://validator-node:40403",
        ReadOnlyURL: "http://observer-node:40403",
        IndexerURL: "http://indexer-node:8080",
        nodeApiProfile: NodeApiProfile.SCALA,
    },
    Dev: {
        ValidatorURL: "",
        ReadOnlyURL: "",
        IndexerURL: "",
        nodeApiProfile: NodeApiProfile.RUST,
    },
    MainNet: {
        ValidatorURL: "",
        ReadOnlyURL: "",
        IndexerURL: "",
        nodeApiProfile: NodeApiProfile.SCALA,
    },
    TestNet: {
        ValidatorURL: "",
        ReadOnlyURL: "",
        IndexerURL: "",
        nodeApiProfile: NodeApiProfile.SCALA,
    },
};

const client = await Client.create({
    networksConfig,
    defaultNetwork: "DevNet",
});

Client.create also brings storage up to date. Persisted data carries a schema version, and startup refuses to touch anything it cannot safely handle: data written by a newer SDK build, a malformed migration chain, or a migration that a previous run left unfinished. Those rejections are StorageSchemaErrors carrying an isStorageIntact flag, which tells you whether the data on disk is still readable (update the SDK) or needs restoring from an export.

nodeApiProfile is required on every network. It selects which f1r3node implementation the SDK talks to — SCALA for the legacy node, RUST for the new one — and that choice drives the HTTP request shape, the endpoint a given call targets, and which Rholang vault contract the built-in terms address. There is no default: an omitted or unknown profile throws at Client.create, because guessing it would silently send legacy-shaped requests to a new node. Custom networks added at runtime through client.addNetwork must supply it too.

Create Wallets

import { MnemonicStrength } from "@asichain/asi-wallet-sdk";

// HD (mnemonic) wallet
const mnemonic = client.generateMnemonic(MnemonicStrength.TWELVE_WORDS);
const hdWallet = await client.createHDWallet(
    { mnemonic, accountName: "Account 1" },
    "wallet-password",
);

// Private-key wallet
const privateKey = client.generatePrivateKey();
const pkWallet = await client.createPrivateKeyWallet(
    { privateKey, accountName: "Imported" },
    "wallet-password",
);

// Derive another account on the HD wallet
const { account } = await client.deriveAccount(
    hdWallet.getId(),
    "Account 2",
    "wallet-password",
);
console.log("New address:", account.getAddress());

See Client, Wallet, and Account for the full API reference.

Creating a wallet whose secret is already stored throws DuplicateWalletError, and one whose key already belongs to a stored account throws DuplicateAccountError. Both carry the ids of the existing owner, and both work while every wallet is closed, because the match runs on a key fingerprint rather than on decrypted material.

Open, Unlock, and Close Wallets

A wallet being open (present in memory) and a wallet being unlocked (able to sign without a password) are two different states.

// Load a stored wallet into memory. With the default session policy it comes
// back already unlocked.
const wallet = await client.openWallet(signerId, "wallet-password");

client.isWalletOpen(wallet.getId()); // true
client.isWalletUnlocked(wallet.getId()); // true

// End the signing session, keep the wallet open
client.lockWallet(wallet.getId());

// Start a new session on the wallet that is already open
await client.unlockWallet(wallet.getId(), "wallet-password");

// Drop it from memory; storage is untouched
client.closeWallet(wallet.getId());

// Delete it from storage for good
await client.removeWallet(wallet.getId());

Sessions are fixed-duration: they auto-lock autoLockMs after unlock (15 min by default) and are not extended by activity. Signing after expiry without a password throws WalletLockedError with an HTTP-style status 403, so a UI can treat it like an expired token and re-prompt. See Open vs unlocked.

Export and Import a Wallet Keyfile

A wallet keyfile is the password-protected backup of a whole wallet: its secret plus its account list, both encrypted.

// Export (returns an object; serialize it however you like)
const keyfile = await client.exportWalletKeyfile(wallet.getId(), "wallet-password");

// Import: look before you write
const preview = await client.previewWalletKeyfileImport(keyfile, "wallet-password");

if (preview.existingSignerId) {
    // The secret is already stored - add only the accounts that are new
    const newIndexes = preview.accounts
        .filter((account) => account.status === "new")
        .map((account) => account.index!);

    await client.importKeyfileAccounts(keyfile, "wallet-password", {
        accountIndexes: newIndexes,
    });
} else {
    // Unknown secret - create the wallet
    await client.importWalletKeyfile(keyfile, "wallet-password");
}

previewWalletKeyfileImport writes nothing. It decrypts the keyfile, derives every account it declares, and reports each one as "new" or "already-imported", so a UI can show what an import would actually do and let the user choose. source accepts either the object or its JSON string.

Note that getExportedAccountData is a different thing: a public, passwordless descriptor of one account (name, address, index). It carries no key material and cannot restore anything. See keyfile export & import.

Subscribe to Events

client.getEventBus() returns a typed on / off source. Unlike the constructor-time eventDispatcher, subscriptions can be added and removed at any point in the client's life, and on hands back its own unsubscribe.

import { ClientEvent } from "@asichain/asi-wallet-sdk";

const unsubscribe = client
    .getEventBus()
    .on(ClientEvent.WALLETS_CHANGED, (wallets) => {
        render(wallets);
    });

// later
unsubscribe();

Listeners are isolated: one that throws or rejects never breaks the emit loop or the SDK operation behind it. Route those failures somewhere visible with the onListenerError option on Client.create.

Check Balance and Transfer

// The SDK keeps no active account: every call names its target account
const [account] = hdWallet.getAccounts();

// Total and reservation-aware available balance
const balance = await client.getBalance(account.getAddress());
const available = await client.getAvailableBalance(
    hdWallet.getId(),
    account.getId(),
);
console.log("Balance:", client.toDisplayAmount(balance));

// Transfer tokens (amount in atomic units)
const reserved = await client.transfer(
    {
        walletId: hdWallet.getId(),
        accountId: account.getId(),
        to: recipientAddress,
        amount: client.toAtomicAmount("10"), // 10 ASI
    },
    "wallet-password",
);
console.log("Deploy id:", reserved.deployId);

// Follow the deploy until the node confirms it
const unsubscribe = reserved.subscribe({
    onStatus: (status) => console.log("Status:", status.status),
    onConfirmed: () => console.log("Confirmed"),
});

A balance read that cannot be trusted now throws BalanceUnavailableError (status 502) carrying the address and a reason, instead of resolving to 0n. A node that is unreachable, a vault that reports an error, and an account with no funds are three different outcomes, so handle the error rather than reading a falsy balance as "empty".

See Client for the full API reference. For amount conversions, see functions utilities.

Reserve Funds for a Deploy You Submit Yourself

transfer and deploy reserve funds on their own. When the deploy is submitted outside the SDK — a hardware signer, a relayer, another app on the same vault — the reservation can be created directly so the available balance and the pending history stay correct.

const request = {
    walletId: hdWallet.getId(),
    accountId: account.getId(),
    kind: "transfer" as const,
    deployId, // the deploy you submitted yourself
    to: recipientAddress,
    amount: client.toAtomicAmount("10"),
    gasCost: client.toAtomicAmount("0.1"),
    pendingAmount: client.toAtomicAmount("10.1"), // must cover amount + gasCost
};

const reservation = await client.addTransactionReservation(
    request,
    "wallet-password",
);

// Correct it while it is still pending, keeping the same reservation id
await client.updateTransactionReservation(reservation.id, {
    ...request,
    amount: client.toAtomicAmount("12"),
    pendingAmount: client.toAtomicAmount("12.1"),
});

// Or release the funds early
await client.removeTransactionReservation(hdWallet.getId(), reservation.id);

pendingAmount is the total to lock and must cover amount + gasCost; a reservation that does not is rejected rather than under-locking the balance. The whole available balance may be reserved. A reservation still expires on its own after RESERVATION_EXPIRATION_TIME and is released when the deploy is confirmed, so these calls are a correction channel, not a lifecycle to manage by hand.

Concurrent actions on the same account, deploy, or reservation are refused with ReservationActionInProgressError (status 409) rather than interleaved. See External reservations.

Sign a Deploy Without Submitting It

When the submission is yours but the signature is not, signDeploy stops after signing and hands back the signed envelope. Nothing is sent to the node and no reservation is created, so pair it with addTransactionReservation to lock the funds locally.

const signed = await client.signDeploy(
    {
        walletId: hdWallet.getId(),
        accountId: account.getId(),
        term: rholangTerm,
        phloLimit: 500_000, // optional, defaults from config
        phloPrice: 1, // optional, defaults from config
        shardId: "root", // optional, defaults to "root"
    },
    "wallet-password", // omit while a signing session is active
);

// { data, deployer, signature, sigAlgorithm } - submit it yourself
await submitToNode(signed);

validAfterBlockNumber and timestamp are filled in by the SDK from the current chain head, so the call still needs the network. The payload is validated before anything is signed: a blank term, a non-positive or unsafe phloLimit / phloPrice, or a blank shardId are rejected.


Architecture

SDK Components

┌──────────────────────────────────────────────────────────────────┐
│                        Application                               │
└──────────────────────────────────────────────────────────────────┘
                               │
                               ▼
┌─────────────────────────────────────────────────────────────────────┐
│                     ASI Wallet SDK                                  │
│                                                                     │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │                    Client (facade)                            │  │
│  │  Wallet & account lifecycle • networks • balances • transfers │  │
│  └───────────────────────────────────────────────────────────────┘  │
│                                                                     │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │                      Domains                                  │  │
│  │  • Wallet / Account    - Multi-account HD & PK wallets        │  │
│  │  • Signer (HD / PK)    - No-raw-export signing boundary       │  │
│  │  • SigningSession      - Fixed-window in-memory secret        │  │
│  │  • LifecycleGuard      - Invalidate + drain in-flight work    │  │
│  │  • Asset               - Token representation                 │  │
│  │  • ReservationAdapter  - Pending-transaction reservations     │  │
│  │  • ApiClientManager    - Per-network transport clients        │  │
│  │  • ApiServiceRegistry  - Service composition root             │  │
│  │  • Storage repositories- Signers / Accounts / Reservations    │  │
│  └───────────────────────────────────────────────────────────────┘  │
│                                                                     │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │                  Services / Managers                          │  │
│  │  • WalletManager / AccountManager - In-memory ownership       │  │
│  │  • StorageManager      - Persistence orchestration            │  │
│  │  • ClientEventBus      - Typed client event subscriptions     │  │
│  │  • WalletOperationGuard- Duplicate & concurrency guards       │  │
│  │  • ReservationOperationGuard - Per-network reservation locks  │  │
│  │  • StorageBootstrap / StorageMigrationRunner (schema)         │  │
│  │  • ExportKeyfileService / ImportKeyfileService                │  │
│  │  • DeployService / BlockService / AccountDataService          │  │
│  │  • AssetsService / TransactionService / DeployStatusPoller    │  │
│  │  • CryptoService / KeysManager / KeyDerivation / Mnemonic     │  │
│  │  • KeyFingerprintService - Non-reversible key identity        │  │
│  └───────────────────────────────────────────────────────────────┘  │
│                                                                     │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │                    Storage backends                           │  │
│  │  • BrowserStorage (IndexedDB) • NodeStorage (node-persist)    │  │
│  │    selected automatically by environment                      │  │
│  └───────────────────────────────────────────────────────────────┘  │
│                                                                     │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │                    Utils / Config                             │  │
│  │  • codec / constants / validators / functions / polyfills     │  │
│  │  • decorators / guards / fabrics                              │  │
│  └───────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────┘
                               │
                               ▼
┌─────────────────────────────────────────────────────────────────────┐
│                    ASI Chain Network                                │
│                                                                     │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐               │
│  │  Validator   │  │  Observer    │  │  Indexer     │               │
│  │    Node      │  │    Node      │  │  (GraphQL)   │               │
│  │  (Deploys)   │  │  (Queries)   │  │  (History)   │               │
│  └──────────────┘  └──────────────┘  └──────────────┘               │
└─────────────────────────────────────────────────────────────────────┘

Cryptographic Flow


Project Structure

asi-chain-wallet-sdk/
├── src/                        # SDK source code
│   ├── config/                # Runtime defaults and constants
│   ├── domains/               # Domain models & transport (→ docs/DOMAINS.md)
│   ├── services/              # Managers & business logic (→ docs/SERVICES.md)
│   ├── fabrics/               # Factories: signer, storage, client, reservations (→ docs/UTILS.md)
│   ├── utils/                 # Utilities & guards (→ docs/UTILS.md)
│   └── index.ts              # Main export
│
├── playground/                # React demo app (→ docs/PLAYGROUND.md)
│   ├── src/
│   │   ├── sdk-react-kit/    # SDK ↔ React integration layer (hooks, context)
│   │   ├── components/       # UI components
│   │   ├── pages/            # WalletsPage, TxHistoryPage
│   │   └── router/           # Client-side routing
│   └── package.json
│
├── docs/                      # API reference
│   ├── DOMAINS.md            # Domain models & transport
│   ├── SERVICES.md           # Managers & services
│   ├── UTILS.md              # Utilities & config
│   └── PLAYGROUND.md         # Playground components
│
├── package.json              # SDK dependencies
├── tsconfig.build.json       # TypeScript config
└── README.md                 # This file

Documentation

SDK Reference

| Document | Description | | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | docs/DOMAINS.md | Domain models & transport (Client, Wallet, Account, Signer, ReservationAdapter, ApiClientManager, NodeApiAdapter, storage repositories, and types) | | docs/SERVICES.md | Managers & services (WalletManager, AccountManager, StorageManager, DeployService, AssetsService, TransactionService, CryptoService) | | docs/UTILS.md | Utilities & config (codec, constants, validators, functions, guards, decorators, fabrics, polyfills) | | docs/PLAYGROUND.md | Playground components, the sdk-react-kit integration layer, and usage examples |

Related Resources

| Resource | Link | | ----------------------- | ------------------------------------------------------------------------------------------------ | | ASI Chain Documentation | https://docs.asichain.io | | ASI Chain Node | github.com/asi-alliance/asi-chain | | ASI Chain Wallet | github.com/asi-alliance/asi-chain-wallet | | ASI Chain Explorer | github.com/asi-alliance/asi-chain-explorer | | ASI Chain Faucet | github.com/asi-alliance/asi-chain-faucet |


Security

| Document | Description | | ------------------------------------------------ | -------------------------------------------------------------------------- | | SECURITY.md | Vulnerability reporting policy, disclosure process, and supported versions | | THREAT_MODEL.md | Threat assumptions, trust boundaries, adversary model, and mitigations | | SECURITY_INVARIANTS.md | Non-negotiable key/storage/signing/documentation security guarantees | | CRYPTO_PROFILE.md | Versioned crypto parameters, key-handling profile, and migration notes |


Development

Prerequisites

  • Node.js 18.x or higher
  • npm 9.x or higher

Setup

# Install SDK dependencies
npm install

# Build the SDK
npm run build

# Watch mode for development
npm run dev

# Run the release gate locally: build, unit tests, security tests,
# secret-log scan, and a production-dependency audit
npm run gate

The gate was npm run security:gate and covered security checks only; it now also runs npm run test:unit, so the same command CI runs is the one that has to pass locally. The GitHub workflow is .github/workflows/gate.yml.

Playground

The playground provides a React-based demo application for testing SDK functionality:

cd playground
npm install

# Create .env file with per-network endpoints, e.g.:
# VITE_DEFAULT_NETWORK=DevNet
# VITE_DEVNET_VALIDATOR_URL=...
# VITE_DEVNET_READONLY_URL=...
# VITE_DEVNET_INDEXER_URL=...

npm run dev

Playground available at http://localhost:5173. See docs/PLAYGROUND.md for component details.

Dependencies

SDK (package.json):

| Package | Version | Purpose | | ---------------------------------------------------------------- | ------- | ----------------------------------------- | | axios | 1.13.2 | HTTP client for node communication | | bip32 | 4.0.0 | BIP-32 hierarchical deterministic wallets | | bip39 | 3.1.0 | BIP-39 mnemonic generation | | blakejs | 1.2.1 | BLAKE2b hashing for addresses | | bs58 | 6.0.0 | Base58 encoding | | @noble/hashes | 1.6.0 | Cryptographic hash helpers | | @noble/secp256k1 | 1.7.0 | secp256k1 key generation and signing | | js-sha3 | 0.9.3 | keccak256 hashing | | node-persist | 4.0.4 | Node.js storage backend | | buffer | 6.0.3 | Browser Buffer compatibility |

Playground (playground/package.json):

| Package | Version | Purpose | | -------------------------- | ------- | ------------------------- | | react | 18.2.0 | UI framework | | vite | 7.2.6 | Build tool and dev server |


License

This project is licensed under the Apache 2.0 License. See LICENSE file for details.


ASI Alliance founding members: Fetch.ai, SingularityNET, and CUDOS