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

@pixagram/dpixa

v1.5.4

Published

Pixa blockchain RPC client library

Readme

dpixa

Robust pixa client library that runs in both node.js and the browser.

Needs test net urls, chain id


note As of version 0.7.0 WebSocket support has been removed. The only transport provided now is HTTP(2). For most users the only change required is to swap wss:// to https:// in the address. If you run your own full node make sure to set the proper CORS headers if you plan to access it from a browser.


Browser compatibility

Build Status

Installation

Via npm

For node.js or the browser with browserify or webpack.

npm install @pixagram/dpixa

Bundling

The easiest way to bundle dpixa (with browserify, webpack etc.) is to just npm install @pixagram/dpixa and require('@pixagram/dpixa') which will give you well-tested (see browser compatibility matrix above) pre-bundled code guaranteed to JustWork™. However, that is not always desirable since it will not allow your bundler to de-duplicate any shared dependencies dpixa and your app might have.

To allow for deduplication you can require('@pixagram/dpixa/lib/index-browser'), or if you plan to provide your own polyfills: require('@pixagram/dpixa/lib/index'). See src/index-browser.ts for a list of polyfills expected.


Share and Enjoy!


client.database .getDiscussions("trending", { tag: "writing", limit: 5 }) .then(function(discussions) { discussions.forEach(post => { console.log(${post.title} by @${post.author}); }); }); </script>

const client = new Client([ "https://api.pixagram.io", "https://api.hivekings.com" ]);

async function main() { const props = await client.database.getDynamicGlobalProperties(); console.log(Current block: ${props.head_block_number}); }

main();

const client = new Client(["https://api.pixagram.io"]);

// Vote on a post const key = PrivateKey.fromLogin("username", "password", "posting");

client.broadcast .vote( { voter: "username", author: "almost-digital", permlink: "dpixa-is-the-best", weight: 10000 }, key ) .then(result => { console.log(Included in block: ${result.block_num}); });

// Basic initialization with multiple nodes for failover const client = new Client([ "https://api.pixagram.io", "https://api.hivekings.com", "https://anyx.io", "https://api.openhive.network" ]);

// With custom options const clientWithOptions = new Client(["https://api.pixagram.io"], { timeout: 30000, // Request timeout in ms (default: 60000) failoverThreshold: 3, // Retry rounds before giving up consoleOnFailover: true, // Log when failing over to another node addressPrefix: "PIX", // Network address prefix chainId: "your-chain-id" // Custom chain ID });

Option | Type | Default | Description -- | -- | -- | -- timeout | number | 60000 | Request timeout in milliseconds. Set to 0 to retry forever. failoverThreshold | number | 3 | Number of retry rounds across all URLs before failing. Set to 0 for infinite retries. consoleOnFailover | boolean | false | Log failover events to console addressPrefix | string | "PIX" | Network address prefix for key encoding chainId | string | Main chain ID | Blockchain chain ID (32-byte hex string) agent | http.Agent | https.globalAgent | Custom HTTP agent for keep-alive connections backoff | (tries: number) => number | Default backoff | Custom retry backoff function returning milliseconds

</details>

// BlockchainMode BlockchainMode.Irreversible // 0 — Only confirmed blocks (default) BlockchainMode.Latest // 1 — Head block (may be reversed on fork)

console.log(VERSION); // Library version string console.log(DEFAULT_ADDRESS_PREFIX); // "PIX" console.log(DEFAULT_CHAIN_ID); // Buffer (32 bytes) console.log(NETWORK_ID); // Buffer (network ID for WIF)

const agent = new https.Agent({ keepAlive: true, maxSockets: 10 });

const client = new Client(["https://api.pixagram.io"], { agent: agent });

for await (const op of client.blockchain.getOperations()) { const [opType, opData] = op.op;

if (opType === "comment" &amp;&amp; 
    opData.parent_author === "" &amp;&amp;  // Root post only
    authors.includes(opData.author)) {
  
  try {
    await client.broadcast.vote({
      voter: "mybot",
      author: opData.author,
      permlink: opData.permlink,
      weight: weight
    }, postingKey);
    
    console.log(`Voted on @${opData.author}/${opData.permlink}`);
  } catch (error) {
    console.error(`Vote failed: ${error.message}`);
  }
}

} }

