# Blockchain basics for developers

This page explains blockchain concepts you will encounter when integrating with the Vilna API. It is not a general blockchain tutorial - it covers only what you need to know to use Vilna effectively. If you already know how addresses, keys, and derivation paths work, skip ahead to [Core Concepts](/guides/core-concepts).

## Addresses - your starting point

An address is like a bank account number. It is the identifier where cryptocurrency is received. Every blockchain has its own address format, and the format tells you which network the address belongs to.

**EVM chains** (Ethereum, Polygon, BSC, Arbitrum, Optimism, Base, Avalanche) all share one format: a `0x` prefix followed by 40 hexadecimal characters, for a total of 42 characters. The same address works across every EVM chain - if you have an Ethereum address, you can receive tokens on Polygon or Arbitrum with that same address. This is one of the key advantages of the EVM ecosystem.

**Bitcoin** has several address formats depending on the era and technology:

| Format | Starts with | Example |
|  --- | --- | --- |
| Legacy (P2PKH) | `1` | `1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa` |
| Compatibility (P2SH) | `3` | `3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy` |
| Native SegWit (P2WPKH) | `bc1q` | `bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq` |
| Taproot (P2TR) | `bc1p` | `bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg3s7p` |


**TRON** addresses start with `T` and are 34 characters long.

**Solana** addresses are base58-encoded strings, typically around 44 characters.

When you add an address to Vilna, you specify a `chainFamily` (`evm`, `bitcoin`, `solana`, or `tron`) and the address format is auto-detected from the address value. The supported address formats are `evm`, `p2pkh`, `p2sh`, `p2wpkh`, `p2wsh`, `p2tr`, `solana`, and `tron`.

## Private keys and public keys

Think of a private key as the password to a bank account. Anyone who has it can spend the funds. A public key is derived from the private key using one-way mathematics - you can go from private to public, but never the reverse.

An address is then derived from the public key. The full chain looks like this:


```mermaid
flowchart LR
    PK["Private Key<br/>(secret)"] --> PUB["Public Key<br/>(safe to share)"]
    PUB --> ADDR["Address<br/>(safe to share)"]
```

The private key is the only piece that must remain secret. The public key and address can be shared freely.

**Vilna never needs your private key.** To monitor addresses and track balances, Vilna only requires the public key or the address itself. When you import a public key into Vilna, you are giving it the ability to generate and watch addresses - not the ability to move funds.

For transaction signing, the Vilna Widget stores the private key locally inside your browser extension. The key never leaves your device and is never sent to Vilna servers.

## HD wallets (Hierarchical Deterministic)

Managing hundreds or thousands of individual private keys is impractical. HD wallets solve this by generating a tree of keys from a single master seed.

Here is the idea: you start with one secret (a seed phrase, typically 12 or 24 words). From that seed, the wallet can deterministically generate an unlimited number of key pairs. "Deterministic" means the same seed always produces the same keys in the same order.

