# IoTeX Node.js SDK - Complete API Reference

This is the exhaustive API reference for the IoTeX Node.js SDK, documenting every module, method, type, and utility function.

## Table of Contents

1. [Core SDK](#core-sdk)
2. [Account Module](#account-module)
3. [Blockchain Module](#blockchain-module)
4. [Node Delegate Module](#node-delegate-module)
5. [Keystore Management](#keystore-management)
6. [HD Wallet](#hd-wallet)
7. [Cryptographic Functions](#cryptographic-functions)
8. [Validation Utilities](#validation-utilities)
9. [Conversion Utilities](#conversion-utilities)
10. [Error Handling](#error-handling)
11. [Configuration](#configuration)
12. [All Type Definitions](#type-definitions)

---

## Core SDK

The main `IoTeXSDK` class is the entry point to all functionality.

### Creating SDK Instances

#### Mainnet
```typescript
const sdk = IoTeXSDK.mainnet();
```

#### Testnet
```typescript
const sdk = IoTeXSDK.testnet();
```

#### Localhost (Development)
```typescript
const sdk = IoTeXSDK.localhost();
```

#### Custom Endpoint
```typescript
const sdk = new IoTeXSDK({
  endpoint: 'your-node:443',
  secure: true,
  timeout: 30000,
  jwtToken: 'optional-jwt-token'
});
```

### Connection Lifecycle

```typescript
// Connect to blockchain
await sdk.connect();

// Check connection status
const isConnected = await sdk.isConnected();

// Get underlying gRPC client (advanced use)
const client = sdk.getClient();

// Disconnect when done
sdk.disconnect();
```

### Module Access

```typescript
// Account queries and management
sdk.account

// Blockchain queries
sdk.blockchain

// Node and delegate queries
sdk.node

// Staking operations (stub - not implemented)
sdk.stake
```

---

## Account Module

The Account module handles account queries, address conversion, and account management (keystore & HD wallet).

### Query Methods

#### Get Account Balance
```typescript
const balance = await sdk.account.getBalance('io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v');
// Returns: "123.456" (string in IOTX)
```

#### Get Full Account Metadata
```typescript
const meta = await sdk.account.getMeta('io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v');
// Returns AccountMeta:
// {
//   balance: "123.456",
//   nonce: 42n,
//   pendingNonce: 43n,
//   numActions: 100n,
//   isContract: false
// }
```

#### Get Pending Nonce
```typescript
const nonce = await sdk.account.getNonce('io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v');
// Returns: 43n (bigint)
```

### Address Conversion

#### Convert IoTeX to Ethereum Format
```typescript
const ethAddr = sdk.account.toEthAddress('io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw');
// Returns: "0xb8744ae4032be5e5ef9fab94ee9c3bf38d5d2ae0"
```

#### Convert Ethereum to IoTeX Format
```typescript
const ioAddr = sdk.account.toIoAddress('0xb8744ae4032be5e5ef9fab94ee9c3bf38d5d2ae0');
// Returns: "io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw"
```

### Keystore Account Management

#### Create New Account
```typescript
const { address, privateKey } = await sdk.account.create('secure-password');
// Creates encrypted keystore file in ~/.iotex-node-sdk/keystore/
// Returns: {
//   address: "io1...",
//   privateKey: "private-key-for-backup"
// }
```

#### Import Private Key to Keystore
```typescript
const address = await sdk.account.importKey(
  'your-private-key-hex',
  'secure-password'
);
// Returns: imported address
```

#### Export Private Key from Keystore
```typescript
const privateKey = await sdk.account.exportKey(
  'io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v',
  'password-for-decryption'
);
// Returns: hex-encoded private key (use with caution!)
```

#### List All Keystore Accounts
```typescript
const accounts = sdk.account.list();
// Returns: [
//   { address: "io1...", publicKey: "0x..." },
//   { address: "io1...", publicKey: "0x..." }
// ]
```

#### Check if Account Exists
```typescript
const exists = sdk.account.exists('io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v');
// Returns: true | false
```

#### Delete Account from Keystore
```typescript
await sdk.account.delete('io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v');
// Deletes keystore file permanently
```

#### Update Account Password
```typescript
await sdk.account.updatePassword(
  'io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v',
  'old-password',
  'new-password'
);
```

#### Sign Message with Keystore Account
```typescript
const signature = await sdk.account.sign(
  'io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v',
  'password',
  'message-to-sign'
);
// Returns: signature hex string (Ethereum-style with prefix)
```

### HD Wallet Operations

#### Create HD Wallet
```typescript
const mnemonic = await sdk.account.createHDWallet('secure-password', 'english');
// Returns: "word1 word2 word3 ... word12"
// Stores encrypted in ~/.iotex-node-sdk/hdwallet/
```

#### Import Existing Mnemonic
```typescript
await sdk.account.importHDWallet(
  'word1 word2 word3 ... word12',
  'secure-password'
);
// Imports 12-word BIP39 mnemonic
```

#### Derive Account from HD Wallet
```typescript
const account = await sdk.account.deriveHDAccount(
  'password',
  0,  // account index (default: 0)
  0,  // change (0=external, 1=internal, default: 0)
  0   // address index (default: 0)
);
// Returns: HDWalletAccount {
//   address: "io1...",
//   publicKey: "0x...",
//   privateKey: "0x..." (for this session only)
// }
```

#### Export HD Wallet Mnemonic
```typescript
const mnemonic = await sdk.account.exportHDWalletMnemonic('password');
// Returns: "word1 word2 word3 ... word12"
```

#### Check HD Wallet Existence
```typescript
const exists = sdk.account.hdWalletExists();
// Returns: true | false
```

#### Delete HD Wallet
```typescript
sdk.account.deleteHDWallet();
// Deletes HD wallet config permanently
```

#### Update HD Wallet Password
```typescript
await sdk.account.updateHDWalletPassword('old-password', 'new-password');
```

#### Get Keystore Directory
```typescript
const dir = sdk.account.getKeystoreDir();
// Returns: "/Users/username/.iotex-node-sdk/keystore/"
```

### Static Account Methods

#### Generate Random Account
```typescript
const { address, privateKey, publicKey } = Account.generate();
// Returns: {
//   address: "io1...",
//   privateKey: "0x...",
//   publicKey: "0x..."
// }
```

#### Get Address from Private Key
```typescript
const address = Account.getAddress('0xprivate-key');
// Returns: "io1..."
```

#### Verify Message Signature
```typescript
const isValid = Account.verify(
  'original-message',
  'signature-hex',
  'io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v'
);
// Returns: true | false
```

#### Parse HD Wallet Path
```typescript
const { account, change, index } = Account.parseHDPath("m/44'/304'/0'/0/0");
// Returns: { account: 0, change: 0, index: 0 }
```

---

## Blockchain Module

Comprehensive blockchain query functionality.

### Chain & Epoch Queries

#### Get Chain Metadata
```typescript
const chainMeta = await sdk.blockchain.getChainMeta();
// Returns: ChainMeta {
//   height: 20000000n,
//   numActions: 500000000n,
//   epoch: { num: 5000n, height: 1234567n },
//   tps: 100,
//   tpsFloat: 100.5
// }
```

#### Get Epoch Metadata
```typescript
// Current epoch
const currentEpoch = await sdk.blockchain.getEpochMeta();

// Specific epoch
const epoch1000 = await sdk.blockchain.getEpochMeta(1000);

// Returns: EpochMeta {
//   num: 1000n,
//   height: 123456n,
//   gravityChainStartHeight: 5000000n
// }
```

### Block Queries

#### Get Block by Height
```typescript
const block = await sdk.blockchain.getBlock(1000000);
// Returns: Block {
//   blockHash: "0x...",
//   height: 1000000n,
//   timestamp: 1640000000,
//   numActions: 50,
//   producerAddress: "io1..."
// }
```

#### Get Block by Hash
```typescript
const block = await sdk.blockchain.getBlock('0xblock-hash-here');
// Returns: Block { ... }
```

#### Get Latest Block
```typescript
const chainMeta = await sdk.blockchain.getChainMeta();
const latestBlock = await sdk.blockchain.getBlock(Number(chainMeta.height));
```

### Blockchain Version

#### Get Blockchain Version Info
```typescript
const version = await sdk.blockchain.getVersion();
// Returns: VersionInfo {
//   packageVersion: "v1.12.0",
//   packageCommitID: "abc123def456",
//   goVersion: "go1.19.5",
//   buildTime: "2023-01-15T10:30:00Z"
// }
```

### Transaction Queries

#### Get Transaction Receipt
```typescript
const receipt = await sdk.blockchain.getReceipt('action-hash-hex');
// Returns: {
//   status: 1 | 0,
//   blockHeight: 1000000n,
//   actionHash: "0x...",
//   gasConsumed: 50000n,
//   contractAddress: "io1..." | null
// }
```

#### Query Actions (Advanced)
```typescript
// By action hash
const actions = await sdk.blockchain.getActions({
  byHash: 'action-hash-hex'
});

// By address with pagination
const actions = await sdk.blockchain.getActions({
  byAddr: {
    address: 'io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v',
    start: 0,
    count: 10
  }
});

// By block hash with pagination
const actions = await sdk.blockchain.getActions({
  byBlk: {
    blkHash: 'block-hash',
    start: 0,
    count: 10
  }
});

// By height range
const actions = await sdk.blockchain.getActions({
  byIndex: {
    start: 100,
    count: 50
  }
});

// Returns: ActionInfo[] with transaction details
```

### Voting Bucket Queries

#### Get All Voting Buckets
```typescript
const buckets = await sdk.blockchain.getBucketList();
// Returns: VoteBucket[] {
//   index: 1n,
//   voter: "io1...",
//   candidate: "delegate-name",
//   amount: "1000.5",  // in IOTX
//   duration: 7,       // days
//   createTime: 1640000000,
//   unstakeTime: 1640604800,
//   unstakeStartTime: null,
//   endorse: false
// }
```

#### Get Buckets by Voter
```typescript
const buckets = await sdk.blockchain.getBucketList({
  voterAddress: 'io1...',
  offset: 0,
  limit: 100
});
```

#### Get Buckets by Candidate
```typescript
const buckets = await sdk.blockchain.getBucketList({
  candidateName: 'delegate-name',
  offset: 0,
  limit: 100
});

// Calculate total raw staked IOTX for a delegate
// (This is different from weighted votes which include lock multiplier)
const totalStakedIotx = buckets.reduce(
  (sum, bucket) => sum + parseFloat(bucket.stakedAmount),
  0
);
```

#### Get Specific Bucket
```typescript
const bucket = await sdk.blockchain.getBucket(42);
// Returns: VoteBucket { ... }
```

### Smart Contract Queries

#### Read Contract State
```typescript
const result = await sdk.blockchain.readContract({
  execution: {
    amount: '0',
    contract: 'io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw',
    data: 'contract-method-call-data'
  },
  callerAddress: 'io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v',
  gasLimit: '1000000',
  gasPrice: '1'
});
// Returns: { result: "0x..." }
```

---

## Node Delegate Module

Query delegates, candidates, and epoch information.

### Delegate Queries

#### Get Block Producers (Top 36)
```typescript
const delegates = await sdk.node.getDelegates();
// Returns: Delegate[] with full candidate information
// Each delegate contains:
// {
//   rank: 1,
//   address: "io1...",              // Operator address
//   name: "Delegate Name",
//   votes: "1000000.5",             // WEIGHTED votes in IOTX (includes lock multiplier)
//   production: 100,
//   expectedProduction: 104,
//   active: true,                   // Whether actively producing blocks in current epoch
//
//   // Extended candidate information (v0.2.2+)
//   ownerAddress: "io1...",         // Owner address
//   operatorAddress: "io1...",      // Same as 'address'
//   rewardAddress: "io1...",        // Where rewards are sent
//   totalWeightedVotes: "1234...",  // Raw weighted votes (Rau string)
//   selfStakeBucketIdx: 55n,        // Self-stake bucket index
//   selfStakingTokens: "1200...",   // Self-staked amount (Rau string)
//   id: "io1..."                    // Candidate ID
// }

// NOTE: 'votes' is WEIGHTED (includes lock duration multiplier).
// To get actual staked IOTX, query buckets by candidate name.
```

#### Get All Registered Candidates
```typescript
const allCandidates = await sdk.node.getDelegates({ all: true });
// Returns: ~120-150 candidates including non-producers
// All candidates include the same extended information as above
```

#### Get Delegates for Specific Epoch
```typescript
const epochDelegates = await sdk.node.getDelegates({
  epochNumber: 1000,
  all: false  // only block producers
});

const allEpochCandidates = await sdk.node.getDelegates({
  epochNumber: 1000,
  all: true   // all registered candidates
});

// Access extended delegate information
for (const delegate of epochDelegates) {
  console.log(`${delegate.name}:`);
  console.log(`  Operator: ${delegate.operatorAddress}`);
  console.log(`  Owner: ${delegate.ownerAddress}`);
  console.log(`  Reward: ${delegate.rewardAddress}`);
  console.log(`  Self-stake: ${delegate.selfStakingTokens}`);
}
```

### Epoch Information

#### Get Current Epoch
```typescript
const currentEpoch = await sdk.node.getCurrentEpoch();
// Returns: EpochMeta {
//   num: 5000n,
//   height: 123456n,
//   gravityChainStartHeight: 5000000n
// }
```

### Advanced Delegate Methods

#### Get Block Producers Only
```typescript
const producers = await sdk.node.getBlockProducers(1000);
// Returns: Array<{ address: string; name: string; votes: string }>
```

#### Get All Staking Candidates
```typescript
const candidates = await sdk.node.getAllCandidates(offset = 0, limit = 100);
// Returns: Candidate[] { ... }
// Note: Use pagination for large result sets
```

#### Get Candidate by Name
```typescript
const candidate = await sdk.node.getCandidateByName('delegate-name');
// Returns: Candidate { ... } | null
```

#### Get Probation List
```typescript
const probationList = await sdk.node.getProbationList(1000);
// Returns: Set<string> of probation addresses
```

#### Get Active Block Producers
```typescript
const activeProducers = await sdk.node.getActiveBlockProducers(1000, '123456');
// Returns: Set<string> of active producer addresses
```

---

## Keystore Management

Direct keystore operations (also available via `sdk.account`).

### Usage Example
```typescript
import { Keystore } from 'iotex-node-sdk';

const keystore = new Keystore();

// Create account
const { address } = await keystore.create('password');

// List accounts
const accounts = keystore.list();

// Get keystore directory
const dir = keystore.getKeystoreDir();
// Returns: ~/.iotex-node-sdk/keystore/
```

### Features
- Encrypted storage using ethers.js Wallet format
- AES-256-CFB encryption
- Password-based key derivation
- SCRYPT key derivation parameters
- Atomic operations with temp files

---

## HD Wallet

Direct HD wallet operations (also available via `sdk.account`).

### Usage Example
```typescript
import { HDWallet } from 'iotex-node-sdk';

const hdwallet = new HDWallet();

// Create wallet
const mnemonic = await hdwallet.create('password', 'english');

// Derive account
const account = await hdwallet.derive('password', 0, 0, 0);
// Path: m/44'/304'/0'/0/0
```

### Derivation Path Format
- **BIP44 Standard**: `m/44'/304'/account'/change/index`
- **Coin Type**: 304 (IoTeX)
- **Path Examples**:
  - `m/44'/304'/0'/0/0` - First account, external, first address
  - `m/44'/304'/0'/0/1` - First account, external, second address
  - `m/44'/304'/0'/1/0` - First account, internal (change), first address
  - `m/44'/304'/1'/0/0` - Second account, external, first address

### Security
- 128-bit mnemonic (12 words)
- Encrypted with AES-256-CFB
- SHA256 integrity check
- Config stored in `~/.iotex-node-sdk/hdwallet/`
- Private keys never persisted

---

## Cryptographic Functions

Low-level cryptographic operations.

### Key Generation & Management

#### Generate Random Key Pair
```typescript
import { generateKeyPair } from 'iotex-node-sdk';

const { address, privateKey, publicKey } = generateKeyPair();
// Returns: {
//   address: "io1...",
//   privateKey: "0x...",
//   publicKey: "0x..."
// }
```

#### Get Public Key from Private Key
```typescript
import { getPublicKey } from 'iotex-node-sdk';

const publicKey = getPublicKey('0xprivate-key');
```

#### Get IoTeX Address from Private Key
```typescript
import { getAddress } from 'iotex-node-sdk';

const address = getAddress('0xprivate-key');
```

#### Get Ethereum Address from Private Key
```typescript
import { getEthAddress } from 'iotex-node-sdk';

const ethAddress = getEthAddress('0xprivate-key');
```

### Message Signing & Verification

#### Sign Message (Ethereum-style)
```typescript
import { signMessage } from 'iotex-node-sdk';

const signature = await signMessage('0xprivate-key', 'message-to-sign');
// Returns: "0x..."
// Uses Ethereum message prefix: "\x19Ethereum Signed Message:\n"
```

#### Verify Message Signature
```typescript
import { verifyMessage } from 'iotex-node-sdk';

const isValid = verifyMessage(
  'original-message',
  '0xsignature',
  'io1address-or-0xeth-address'
);
// Returns: true | false
```

### Hashing

#### SHA256 Hash
```typescript
import { hashSHA256 } from 'iotex-node-sdk';

const hash = hashSHA256('data-to-hash');
// or
const hash = hashSHA256(Buffer.from('data'));
// Returns: Buffer (32 bytes)
```

#### Keccak256 Hash
```typescript
import { hashKeccak256 } from 'iotex-node-sdk';

const hash = hashKeccak256('data-to-hash');
// Returns: string (hex)
```

### Encryption & Decryption

#### Encrypt Data
```typescript
import { encrypt, deriveKeyFromPassword } from 'iotex-node-sdk';

const key = deriveKeyFromPassword('password');
const encrypted = encrypt(Buffer.from('data'), key);
// Returns: Buffer
// Uses AES-256-CFB encryption
```

#### Decrypt Data
```typescript
import { decrypt, deriveKeyFromPassword } from 'iotex-node-sdk';

const key = deriveKeyFromPassword('password');
const decrypted = decrypt(encryptedBuffer, key);
// Returns: Buffer
```

#### Derive Key from Password
```typescript
import { deriveKeyFromPassword } from 'iotex-node-sdk';

const key = deriveKeyFromPassword('password');
// Returns: Buffer (32 bytes)
// Uses SHA256 for simplicity (production uses PBKDF2)
```

### Action Signing

#### Sign Transaction Action
```typescript
import { signAction } from 'iotex-node-sdk';

const signature = signAction(serializedActionBuffer, '0xprivate-key');
// Returns: string (hex signature)
```

---

## Validation Utilities

Input validation functions.

### Validation Predicates (return boolean)

#### Validate IoTeX Address
```typescript
import { isValidIoAddress } from 'iotex-node-sdk';

const valid = isValidIoAddress('io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw');
// Returns: true | false
```

#### Validate Ethereum Address
```typescript
import { isValidEthAddress } from 'iotex-node-sdk';

const valid = isValidEthAddress('0xb8744ae4032be5e5ef9fab94ee9c3bf38d5d2ae0');
// Returns: true | false
```

#### Validate Any Address Format
```typescript
import { isValidAddress } from 'iotex-node-sdk';

const valid = isValidAddress('io1...' | '0x...');
// Returns: true | false (accepts either format)
```

#### Validate Amount
```typescript
import { isValidAmount } from 'iotex-node-sdk';

const valid = isValidAmount('123.456');
// Returns: true | false (must be positive number)
```

#### Validate Duration
```typescript
import { isValidDuration } from 'iotex-node-sdk';

const valid = isValidDuration(7);
// Returns: true | false (must be positive)
```

#### Validate Candidate Name
```typescript
import { isValidCandidateName } from 'iotex-node-sdk';

const valid = isValidCandidateName('delegate-name');
// Returns: true | false
```

#### Validate Private Key
```typescript
import { isValidPrivateKey } from 'iotex-node-sdk';

const valid = isValidPrivateKey('0x...');
// Returns: true | false
```

#### Validate BLS Public Key
```typescript
import { isValidBLSPubKey } from 'iotex-node-sdk';

const valid = isValidBLSPubKey('0x...');
// Returns: true | false (96 bytes = 192 hex chars)
```

### Validation Throwing Functions (throw on invalid)

#### Validate Address (throws)
```typescript
import { validateAddress } from 'iotex-node-sdk';

validateAddress('io1...', 'paramName');
// Throws: IoTeXError if invalid
```

#### Validate Amount (throws)
```typescript
import { validateAmount } from 'iotex-node-sdk';

validateAmount('123.456', 'amount');
// Throws: IoTeXError if invalid
```

#### Validate Duration (throws)
```typescript
import { validateDuration } from 'iotex-node-sdk';

validateDuration(7, 'duration');
// Throws: IoTeXError if invalid
```

#### Validate Candidate Name (throws)
```typescript
import { validateCandidateName } from 'iotex-node-sdk';

validateCandidateName('delegate-name', 'name');
// Throws: IoTeXError if invalid
```

#### Validate BLS Public Key (throws)
```typescript
import { validateBLSPubKey } from 'iotex-node-sdk';

validateBLSPubKey('0x...', 'blsPubKey');
// Throws: IoTeXError if invalid
```

#### Validate Private Key (throws)
```typescript
import { validatePrivateKey } from 'iotex-node-sdk';

validatePrivateKey('0x...', 'privateKey');
// Throws: IoTeXError if invalid
```

---

## Conversion Utilities

Unit and format conversions.

### Currency Conversion

#### Convert IOTX to Rau (Smallest Unit)
```typescript
import { iotxToRau } from 'iotex-node-sdk';

const rau = iotxToRau('100');
// Returns: 100000000000000000000n (bigint)
// 1 IOTX = 10^18 Rau
```

#### Convert Rau to IOTX
```typescript
import { rauToIotx } from 'iotex-node-sdk';

const iotx = rauToIotx(100000000000000000000n);
// Returns: "100"
```

### Gas Price Conversion

#### Convert Rau to QEv (12 decimals)
```typescript
import { rauToQev } from 'iotex-node-sdk';

const qev = rauToQev(1000000000000000000n);
// Returns: "1000000000000" (string)
// Used for gas prices
```

#### Convert QEv to Rau
```typescript
import { qevToRau } from 'iotex-node-sdk';

const rau = qevToRau('1000000000000');
// Returns: 1000000000000000000n (bigint)
```

### Duration Formatting

#### Parse Duration String
```typescript
import { parseDuration } from 'iotex-node-sdk';

const days = parseDuration('7d');    // "7d" → 7
const days = parseDuration('1y');    // "1y" → 365
const days = parseDuration('30');    // "30" → 30
```

#### Format Days to Duration String
```typescript
import { formatDuration } from 'iotex-node-sdk';

const str = formatDuration(7);       // 7 → "7d"
const str = formatDuration(365);     // 365 → "1y"
const str = formatDuration(90);      // 90 → "90d"
```

---

## Error Handling

Comprehensive error handling with typed errors.

### IoTeXError Class

```typescript
import { IoTeXError } from 'iotex-node-sdk';

try {
  await sdk.account.getBalance('invalid');
} catch (error) {
  if (error instanceof IoTeXError) {
    console.log(error.code);     // Error code string
    console.log(error.message);  // Human-readable message
    console.log(error.details);  // Additional details (optional)
  }
}
```

### Error Codes

| Code | Description | Cause |
|------|-------------|-------|
| `CONNECTION_ERROR` | Cannot connect to endpoint | Network unreachable, wrong endpoint |
| `NOT_FOUND` | Resource not found | Account/block/action doesn't exist |
| `INVALID_ADDRESS` | Invalid address format | Bad address string |
| `INVALID_ARGUMENT` | Invalid argument | Bad parameter value |
| `ACCOUNT_NOT_FOUND` | Account doesn't exist | Query non-existent account |
| `BLOCK_NOT_FOUND` | Block doesn't exist | Query non-existent block |
| `UNAUTHENTICATED` | Authentication failed | Invalid JWT token |
| `PERMISSION_DENIED` | Permission denied | Insufficient permissions |
| `TIMEOUT` | Request timeout | Took too long |
| `ALREADY_EXISTS` | Resource already exists | Duplicate creation |
| `RESOURCE_EXHAUSTED` | Resource exhausted | Out of quota |
| `FAILED_PRECONDITION` | Failed precondition | Invalid state |
| `ABORTED` | Operation aborted | Aborted by system |
| `OUT_OF_RANGE` | Out of range | Parameter out of bounds |
| `UNIMPLEMENTED` | Not implemented | Feature not available |
| `INTERNAL_ERROR` | Internal error | Unexpected error |
| `DATA_LOSS` | Data loss | Data consistency issue |

### Error Handling Pattern

```typescript
import { IoTeXError } from 'iotex-node-sdk';

try {
  const balance = await sdk.account.getBalance('io1...');
} catch (error) {
  if (error instanceof IoTeXError) {
    switch (error.code) {
      case 'INVALID_ADDRESS':
        console.error('Please provide a valid address');
        break;
      case 'ACCOUNT_NOT_FOUND':
        console.error('Account does not exist on blockchain');
        break;
      case 'CONNECTION_ERROR':
        console.error('Cannot connect to blockchain node');
        break;
      default:
        console.error(error.message);
    }
  } else {
    console.error('Unexpected error:', error);
  }
}
```

---

## Configuration

SDK configuration options.

### GrpcConfig Interface

```typescript
interface GrpcConfig {
  endpoint: string;      // gRPC endpoint address:port
  secure: boolean;       // Use TLS encryption
  jwtToken?: string;     // Optional JWT authentication token
  timeout?: number;      // Request timeout in milliseconds
}
```

### Creating Custom Configuration

```typescript
import { IoTeXSDK } from 'iotex-node-sdk';

const sdk = new IoTeXSDK({
  endpoint: 'api.custom.com:443',
  secure: true,
  timeout: 60000,
  jwtToken: process.env.IOTEX_JWT_TOKEN
});
```

### Predefined Configurations

| Network | Endpoint | Secure |
|---------|----------|--------|
| Mainnet | api.iotex.one:443 | true |
| Testnet | api.testnet.iotex.one:443 | true |
| Localhost | localhost:14014 | false |

### Adding JWT Authentication

```typescript
const sdk = IoTeXSDK.mainnet();
sdk.getClient().withAuth('your-jwt-token');
await sdk.connect();
```

---

## Type Definitions

All TypeScript interfaces and types.

### Account Types

```typescript
interface AccountMeta {
  balance: string;           // Balance in IOTX
  nonce: bigint;            // Current nonce
  pendingNonce: bigint;     // Pending nonce
  numActions: bigint;       // Total actions
  isContract: boolean;      // Is contract account
}
```

### Blockchain Types

```typescript
interface ChainMeta {
  height: bigint;                    // Current block height
  numActions: bigint;                // Total actions
  epoch: { num: bigint; height: bigint };
  tps: number;                       // Transactions per second
  tpsFloat: number;                  // TPS with decimals
}

interface Block {
  blockHash: string;                 // Block hash (hex)
  height: bigint;                    // Block height
  timestamp: number;                 // Unix timestamp
  numActions: number;                // Actions in block
  producerAddress: string;           // Block producer address
}

interface EpochMeta {
  num: bigint;                       // Epoch number
  height: bigint;                    // Starting height
  gravityChainStartHeight: bigint;   // Gravity chain height
}

interface VersionInfo {
  packageVersion: string;            // Version tag
  packageCommitID: string;           // Git commit ID
  goVersion: string;                 // Go version used
  buildTime: string;                 // Build timestamp
}
```

### Delegate Types

```typescript
interface Delegate {
  rank: number;                      // 1-36 for producers, higher for others
  address: string;                   // Operator address (IoTeX address)
  name: string;                      // Delegate name
  votes: string;                     // Total WEIGHTED votes in IOTX (includes lock multiplier)
  production: number;                // Blocks produced in current epoch
  expectedProduction: number;        // Expected blocks to produce
  active: boolean;                   // Whether actively producing blocks in current epoch

  // Extended candidate information (available from v0.2.2+)
  ownerAddress?: string;             // Owner address of the delegate
  operatorAddress?: string;          // Operator address (same as 'address')
  rewardAddress?: string;            // Address where block rewards are sent
  totalWeightedVotes?: string;       // Total weighted votes (raw Rau string from blockchain)
  selfStakeBucketIdx?: bigint;       // Index of the self-staking bucket
  selfStakingTokens?: string;        // Self-staked tokens (raw Rau string)
  id?: string;                       // Candidate ID
}
```

#### Understanding Delegate Votes

**Important**: The `votes` field represents **weighted votes**, not raw staked IOTX:

- **Weighted Votes**: Staked IOTX multiplied by a lock duration multiplier (longer lock = higher multiplier)
- **Raw Staked IOTX**: The actual amount of IOTX tokens staked (without multiplier)

To get the **total raw staked IOTX** for a delegate, you need to query all buckets voting for that delegate and sum their `stakedAmount`:

```typescript
// Get total raw staked IOTX for a delegate
const buckets = await sdk.blockchain.getBucketList({
  candidateName: 'delegateName',
  offset: 0,
  limit: 10000
});

const totalStakedIotx = buckets.reduce(
  (sum, bucket) => sum + parseFloat(bucket.stakedAmount),
  0
);
console.log(`Total staked: ${totalStakedIotx} IOTX`);
console.log(`Weighted votes: ${delegate.votes} IOTX`);
```

The `selfStakingTokens` field contains the delegate's own self-staked tokens in raw Rau format.

```typescript

interface Candidate {
  name: string;                      // Candidate name
  ownerAddress: string;              // Owner address
  operatorAddress: string;           // Operator address
  rewardAddress: string;             // Reward address
  totalWeightedVotes: string;        // Total weighted votes
  selfStakingTokens?: string;        // Self-staked tokens
  selfStakeBucketIdx?: bigint;       // Self-stake bucket index
  id?: string;                       // Candidate ID
}
```

### Voting Types

```typescript
interface VoteBucket {
  index: bigint;                     // Bucket index
  candidateAddress: string;          // Candidate/delegate address being voted for
  stakedAmount: string;              // Raw staked amount in IOTX (NOT weighted)
  stakedDuration: number;            // Lock duration in days
  createTime: Date;                  // When bucket was created
  stakeStartTime: Date;              // When staking started
  unstakeStartTime?: Date;           // When unstaking started (if unstaking)
  autoStake: boolean;                // Auto-restake enabled
  owner: string;                     // Bucket owner address
  contractAddress: string;           // Associated contract (if any)
  endorsement?: number;              // Endorsement level
}

// NOTE: stakedAmount is the RAW staked IOTX, not weighted.
// Weighted votes = stakedAmount × lock duration multiplier
// Sum all bucket stakedAmounts to get total staked IOTX for a delegate.

interface ActionInfo {
  actionHash: string;
  actionType: string;
  nonce: bigint;
  sender: string;
  recipient?: string;
  gasPrice: string;
  gasLimit: bigint;
  amount?: string;
  payload?: string;
}
```

### Account Management Types

```typescript
interface KeystoreAccount {
  address: string;                   // IoTeX address
  publicKey: string;                 // Public key hex
}

interface HDWalletAccount {
  address: string;                   // Derived address
  publicKey: string;                 // Public key hex
  privateKey: string;                // Private key (temp)
}

interface SDKConfig {
  endpoint: string;
  secure: boolean;
  jwtToken?: string;
  timeout?: number;
}
```

### Staking Parameter Types

```typescript
interface StakeCreateParams {
  candidateName: string;
  stakedAmount: string;              // In IOTX
  stakedDuration: number;            // In days
  autoStake: boolean;
  payload?: string;
}

interface StakeRegisterParams {
  candidateName: string;
  operatorAddress: string;
  rewardAddress: string;
  ownerAddress?: string;
  amount?: string;
}

interface StakeUpdateCandidateParams {
  name?: string;
  operatorAddress?: string;
  rewardAddress?: string;
}

interface SendActionResult {
  actionHash: string;
  blockHeight?: bigint;
  status: number;
}
```

---

## Import Examples

### Import Everything
```typescript
import {
  IoTeXSDK,
  iotxToRau,
  rauToIotx,
  isValidIoAddress,
  IoTeXError
} from 'iotex-node-sdk';
```

### Import Specific Modules
```typescript
import { IoTeXSDK } from 'iotex-node-sdk';
import { Keystore, HDWallet } from 'iotex-node-sdk';
import { signMessage, verifyMessage } from 'iotex-node-sdk';
```

### Import from Entry Point
```typescript
import * as IoTeX from 'iotex-node-sdk';

const sdk = new IoTeX.IoTeXSDK({ endpoint: '...' });
```

---

## Complete Example

A comprehensive example using multiple features:

```typescript
import {
  IoTeXSDK,
  iotxToRau,
  rauToIotx,
  isValidIoAddress,
  IoTeXError
} from 'iotex-node-sdk';

async function completeExample() {
  // Create SDK
  const sdk = IoTeXSDK.mainnet();

  try {
    // Connect
    await sdk.connect();
    console.log('Connected to IoTeX mainnet');

    // Query chain
    const chain = await sdk.blockchain.getChainMeta();
    console.log(`Height: ${chain.height}, Epoch: ${chain.epoch.num}`);

    // Create account
    const { address, privateKey } = await sdk.account.create('password');
    console.log(`Created account: ${address}`);

    // Query balance
    const balance = await sdk.account.getBalance(address);
    console.log(`Balance: ${balance} IOTX`);

    // Get delegates
    const delegates = await sdk.node.getDelegates({ all: true });
    console.log(`Total candidates: ${delegates.length}`);

    // Conversion
    const rau = iotxToRau('100');
    const iotx = rauToIotx(rau);
    console.log(`100 IOTX = ${rau} Rau = ${iotx} IOTX`);

    // Validation
    if (isValidIoAddress(address)) {
      console.log('Address is valid');
    }

    // Export voting buckets
    const buckets = await sdk.blockchain.getBucketList({
      voterAddress: address,
      limit: 10
    });
    console.log(`Found ${buckets.length} voting buckets`);

  } catch (error) {
    if (error instanceof IoTeXError) {
      console.error(`SDK Error [${error.code}]: ${error.message}`);
    } else {
      console.error('Unexpected error:', error);
    }
  } finally {
    sdk.disconnect();
  }
}

completeExample();
```

---

## See Also

- [README_QUERIES.md](./README_QUERIES.md) - Query examples and patterns
- [QUERY_GUIDE.md](./QUERY_GUIDE.md) - Quick reference guide
- [GETTING_STARTED.md](./GETTING_STARTED.md) - Setup instructions
- [IoTeX Docs](https://docs.iotex.io) - Official IoTeX documentation