autoVoter(["favorite-author1", "favorite-author2"]);


Table of Contents


Installation

Via npm

npm install @pixagram/dpixa

Via yarn

yarn add @pixagram/dpixa

Via CDN

<script src="https://unpkg.com/@pixagram/dpixa@latest/dist/dpixa.js"></script>

Self-hosted

Download dist/dpixa.js from the repository and include it in your HTML:

<script src="dpixa.js"></script>

Quick Start

Browser Usage

<script src="https://unpkg.com/@pixagram/dpixa@latest/dist/dpixa.js"></script>
<script>
  const client = new dpixa.Client([
    "https://api.pixagram.io",
    "https://api.hivekings.com",
    "https://anyx.io"
  ]);

  client.database
    .getDiscussions("trending", { tag: "writing", limit: 5 })
    .then(function(discussions) {
      discussions.forEach(post => {
        console.log(`${post.title} by @${post.author}`);
      });
    });
</script>

Node.js with ES Modules

import { Client } from "@pixagram/dpixa";

const client = new Client([
  "https://api.pixagram.io",
  "https://api.hivekings.com"
]);

async function main() {
  const props = await client.database.getDynamicGlobalProperties();
  console.log(`Current block: ${props.head_block_number}`);
}

main();

Node.js with CommonJS

const { Client, PrivateKey } = require("@pixagram/dpixa");

const client = new Client(["https://api.pixagram.io"]);

// Vote on a post
const key = PrivateKey.fromLogin("username", "password", "posting");

client.broadcast
  .vote(
    {
      voter: "username",
      author: "almost-digital",
      permlink: "dpixa-is-the-best",
      weight: 10000
    },
    key
  )
  .then(result => {
    console.log(`Included in block: ${result.block_num}`);
  });

Core Concepts

Client

The Client class is your main entry point to interact with the Pixa blockchain. It manages RPC connections, provides access to various APIs, and handles failover between multiple nodes.

Creating a Client

import { Client } from "@pixagram/dpixa";

// Basic initialization with multiple nodes for failover
const client = new Client([
  "https://api.pixagram.io",
  "https://api.hivekings.com",
  "https://anyx.io",
  "https://api.openhive.network"
]);

// With custom options
const clientWithOptions = new Client(["https://api.pixagram.io"], {
  timeout: 30000,              // Request timeout in ms (default: 60000)
  failoverThreshold: 3,        // Retry rounds before giving up
  consoleOnFailover: true,     // Log when failing over to another node
  addressPrefix: "PIX",        // Network address prefix
  chainId: "your-chain-id"    // Custom chain ID
});

Using Testnet

// Create a client configured for testnet
const testClient = Client.testnet();

Making Raw RPC Calls

// Direct RPC call to any API
const result = await client.call("database_api", "get_dynamic_global_properties", []);

| Option | Type | Default | Description | |--------|------|---------|-------------| | timeout | number | 60000 | Request timeout in milliseconds. Set to 0 to retry forever. | | failoverThreshold | number | 3 | Number of retry rounds across all URLs before failing. Set to 0 for infinite retries. | | consoleOnFailover | boolean | false | Log failover events to console | | addressPrefix | string | "PIX" | Network address prefix for key encoding | | chainId | string | Main chain ID | Blockchain chain ID (32-byte hex string) | | agent | http.Agent | https.globalAgent | Custom HTTP agent for keep-alive connections | | backoff | (tries: number) => number | Default backoff | Custom retry backoff function returning milliseconds |

Client Properties

// Available API helpers
client.database   // DatabaseAPI - Query blockchain state
client.broadcast  // BroadcastAPI - Send transactions
client.blockchain // Blockchain - Stream blocks and operations
client.rc         // RCAPI - Resource credits
client.keys       // AccountByKeyAPI - Find accounts by key
client.pixamind   // PixamindAPI - Community features
client.transaction // TransactionStatusAPI - Check transaction status

// Network configuration (read-only)
client.chainId        // Buffer - Current chain ID
client.addressPrefix  // string - Address prefix (e.g., "PIX")
client.address        // string | string[] - Configured RPC addresses
client.options        // ClientOptions - Current options

// Mutable
client.currentAddress // string - Currently active RPC node

Database API

The DatabaseAPI provides methods to query blockchain state, retrieve accounts, blocks, and content.