![HD Wallet Tree - address derivation from master seed](https://cdn.vilna.io/docs/hd-wallet-tree.svg)

The practical benefit is significant. Instead of backing up thousands of keys, you back up one seed phrase. Instead of importing addresses one at a time, you import a single extended public key and generate addresses on demand.

This is exactly how exchanges and payment processors work. They generate a unique deposit address for each customer, all derived from one master key.

## Extended public keys (xPub, yPub, zPub)

An extended public key is a special form of public key that can generate child addresses. There are three variants, each tied to a different address format:

| Key prefix | Standard | Address type |
|  --- | --- | --- |
| `xPub` | BIP-44 | Legacy addresses (starts with `1`) |
| `yPub` | BIP-49 | SegWit-compatible addresses (starts with `3`) |
| `zPub` | BIP-84 | Native SegWit addresses (starts with `bc1q`) |


For Bitcoin Taproot (BIP-86), there is no widely adopted single-letter pub prefix. Use an xPub with derivation path `m/86'/0'/0'` to generate Taproot addresses.

For EVM chains (Ethereum, Polygon, etc.), you use an xPub with BIP-44 derivation.

These keys are safe to share with Vilna. An extended public key can only generate addresses and monitor balances. It cannot sign transactions or move funds.

When you import an xPub into Vilna with [`POST /public_keys`](/apis/platform/api/public_key/create-public-key), you can then call [`POST /public_keys/{public_key_id}/addresses/next`](/apis/platform/api/public_key/generate-next-public-key-address) to generate the next address in the sequence. Each new address is automatically registered for monitoring.

## Derivation paths

A derivation path is an instruction that tells the wallet which branch of the key tree to follow when generating addresses. Think of it as a folder path in a file system - it describes exactly where in the tree a particular key lives.

The format looks like this:


```mermaid
flowchart LR
    M["m<br/>Root"] --> P["purpose'<br/>44, 49, 84, 86"]
    P --> C["coin_type'<br/>0=BTC, 60=ETH"]
    C --> A["account'<br/>0, 1, 2..."]
    A --> CH["change<br/>0=external"]
    CH --> I["index<br/>0, 1, 2..."]
```

- `m` is the root (master key)
- `purpose` identifies the standard (44, 49, 84, or 86)
- `coin_type` identifies the blockchain (a number from the SLIP-44 registry)
- `account` allows multiple accounts under one wallet (usually `0`)
- The `'` (apostrophe) after a number means "hardened" - a security feature that prevents child keys from being used to reverse-engineer the parent


Here are the common paths you will encounter:

| Path | Blockchain | Standard |
|  --- | --- | --- |
| `m/44'/60'/0'` | Ethereum and all EVM chains | BIP-44 |
| `m/44'/0'/0'` | Bitcoin Legacy | BIP-44 |
| `m/49'/0'/0'` | Bitcoin SegWit-compatible | BIP-49 |
| `m/84'/0'/0'` | Bitcoin Native SegWit | BIP-84 |
| `m/86'/0'/0'` | Bitcoin Taproot | BIP-86 |
| `m/44'/195'/0'` | TRON | BIP-44 |
| `m/44'/501'/0'` | Solana | BIP-44 |


The `coin_type` numbers come from the SLIP-44 standard: 60 for Ethereum, 0 for Bitcoin, 195 for TRON, 501 for Solana.

**Quick decision guide:** If you are working with EVM chains, use `m/44'/60'/0'`. For Bitcoin, use `m/86'/0'/0'` (Taproot) for the latest standard with the lowest fees, or `m/84'/0'/0'` (Native SegWit) for broader compatibility.

## How to get your xPub

### From hardware wallets

**Ledger Live:** Open an account, go to Advanced settings, and look for "Extended Public Key."

**Trezor Suite:** Open an account and select "Show xPub."

**MetaMask:** MetaMask is an account-based wallet and does not support exporting an xPub. You can import individual addresses from MetaMask into Vilna as external addresses instead.

### Programmatically (Node.js)

If you are generating wallets in code, you can derive the xPub like this:


```typescript
import { generateMnemonic, mnemonicToSeedSync } from "bip39";
import BIP32Factory from "bip32";
import * as ecc from "tiny-secp256k1";

const bip32 = BIP32Factory(ecc);

// Generate a new wallet (store the mnemonic securely)
const mnemonic = generateMnemonic();
const seed = mnemonicToSeedSync(mnemonic);
const root = bip32.fromSeed(seed);

// Derive the xPub for Ethereum (BIP-44, coin type 60)
const account = root.derivePath("m/44'/60'/0'");
const xpub = account.neutered().toBase58();
// xpub looks like: xpub6CUGRUonZSQ4TWtTMm...

// Import this xPub into Vilna to generate addresses
```

Store the mnemonic (seed phrase) securely and never expose it in code, logs, or version control. Vilna only needs the xPub.

## Chain families in Vilna

Vilna groups blockchains into families that share similar characteristics.

**EVM chains** - Ethereum, BSC, Polygon, Arbitrum, Optimism, Base, Avalanche, and others. All use the same address format and transaction model. One EVM address works across all of them.

**Bitcoin-like chains** - Bitcoin, Litecoin, Dogecoin. These use the UTXO (Unspent Transaction Output) model and support multiple address formats. Each format has its own trade-offs in terms of fees and compatibility.

**Solana** - A unique address format and a different transaction model based on accounts rather than UTXOs.

**TRON** - Similar to EVM internally but operates as a separate network with its own address format starting with `T`.

Vilna identifies each chain using CAIP-2 identifiers:

| Identifier | Chain |
|  --- | --- |
| `eip155:1` | Ethereum |
| `eip155:56` | BNB Smart Chain |
| `eip155:137` | Polygon |
| `eip155:42161` | Arbitrum One |
| `bip122:000000000019d6689c085ae165831e93` | Bitcoin |
| `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | Solana |


See [Core Concepts](/guides/core-concepts#blockchains-and-chain-ids-caip-2) for the full list of supported chains.

## Tokens and native currencies

Every blockchain has a native currency - the currency used to pay transaction fees and that exists without any smart contract. ETH on Ethereum, BTC on Bitcoin, SOL on Solana, TRX on TRON.

Tokens are additional currencies built on top of a blockchain using smart contracts. USDT, USDC, DAI, and thousands of others are all tokens. They piggyback on the underlying blockchain's infrastructure.

On EVM chains, tokens follow standardized interfaces:

- **ERC-20** - fungible tokens (every unit is identical, like dollars)
- **ERC-721** - non-fungible tokens (each one is unique, like serial-numbered items)


TRON has an equivalent standard called TRC-20.

Vilna identifies every asset - whether native or token - with a CAIP-19 identifier:


```
eip155:1/slip44:60                                              - ETH on Ethereum
eip155:1/erc20:0xdAC17F958D2ee523a2206206994597C13D831ec7       - USDT on Ethereum
eip155:56/erc20:0x55d398326f99059fF775485246999027B3197955       - USDT on BSC
```

Amounts in the API are always returned in two formats:


```json
{
  "base": "1500000000000000000",
  "formatted": "1.5"
}
```

The `base` value is the raw amount in the token's smallest unit (like cents to dollars, but often with 18 decimal places). The `formatted` value is what a human would read. Use `base` for calculations and storage; use `formatted` for display.

## Confirmations

When someone sends a transaction, it does not become final immediately. Here is what happens:

1. The transaction is broadcast to the network and sits in a waiting area called the **mempool**. At this point it is "pending."
2. A miner or validator includes the transaction in a **block**. This is the first confirmation.
3. Each new block added to the chain after that block is an additional confirmation.


More confirmations mean more certainty that the transaction will not be reversed. Different blockchains require different confirmation counts before a transaction is considered safe:

| Chain | Typical confirmations needed |
|  --- | --- |
| Bitcoin | ~6 |
| Ethereum | ~12 |
| BSC | ~15 |
| Polygon | ~128 |


Vilna tracks confirmation progress automatically. When you set up webhook notifications, Vilna will notify you when a transaction reaches the required confirmation threshold for its chain.

## What's next

Quickstart
Make your first API call and monitor an address

Core Concepts
Vilna-specific terminology and API patterns

Integration Patterns
Deposit detection, HD wallet management, and more

Platform API
Full endpoint documentation