# IoTeX Node.js SDK - Advanced Queries & Error Handling

Comprehensive guide to advanced query operations, error handling patterns, and troubleshooting.

## Table of Contents

1. [Advanced Blockchain Queries](#advanced-blockchain-queries)
2. [Action & Transaction Queries](#action--transaction-queries)
3. [Voting Bucket Queries](#voting-bucket-queries)
4. [Smart Contract Queries](#smart-contract-queries)
5. [Delegate & Candidate Queries](#delegate--candidate-queries)
6. [Error Handling](#error-handling)
7. [Performance Optimization](#performance-optimization)
8. [Batch Operations](#batch-operations)

---

## Advanced Blockchain Queries

### Get Detailed Block Information

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

const sdk = IoTeXSDK.mainnet();
await sdk.connect();

// Get latest block height
const chain = await sdk.blockchain.getChainMeta();
const latestHeight = Number(chain.height);

// Get latest block details
const latestBlock = await sdk.blockchain.getBlock(latestHeight);

console.log({
  hash: latestBlock.blockHash,
  height: latestBlock.height.toString(),
  timestamp: new Date(latestBlock.timestamp * 1000),
  producer: latestBlock.producerAddress,
  numActions: latestBlock.numActions
});
```

### Query Historical Blocks

```typescript
// Get blocks in a range
async function getBlocksInRange(startHeight: number, endHeight: number) {
  const blocks = [];

  for (let height = startHeight; height <= endHeight; height++) {
    try {
      const block = await sdk.blockchain.getBlock(height);
      blocks.push({
        height: block.height.toString(),
        hash: block.blockHash,
        numActions: block.numActions,
        producer: block.producerAddress
      });
    } catch (error) {
      console.error(\`Failed to get block \${height}:\`, error);
    }
  }

  return blocks;
}

// Get last 100 blocks
const chain = await sdk.blockchain.getChainMeta();
const latestHeight = Number(chain.height);
const blocks = await getBlocksInRange(latestHeight - 100, latestHeight);
console.log(\`Retrieved \${blocks.length} blocks\`);
```

### Get Block by Hash

```typescript
// If you know the block hash
const blockHash = '0xabcd1234...';
const block = await sdk.blockchain.getBlock(blockHash);

console.log('Block:', {
  hash: block.blockHash,
  height: block.height.toString(),
  actions: block.numActions
});
```

### Epoch Pagination

```typescript
async function getAllEpochsData() {
  const chain = await sdk.blockchain.getChainMeta();
  const currentEpoch = Number(chain.epoch.num);

  const epochs = [];

  // Get metadata for last 10 epochs
  for (let i = currentEpoch; i > currentEpoch - 10; i--) {
    try {
      const epoch = await sdk.blockchain.getEpochMeta(i);
      epochs.push({
        num: epoch.num.toString(),
        height: epoch.height.toString(),
        gravityChainHeight: epoch.gravityChainStartHeight.toString()
      });
    } catch (error) {
      console.error(\`Failed to get epoch \${i}:\`, error);
    }
  }

  return epochs;
}

const epochsData = await getAllEpochsData();
console.log('Recent epochs:', epochsData);
```

### Get Blockchain Statistics

```typescript
async function getBlockchainStats() {
  const chain = await sdk.blockchain.getChainMeta();

  return {
    currentHeight: chain.height.toString(),
    currentEpoch: chain.epoch.num.toString(),
    totalActions: chain.numActions.toString(),
    transactionsPerSecond: chain.tps,
    tpsAverage: chain.tpsFloat
  };
}

const stats = await getBlockchainStats();
console.log('Blockchain Statistics:', stats);
```

---

## Action & Transaction Queries

### Query Action by Hash

```typescript
// Get a specific transaction
const actionHash = '0xabcd1234...';
const actions = await sdk.blockchain.getActions({
  byHash: actionHash
});

if (actions.length > 0) {
  const action = actions[0];
  console.log({
    hash: action.actionHash,
    sender: action.sender,
    recipient: action.recipient,
    amount: action.amount,
    gasPrice: action.gasPrice,
    gasLimit: action.gasLimit.toString()
  });
}
```

### Query Actions by Address

```typescript
// Get all actions from an address with pagination
async function getAddressActions(
  address: string,
  maxResults: number = 1000
) {
  const allActions = [];
  let offset = 0;
  const pageSize = 100;

  while (allActions.length < maxResults) {
    const actions = await sdk.blockchain.getActions({
      byAddr: {
        address,
        start: offset,
        count: pageSize
      }
    });

    if (actions.length === 0) break;

    allActions.push(...actions);
    offset += pageSize;
  }

  return allActions.slice(0, maxResults);
}

const addressActions = await getAddressActions('io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v');
console.log(\`Found \${addressActions.length} actions\`);

// Analyze actions
const received = addressActions.filter(a => a.recipient === 'io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v');
const sent = addressActions.filter(a => a.sender === 'io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v');

console.log(\`Sent: \${sent.length} actions\`);
console.log(\`Received: \${received.length} actions\`);
```

### Error Handling

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

try {
  const balance = await sdk.account.getBalance('io1...');
} catch (error) {
  if (error instanceof IoTeXError) {
    console.error(\`Error: [\${error.code}] \${error.message}\`);
  } else {
    console.error('Unexpected error:', error);
  }
}
```

---

## See Also

- [API_COMPLETE_REFERENCE.md](./API_COMPLETE_REFERENCE.md) - Full API reference
- [ACCOUNT_MANAGEMENT.md](./ACCOUNT_MANAGEMENT.md) - Account & HD wallet guide
- [README_QUERIES.md](./README_QUERIES.md) - Query examples
- [GETTING_STARTED.md](./GETTING_STARTED.md) - Setup guide
- [IoTeX Docs](https://docs.iotex.io) - Official documentation