getDynamicGlobalProperties()

Returns the current state of the blockchain.

Returns: Promise<DynamicGlobalProperties>

const props = await client.database.getDynamicGlobalProperties();
{
  id: 0,
  head_block_number: 12345678,
  head_block_id: "00bc614e...",
  time: "2024-01-15T12:30:00",
  current_witness: "witness-name",
  total_pow: 514415,
  num_pow_witnesses: 172,
  virtual_supply: "400000000.000 PIXA",
  current_supply: "380000000.000 PIXA",
  current_pxs_supply: "15000000.000 PXS",
  total_vesting_fund_pixa: "150000000.000 PIXA",
  total_vesting_shares: "300000000000.000000 VESTS",
  total_reward_fund_pixa: "800000.000 PIXA",
  pending_rewarded_vesting_shares: "500000.000000 VESTS",
  pending_rewarded_vesting_pixa: "250.000 PIXA",
  pxs_interest_rate: 1000,  // 10% APR
  pxs_print_rate: 10000,
  maximum_block_size: 65536,
  current_aslot: 12500000,
  recent_slots_filled: "340282366920938463463374607431768211455",
  participation_count: 128,
  last_irreversible_block_num: 12345660,
  vote_power_reserve_rate: 10,
  current_reserve_ratio: 200000000
}

Use Cases:

  • Check current block height
  • Calculate VESTS to PIXA conversion
  • Monitor network participation
  • Get current witness schedule
// Practical example: Calculate PIXA Power from VESTS
const props = await client.database.getDynamicGlobalProperties();
const totalVestingFund = Asset.fromString(props.total_vesting_fund_pixa);
const totalVestingShares = Asset.fromString(props.total_vesting_shares);

function vestsToPixa(vests) {
  return (vests * totalVestingFund.amount) / totalVestingShares.amount;
}

console.log(`1M VESTS = ${vestsToPixa(1000000).toFixed(3)} PIXA`);

getChainProperties()

Returns the median chain properties as voted by witnesses.

Returns: Promise<ChainProperties>

const chainProps = await client.database.getChainProperties();
{
  account_creation_fee: "3.000 PIXA",
  maximum_block_size: 65536,
  pxs_interest_rate: 1000  // 10% APR (basis points)
}

Use Cases:

  • Check minimum account creation fee
  • Get current interest rate on PXS
// Calculate actual account creation fee (30x the base fee)
const props = await client.database.getChainProperties();
const baseFee = Asset.fromString(props.account_creation_fee);
const actualFee = baseFee.multiply(30);
console.log(`Account creation costs: ${actualFee}`); // "90.000 PIXA"

getCurrentMedianHistoryPrice()

Returns the median PIXA/PXS price feed as reported by witnesses.

Returns: Promise<Price>

const price = await client.database.getCurrentMedianHistoryPrice();
{
  base: "0.500 PXS",
  quote: "1.000 PIXA"
}
// This means 1 PIXA = 0.5 PXS

Use Cases:

  • Calculate USD value of PIXA (PXS is pegged to USD)
  • Estimate post payouts
const price = await client.database.getCurrentMedianHistoryPrice();
const priceObj = Price.from(price);

// Convert PIXA to PXS value
const pixaAmount = Asset.fromString("100.000 PIXA");
const pxsValue = priceObj.convert(pixaAmount);
console.log(`100 PIXA ≈ ${pxsValue}`); // "50.000 PXS"

getConfig()

Returns the compile-time configuration of the node.

Returns: Promise<{[name: string]: string | number | boolean}>

const config = await client.database.getConfig();
{
  IS_TEST_NET: false,
  PIXA_BLOCKCHAIN_HARDFORK_VERSION: "1.27.0",
  PIXA_BLOCK_INTERVAL: 3,
  PIXA_BLOCKS_PER_DAY: 28800,
  PIXA_BLOCKS_PER_YEAR: 10512000,
  PIXA_CASHOUT_WINDOW_SECONDS: 604800,
  PIXA_CREATE_ACCOUNT_WITH_PIXA_MODIFIER: 30,
  PIXA_MAX_ACCOUNT_NAME_LENGTH: 16,
  PIXA_MAX_MEMO_SIZE: 2048,
  PIXA_MIN_ACCOUNT_NAME_LENGTH: 3,
  PIXA_SAVINGS_WITHDRAW_TIME: 259200,
  PIXA_VESTING_WITHDRAW_INTERVALS: 13,
  PIXA_VOTE_DUST_THRESHOLD: 50000000
  // ... many more
}

