Nami Wallet Documentation

repository·main·Indexed 18 days ago

https://github.com/input-output-hk/nami

An open-source, browser-based wallet extension for the Cardano blockchain maintained by IOG. It provides a CIP-0030 compliant injected API via window.cardano.nami for web applications to interact with Cardano accounts, sign transactions, and manage assets. The documentation covers API integration, development environment setup using Node.js 20 and Blockfrost, and internal extension functions for account management, key encryption, and asset metadata retrieval.

Tokens
14K
Snippets
66
Records
74
Agent score
13%

What's inside Nami

  1. Use the Nami Injected API (CIP-0030)

    main

    Nami exposes a Cardano provider via window.cardano following the CIP-0030 standard. The API is accessed through the nami namespace. Returned data types are in cbor/bytes format and should be deserialized using a library like cardano-serialization-lib.

    Basic Integration Flow

    1. Detect the provider: Check for window.cardano.
    2. Detect Nami: Check for window.cardano.nami.
    3. Enable the API: Call window.cardano.nami.enable() to request access and receive the api object.
    4. Identify Network: Check the network ID (1 = Mainnet, 0 = Testnet).
    5. Access Account: Use the API to retrieve the user's Cardano account.
    // Basic usage pattern
    if (window.cardano && window.cardano.nami) {
      const api = await window.cardano.nami.enable();
      const networkId = await api.getNetworkId(); // 1 for Mainnet, 0 for Testnet
      const account = await api.getUsedAddresses();
    }
  2. Setup Nami development environment

    main

    To develop Nami locally, ensure you have Node.js 20 installed. You must configure your own Blockfrost project IDs to interact with the blockchain.

    1. Configure Secrets

    Do not commit your keys to the repository. Copy the testing secrets template to your development or production file:

    cp secrets.testing.js secrets.development.js

    Then, edit ./src/config/provider.js and replace the following keys with your Blockfrost project IDs:

    • secrets.PROJECT_ID_MAINNET
    • secrets.PROJECT_ID_TESTNET
    • secrets.PROJECT_ID_PREVIEW
    • secrets.PROJECT_ID_PREPROD

    2. Run Commands

    Start development server:

    npm start

    Create production build:

    npm run build

    Run tests:

    npm test
    # Update secrets file with your own keys
    cp secrets.testing.js secrets.development.js
    npm start
  3. Install Nami for Testnet development

    main

    To use Nami for testing purposes, you can install it as an unpacked extension in Chrome:

    1. Download and extract the zip file from the latest Nami Release.
    2. Open Chrome and navigate to chrome://extensions.
    3. Enable Developer mode (usually a toggle in the top right).
    4. Click Load unpacked at the top left.
    5. Select the extracted build folder.
  4. Handle Protected and Unprotected Headers

    main

    COSE messages distinguish between protected and unprotected headers using the Headers structure.

    • ProtectedHeaderMap: Contains headers that are part of the signed data and must be protected.
    • HeaderMap: Contains unprotected headers.
    • Headers: A container holding both a ProtectedHeaderMap and an unprotected HeaderMap.

    Use Headers.protected() to access the protected map and Headers.unprotected() to access the unprotected map.

  5. Construct COSE Signatures and Messages

    main

    The library provides several structures for representing signed data:

    • COSESignature: A single signature with associated Headers.
    • COSESignatures: A collection of COSESignature objects.
    • CounterSignature: A wrapper for COSESignatures used in counter-signatures.
    • COSESign1: A signature format that includes an optional payload.
    • COSESign: A signature format that includes a payload and multiple signatures.
    • SignedMessage: A top-level wrapper that can hold either a COSESign or a COSESign1 message.
  6. Deprecated Injected API Reference

    main

    The following API is deprecated and follows a different proposed CIP. Use the standard CIP-0030 Injected API for new projects. All methods in this section return Promise objects.

    ##### cardano.enable()
    Will ask the user to give access to requested website. Returns `true` if access is given, otherwise throws an `error`.
    
    ##### cardano.isEnabled()
    `cardano.isEnabled() : boolean`
    
    ##### cardano.getBalance()
    `cardano.getBalance() : Value` (hex encoded cbor string).
    
    ##### cardano.getUtxos(amount, paginate)
    `cardano.getUtxos(amount?: Value, paginate?: {page: number, limit: number}) : [TransactionUnspentOutput]`
    
    ##### cardano.getCollateral()
    `cardano.getCollateral() : [TransactionUnspentOutput]`
    
    ##### cardano.getUsedAddresses()
    `cardano.getUsedAddresses() : [BaseAddress]` (Returns an array of length 1).
    
    ##### cardano.getUnusedAddresses()
    `cardano.getUnusedAddresses() : [BaseAddress]` (Returns an empty array `[]`).
    
    ##### cardano.getChangeAddress()
    `cardano.getChangeAddress() : BaseAddress` (Returns the same address as `getUsedAddresses`).
    
    ##### cardano.getRewardAddress()
    `cardano.getRewardAddress() : [RewardAddress]` (Returns an array of length 1).
    
    ##### cardano.getNetworkId()
    `cardano.getNetworkId() : number` (0 for testnet, 1 for mainnet).
    
    ##### cardano.signData(address, payload)
    `cardano.signData(address: BaseAddress|RewardAddress, payload: string) : CoseSign1`
    - `payload`: hex encoded utf8 string.
    - `CoseSign1`: hex encoded bytes string.
    
    ##### cardano.signTx(tx, partialSign)
    `cardano.signTx(tx: Transaction, partialSign?: boolean) : TransactionWitnessSet`
    - `partialSign`: boolean (default `false`).
    
    ##### cardano.submitTx(tx)
    `cardano.submitTx(tx : Transaction) : hash32`
  7. Reference the Nami experimental API endpoints

    main

    Nami provides several experimental endpoints available under the api.experimental namespace to extend standard CIP-0030 functionality.

    ##### api.experimental.getCollateral()

    cardano.getCollateral() : [TransactionUnspentOutput]

    
    ##### api.experimental.on(eventName, callback)
    Register events coming from Nami. Available events are:
    - `accountChange`: `((addresses : [BaseAddress]) => void)`
    - `networkChange`: `((network : number) => void)`
    
    ##### api.experimental.off(eventName, callback)
    Deregister the events (works also with anonymous functions).
  8. Troubleshoot Cardano message signing deserialization errors

    main

    When using the cardano-message-signing WASM module, deserialization failures are wrapped in a DeserializeError. These errors typically occur when the input CBOR data does not match the expected schema.

    Common failure reasons include:

    • MandatoryFieldMissing(Key): A required field was not found in the input.
    • DuplicateKey(Key): The same key appeared more than once.
    • UnknownKey(Key): An unexpected key was encountered.
    • FixedValueMismatch: The value found did not match the expected fixed value.
    • TagMismatch: The CBOR tag did not match the expected value.
    • DefiniteLenMismatch: The number of elements in a sequence did not match the declared length.
    • UnexpectedKeyType: The type of the value provided does not match the expected CBOR type.

    In WASM environments, these errors are converted to JsError (a wasm_bindgen::prelude::JsValue) to be thrown as JavaScript exceptions.

  9. Initialize Blaze provider with getBlazeProvider

    main

    Obtain a Blaze provider instance, which integrates Blockfrost and a WebWallet for interacting with the Cardano blockchain.

    Returns: A Blaze instance configured for the current Nami network.

    const blaze = await getBlazeProvider();
    // Use blaze to interact with the blockchain
  10. Retrieve account balances and UTXOs

    main

    The API provides several ways to fetch balance information and Unspent Transaction Outputs (UTXOs) via Blockfrost.

    // Get the current account's balance as a Cardano Value object
    const balance = await getBalance();
    
    // Get extended balance information
    const extendedBalance = await getBalanceExtended();
    
    // Get all UTXOs for the current account
    const utxos = await getUtxos();
    
    // Get UTXOs with pagination and a minimum amount filter
    const filteredUtxos = await getUtxos('HEX_CBOR_AMOUNT', { page: 0, limit: 20 });
  11. Fetch transaction and block information

    main

    Query the blockchain for transaction details, metadata, UTXOs associated with a transaction, or specific blocks.

    // Get a list of recent transactions
    const txs = await getTransactions(1, 10);
    
    // Get detailed info for a specific transaction hash
    const txInfo = await getTxInfo('TX_HASH');
    
    // Get UTXOs for a specific transaction
    const utxos = await getTxUTxOs('TX_HASH');
    
    // Get metadata for a transaction
    const metadata = await getTxMetadata('TX_HASH');
    
    // Get a block by hash or number
    const block = await getBlock('BLOCK_HASH_OR_NUMBER');