getState(path)

Returns the complete state for a URL path (legacy, use specific methods when possible).

Parameters:

| Parameter | Type | Description | |-----------|------|-------------| | path | string | URL path like @username or trending/tag |

Returns: Promise<any>

// Get state for a user profile
const state = await client.database.getState("@alice");

// Get state for a tag
const tagState = await client.database.getState("trending/photography");

getBlockHeader(blockNum)

Returns the header of a specific block (without transactions).

Parameters:

| Parameter | Type | Description | |-----------|------|-------------| | blockNum | number | Block number to fetch |

Returns: Promise<BlockHeader>

const header = await client.database.getBlockHeader(12345678);
{
  previous: "00bc614d...",
  timestamp: "2024-01-15T12:30:00",
  witness: "witness-name",
  transaction_merkle_root: "0000000000000000000000000000000000000000",
  extensions: []
}

getBlock(blockNum)

Returns a complete block including all transactions.

Parameters:

| Parameter | Type | Description | |-----------|------|-------------| | blockNum | number | Block number to fetch |

Returns: Promise<SignedBlock>

const block = await client.database.getBlock(12345678);
{
  previous: "00bc614d...",
  timestamp: "2024-01-15T12:30:00",
  witness: "witness-name",
  transaction_merkle_root: "abc123...",
  extensions: [],
  witness_signature: "1f4a2b...",
  block_id: "00bc614e...",
  signing_key: "PIX7abc...",
  transaction_ids: ["trx123...", "trx456..."],
  transactions: [
    {
      ref_block_num: 12345,
      ref_block_prefix: 987654321,
      expiration: "2024-01-15T12:31:00",
      operations: [
        ["vote", { voter: "alice", author: "bob", permlink: "post", weight: 10000 }]
      ],
      extensions: [],
      signatures: ["1f5b3c..."]
    }
  ]
}

Use Cases:

  • Analyze block contents
  • Process historical data
  • Verify transactions
// Process all transfers in a block
const block = await client.database.getBlock(12345678);

for (const tx of block.transactions) {
  for (const op of tx.operations) {
    const [opType, opData] = op;
    if (opType === "transfer") {
      console.log(`${opData.from} → ${opData.to}: ${opData.amount}`);
    }
  }
}

getOperations(blockNum, onlyVirtual?)

Returns all operations from a block, including virtual operations.

Parameters:

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | blockNum | number | - | Block number | | onlyVirtual | boolean | false | Return only virtual operations |

Returns: Promise<AppliedOperation[]>

// Get all operations
const allOps = await client.database.getOperations(12345678);

// Get only virtual operations (rewards, etc.)
const virtualOps = await client.database.getOperations(12345678, true);
[
  {
    trx_id: "abc123...",
    block: 12345678,
    trx_in_block: 0,
    op_in_trx: 0,
    virtual_op: 0,
    timestamp: "2024-01-15T12:30:00",
    op: ["vote", { voter: "alice", author: "bob", permlink: "post", weight: 10000 }]
  },
  {
    trx_id: "0000000000000000000000000000000000000000",
    block: 12345678,
    trx_in_block: 65535,
    op_in_trx: 0,
    virtual_op: 1,
    timestamp: "2024-01-15T12:30:00",
    op: ["curation_reward", { curator: "alice", reward: "1.234567 VESTS", ... }]
  }
]

getAccounts(usernames)

Returns detailed information for multiple accounts.

Parameters:

| Parameter | Type | Description | |-----------|------|-------------| | usernames | string[] | Array of account names (max 1000) |

Returns: Promise<ExtendedAccount[]>

const accounts = await client.database.getAccounts(["alice", "bob", "charlie"]);
[
  {
    id: 12345,
    name: "alice",
    owner: {
      weight_threshold: 1,
      account_auths: [],
      key_auths: [["PIX7abc...", 1]]
    },
    active: { /* similar structure */ },
    posting: { /* similar structure */ },
    memo_key: "PIX7xyz...",
    json_metadata: "{\"profile\":{\"name\":\"Alice\"}}",
    posting_json_metadata: "{\"profile\":{\"about\":\"Hello!\"}}",
    proxy: "",
    
    balance: "100.000 PIXA",
    savings_balance: "50.000 PIXA",
    pxs_balance: "25.000 PXS",
    savings_pxs_balance: "10.000 PXS",
    
    vesting_shares: "1000000.000000 VESTS",
    delegated_vesting_shares: "100000.000000 VESTS",
    received_vesting_shares: "50000.000000 VESTS",
    vesting_withdraw_rate: "0.000000 VESTS",
    
    reward_pixa_balance: "1.000 PIXA",
    reward_pxs_balance: "0.500 PXS",
    reward_vesting_balance: "100.000000 VESTS",
    reward_vesting_pixa: "0.050 PIXA",
    
    voting_power: 9800,  // 98%
    voting_manabar: {
      current_mana: "950000000000",
      last_update_time: 1705320600
    },
    
    post_count: 150,
    created: "2020-01-01T00:00:00",
    last_post: "2024-01-14T10:00:00",
    last_vote_time: "2024-01-15T12:00:00",
    
    curation_rewards: 50000,
    posting_rewards: 100000,
    
    witnesses_voted_for: 30
  }
]

Use Cases:

  • Display user profiles
  • Check balances
  • Verify account authority
// Get account and display formatted info
const [account] = await client.database.getAccounts(["alice"]);

if (account) {
  console.log(`@${account.name}`);
  console.log(`Balance: ${account.balance}`);
  console.log(`Pixa Power: ${account.vesting_shares}`);
  console.log(`Voting Power: ${(account.voting_power / 100).toFixed(2)}%`);
  console.log(`Posts: ${account.post_count}`);
  
  // Parse profile metadata
  try {
    const meta = JSON.parse(account.posting_json_metadata || account.json_metadata);
    if (meta.profile) {
      console.log(`Name: ${meta.profile.name || 'N/A'}`);
      console.log(`About: ${meta.profile.about || 'N/A'}`);
    }
  } catch (e) {
    // Invalid JSON metadata
  }
} else {
  console.log("Account not found");
}

getDiscussions(by, query)

Returns an array of posts/discussions based on sorting method.

Parameters:

| Parameter | Type | Description | |-----------|------|-------------| | by | DiscussionQueryCategory | Sorting method | | query | DisqussionQuery | Query parameters |

Returns: Promise<Discussion[]>

Query Parameters:

| Field | Type | Required | Description | |-------|------|----------|-------------| | tag | string | No | Tag name, or username for blog/feed | | limit | number | Yes | Results to return (max 100) | | filter_tags | string[] | No | Tags to exclude | | select_authors | string[] | No | Only include these authors | | select_tags | string[] | No | Only include these tags | | truncate_body | number | No | Truncate body to N bytes (0 = all) | | start_author | string | No | Pagination: start from this author | | start_permlink | string | No | Pagination: start from this permlink | | parent_author | string | No | Filter by parent author | | parent_permlink | string | No | Filter by parent permlink |

// Get trending posts in a tag
const trending = await client.database.getDiscussions("trending", {
  tag: "photography",
  limit: 20
});

// Get posts from a user's blog
const blog = await client.database.getDiscussions("blog", {
  tag: "alice",  // For 'blog', tag = username
  limit: 10
});

// Get a user's feed (posts from people they follow)
const feed = await client.database.getDiscussions("feed", {
  tag: "alice",
  limit: 10
});

// Pagination
const page1 = await client.database.getDiscussions("trending", {
  tag: "art",
  limit: 20
});

const page2 = await client.database.getDiscussions("trending", {
  tag: "art",
  limit: 20,
  start_author: page1[page1.length - 1].author,
  start_permlink: page1[page1.length - 1].permlink
});

| Category | Description | Tag Usage | |----------|-------------|-----------| | trending | Posts sorted by trending algorithm | Tag name | | hot | Hot posts (recent + popular) | Tag name | | created | Newest posts first | Tag name | | promoted | Promoted posts (by spent PXS) | Tag name | | active | Recently active (new comments) | Tag name | | blog | Posts from user's blog | Username | | feed | Posts from followed accounts | Username | | comments | Comments by an author | Username | | votes | Posts sorted by vote count | Tag name | | children | Posts sorted by comment count | Tag name | | cashout | Posts approaching payout | Tag name |

[
  {
    id: 123456,
    author: "alice",
    permlink: "my-awesome-post",
    category: "photography",
    parent_author: "",
    parent_permlink: "photography",
    
    title: "My Awesome Photography Post",
    body: "Here is my post content with **markdown**...",
    json_metadata: "{\"tags\":[\"photography\",\"nature\"],\"image\":[\"https://...\"]}",
    
    created: "2024-01-14T10:00:00",
    last_update: "2024-01-14T10:00:00",
    depth: 0,
    children: 15,
    
    net_rshares: "50000000000000",
    net_votes: 42,
    
    total_payout_value: "0.000 PXS",
    curator_payout_value: "0.000 PXS",
    pending_payout_value: "12.500 PXS",
    
    active_votes: [
      { voter: "bob", weight: 10000, rshares: "1000000000", time: "2024-01-14T10:05:00" }
    ],
    
    author_reputation: 65000000000000,
    
    url: "/photography/@alice/my-awesome-post",
    root_title: "My Awesome Photography Post",
    
    beneficiaries: [],
    max_accepted_payout: "1000000.000 PXS",
    percent_pxs: 10000,
    allow_votes: true,
    allow_curation_rewards: true
  }
]

getTransaction(txId)

Returns a transaction by its ID.

Parameters:

| Parameter | Type | Description | |-----------|------|-------------| | txId | string | Transaction ID (40-char hex string) |

Returns: Promise<SignedTransaction>

const tx = await client.database.getTransaction("abc123def456...");
{
  ref_block_num: 12345,
  ref_block_prefix: 987654321,
  expiration: "2024-01-15T12:31:00",
  operations: [
    ["transfer", {
      from: "alice",
      to: "bob",
      amount: "10.000 PIXA",
      memo: "Payment"
    }]
  ],
  extensions: [],
  signatures: ["1f4a2b3c..."]
}

getAccountHistory(account, from, limit, operation_bitmask?)

Returns account operation history.

Parameters:

| Parameter | Type | Description | |-----------|------|-------------| | account | string | Account name | | from | number | Start index (-1 for most recent) | | limit | number | Number of operations (max 1000) | | operation_bitmask | [number, number] | Optional: filter by operation types |

Returns: Promise<[[number, AppliedOperation]]>

// Get last 100 operations
const history = await client.database.getAccountHistory("alice", -1, 100);

// Process results (returns [index, operation] pairs)
for (const [index, op] of history) {
  console.log(`#${index}: ${op.op[0]} at block ${op.block}`);
}

Filtering by Operation Type:

import { utils } from "@pixagram/dpixa";

const op = utils.operationOrders;

// Create filter for transfer-related operations
const transferFilter = utils.makeBitMaskFilter([
  op.transfer,
  op.transfer_to_vesting,
  op.transfer_to_savings,
  op.transfer_from_savings,
  op.claim_reward_balance
]);

const transfers = await client.database.getAccountHistory(
  "alice",
  -1,
  100,
  transferFilter
);

// Process only transfer operations
for (const [index, operation] of transfers) {
  const [opType, opData] = operation.op;
  console.log(`${opType}: ${JSON.stringify(opData)}`);
}
[
  [
    12345,  // Operation index
    {
      trx_id: "abc123...",
      block: 12345678,
      trx_in_block: 5,
      op_in_trx: 0,
      virtual_op: 0,
      timestamp: "2024-01-15T12:30:00",
      op: ["transfer", {
        from: "alice",
        to: "bob",
        amount: "10.000 PIXA",
        memo: "Payment"
      }]
    }
  ]
]

getVestingDelegations(account, from?, limit?)

Returns vesting delegations made by an account.

Parameters:

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | account | string | - | Delegator account name | | from | string | "" | Start from delegatee (for pagination) | | limit | number | 1000 | Max results (max 1000) |

Returns: Promise<VestingDelegation[]>

const delegations = await client.database.getVestingDelegations("alice", "", 100);

for (const d of delegations) {
  console.log(`Delegating ${d.vesting_shares} to @${d.delegatee}`);
}
[
  {
    id: 12345,
    delegator: "alice",
    delegatee: "bob",
    vesting_shares: "100000.000000 VESTS",
    min_delegation_time: "2024-01-20T12:00:00"
  },
  {
    id: 12346,
    delegator: "alice",
    delegatee: "charlie",
    vesting_shares: "50000.000000 VESTS",
    min_delegation_time: "2024-01-22T08:00:00"
  }
]

verifyAuthority(signedTransaction)

Verifies that a signed transaction has valid signatures.

Parameters:

| Parameter | Type | Description | |-----------|------|-------------| | signedTransaction | SignedTransaction | Transaction with signatures |

Returns: Promise<boolean>

const isValid = await client.database.verifyAuthority(signedTx);
console.log(`Transaction is ${isValid ? "valid" : "invalid"}`);

getVersion()

Returns the version information of the RPC node.

Returns: Promise<{blockchain_version: string, pixa_revision: string, fc_revision: string}>

const version = await client.database.getVersion();
console.log(`Node version: ${version.blockchain_version}`);

Blockchain

The Blockchain helper provides streaming capabilities for real-time blockchain data.


getCurrentBlockNum(mode?)

Returns the current block number.

Parameters:

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | mode | BlockchainMode | Irreversible | Block finality mode |

Returns: Promise<number>

import { BlockchainMode } from "@pixagram/dpixa";

// Get last irreversible block (confirmed, won't change)
const irreversible = await client.blockchain.getCurrentBlockNum();

// Get head block (may be reversed in case of fork)
const head = await client.blockchain.getCurrentBlockNum(BlockchainMode.Latest);

console.log(`Irreversible: ${irreversible}, Head: ${head}`);

getCurrentBlockHeader(mode?)

Returns the current block header.

Returns: Promise<BlockHeader>

const header = await client.blockchain.getCurrentBlockHeader();
console.log(`Current witness: ${header.witness}`);

getCurrentBlock(mode?)

Returns the current full block.

Returns: Promise<SignedBlock>

const block = await client.blockchain.getCurrentBlock();
console.log(`Block has ${block.transactions.length} transactions`);

getBlockNumbers(options?)

Returns an async iterator of block numbers.

Parameters:

| Option | Type | Description | |--------|------|-------------| | from | number | Starting block (default: current) | | to | number | Ending block (default: infinite) | | mode | BlockchainMode | Finality mode |

Returns: AsyncGenerator<number>

// Stream new block numbers indefinitely
for await (const num of client.blockchain.getBlockNumbers()) {
  console.log(`New block: ${num}`);
}

// Process specific range
for await (const num of client.blockchain.getBlockNumbers({ 
  from: 50000000, 
  to: 50000100 
})) {
  console.log(`Processing block ${num}`);
}

// Get latest blocks (may include reversible)
for await (const num of client.blockchain.getBlockNumbers({
  mode: BlockchainMode.Latest
})) {
  console.log(`Head block: ${num}`);
}

getBlocks(options?)

Returns an async iterator of full blocks.

Returns: AsyncGenerator<SignedBlock>

// Stream all new blocks
for await (const block of client.blockchain.getBlocks()) {
  console.log(`Block #${block.block_id} by @${block.witness}`);
  console.log(`  Transactions: ${block.transactions.length}`);
  
  // Process each transaction
  for (const tx of block.transactions) {
    for (const [opType, opData] of tx.operations) {
      // Handle operations
    }
  }
}

// Start from specific block
for await (const block of client.blockchain.getBlocks({ from: 50000000 })) {
  // Process historical blocks
  if (block.block_id === "target") break;
}

getOperations(options?)

Returns an async iterator of all operations (including virtual).

Returns: AsyncGenerator<AppliedOperation>

// Stream all operations
for await (const appliedOp of client.blockchain.getOperations()) {
  const [opType, opData] = appliedOp.op;
  
  switch (opType) {
    case "transfer":
      console.log(`Transfer: ${opData.from} → ${opData.to}: ${opData.amount}`);
      break;
    case "vote":
      const voteType = opData.weight > 0 ? "upvote" : opData.weight < 0 ? "downvote" : "unvote";
      console.log(`Vote: ${opData.voter} ${voteType} @${opData.author}/${opData.permlink}`);
      break;
    case "curation_reward":  // Virtual operation
      console.log(`Curation reward: ${opData.curator} earned ${opData.reward}`);
      break;
  }
}

Stream Methods (Node.js Streams)

Convert iterators to Node.js readable streams.

Returns: ReadableStream

// Block number stream
const numStream = client.blockchain.getBlockNumberStream();

// Block stream
const blockStream = client.blockchain.getBlockStream();

// Operations stream
const opStream = client.blockchain.getOperationsStream();

// Use with pipes
const es = require("event-stream");

blockStream
  .pipe(es.map((block, cb) => {
    cb(null, `Block ${block.block_id}\n`);
  }))
  .pipe(process.stdout);

Broadcast API

The broadcast API sends transactions to the blockchain and returns a TransactionConfirmation.

{
  id: "trx123abc...",     // Transaction ID
  block_num: 12345678,    // Block number where included
  trx_num: 5,             // Transaction index in block
  expired: false          // Whether transaction expired
}

Voting on Content

import { Client, PrivateKey } from "@pixagram/dpixa";

const client = new Client(["https://api.pixagram.io"]);
const postingKey = PrivateKey.fromLogin("myuser", "mypassword", "posting");

// Upvote 100%
const result = await client.broadcast.vote({
  voter: "myuser",
  author: "post-author",
  permlink: "post-permlink",
  weight: 10000  // 100% = 10000
}, postingKey);

console.log(`Vote included in block ${result.block_num}`);

Vote Weight Guide:

| Weight | Meaning | |--------|---------| | 10000 | 100% upvote | | 5000 | 50% upvote | | 0 | Remove vote | | -5000 | 50% downvote | | -10000 | 100% downvote |


Transferring Funds

const activeKey = PrivateKey.fromLogin("myuser", "mypassword", "active");

// Transfer PIXA
await client.broadcast.transfer({
  from: "myuser",
  to: "recipient",
  amount: "10.000 PIXA",
  memo: "Here's your payment!"
}, activeKey);

// Transfer PXS
await client.broadcast.transfer({
  from: "myuser",
  to: "recipient",
  amount: "5.000 PXS",
  memo: "PXS transfer"
}, activeKey);

// Encrypted memo (starts with #)
const memoKey = PrivateKey.fromLogin("myuser", "mypassword", "memo");
const recipientMemoKey = "PIX7abc..."; // Get from recipient's account

const encryptedMemo = Memo.encode(memoKey, recipientMemoKey, "Secret message");

await client.broadcast.transfer({
  from: "myuser",
  to: "recipient",
  amount: "1.000 PIXA",
  memo: encryptedMemo  // "#encoded..."
}, activeKey);

Creating Posts and Comments

const postingKey = PrivateKey.fromLogin("myuser", "mypassword", "posting");

// Create a new post
await client.broadcast.comment({
  parent_author: "",              // Empty for root posts
  parent_permlink: "photography", // Category/tag
  author: "myuser",
  permlink: "my-first-photo-post",
  title: "My First Photography Post",
  body: `
# Hello World!

This is my first post with **markdown** support.

![My Photo](https://example.com/photo.jpg)
  `,
  json_metadata: JSON.stringify({
    tags: ["photography", "nature", "introduction"],
    image: ["https://example.com/photo.jpg"],
    app: "myapp/1.0",
    format: "markdown"
  })
}, postingKey);

// Reply to a post
await client.broadcast.comment({
  parent_author: "originalauthor",
  parent_permlink: "original-post",
  author: "myuser",
  permlink: "re-originalauthor-original-post-20240115",
  title: "",  // Replies typically have no title
  body: "Great post! Thanks for sharing this.",
  json_metadata: JSON.stringify({
    tags: ["photography"],
    app: "myapp/1.0"
  })
}, postingKey);

Custom JSON Operations

// Follow a user
await client.broadcast.customJson({
  required_auths: [],
  required_posting_auths: ["myuser"],
  id: "follow",
  json: JSON.stringify([
    "follow",
    {
      follower: "myuser",
      following: "targetuser",
      what: ["blog"]  // ["blog"] to follow, [] to unfollow
    }
  ])
}, postingKey);

// Reblog/Resteem a post
await client.broadcast.customJson({
  required_auths: [],
  required_posting_auths: ["myuser"],
  id: "follow",
  json: