SkillAgentSearch skills...

Factomjs

Javascript library to build applications on the Factom blockchain.

Install / Use

/learn @PaulBernier/Factomjs
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Factom.js

npm version Build Status Coverage Status Known Vulnerabilities

Factom.js is a library to easily build applications on the Factom blockchain.

  • Provides higher level functionalities than factomd API making it a breeze to create chains or entries, send transactions...
  • Provides uniform, consistent and easy to use Factom data structures.
  • Provides a range of util functions to manipulate Factom addresses.

Installation

$ npm install --save factom

Documentation and changelog

The complete documentation of the library is available in Markdown format in the docs directory or online in web format at https://factomjs.luciap.ca.

A changelog is available in the file changelog.md.

Web browser

Two versions of factom.js are being bundled for usage in a web browser and can be found in the dist folder. dist/factom.js is a bundle containing all the exposed components of the library. dist/factom-struct.js is a lighter bundle that contains factom structures such as Entry, Chain and Transaction, and all the utily functions related to FCT/EC addresses and fundamental constants. factom-struct bundle doesn't include any component that makes API calls.

import { isValidPrivateAddress, isValidPrivateEcAddress } from 'factom/dist/factom-struct';
import { FactomCli } from 'factom/dist/factom';

Usage

We recommend you have a look at the tutorial on the developer portal of the Factom protocol.

Important: please note than whenever a private (Entry Credit or Factoid) address is needed in this library (typically for signing data), you can either provide a private address or a public address as an argument. If you provide a public address the library will attempt to retrieve the corresponding private address from the wallet. Thus providing private address as arguments allow you to not have to run walletd.

Instantiate FactomCli

const { FactomCli } = require('factom');

// Default factomd connection to localhost:8088
// and walletd connection to localhost:8089
const cli = new FactomCli();

// You can override factomd connection parameters and retry strategy
const cli = new FactomCli({
    host: '52.202.51.228',
    port: 8088,
    path: '/v2', // Path to V2 API. Default to /v2
    debugPath: '/debug', // Path to debug API. Default to /debug
    user: 'paul', // RPC basic authentication
    password: 'pwd',
    protocol: 'http', // http or https. Default to http
    rejectUnauthorized: true, // Set to false to allow connection to a node with a self-signed certificate
    timeout: 5000, // Timeout of individual requests
    retry: {
        retries: 3,
        factor: 2,
        minTimeout: 500,
        maxTimeout: 2000,
    },
});

// You can also override both factomd and walletd options
const cli = new FactomCli({
    factomd: {
        host: '52.202.51.228',
        port: 8088,
    },
    walletd: {
        host: '52.202.51.228',
        port: 8089,
    },
});

Chains and Entries

Add a Chain

const { Entry, Chain } = require('factom');
const firstEntry = Entry.builder()
    .extId('6d79206578742069642031') // If no encoding parameter is passed as 2nd argument, 'hex' is used
    .extId('my ext id 1', 'utf8') // Explicit the encoding. Or you can pass directly a Buffer
    .content('Initial content', 'utf8')
    .build();

const chain = new Chain(firstEntry);
cli.add(chain, 'Es32PjobTxPTd73dohEFRegMFRLv3X5WZ4FXEwNN8kE2pMDfeMym');

Add an entry

const { Entry } = require('factom');
const myEntry = Entry.builder()
    .chainId('9107a308f91fd7962fecb321fdadeb37e2ca7d456f1d99d24280136c0afd55f2')
    .extId('6d79206578742069642031') // If no encoding parameter is passed as 2nd argument, 'hex' is used
    .extId('some external ID', 'utf8')
    .content('My new content', 'utf8')
    .build();
cli.add(myEntry, 'Es32PjobTxPTd73dohEFRegMFRLv3X5WZ4FXEwNN8kE2pMDfeMym');
// Add multiples entries.
// The library will limit the number of concurrent Promises to 200 by default to avoid overwhelming the factomd instance.
cli.add([entry1, entry2], 'Es32PjobTxPTd73dohEFRegMFRLv3X5WZ4FXEwNN8kE2pMDfeMym');

// The concurrency limit can be customized.
cli.add([entry1, entry2], 'Es32PjobTxPTd73dohEFRegMFRLv3X5WZ4FXEwNN8kE2pMDfeMym', {
    concurrency: 1,
});

Commit/reveal acknowledgment when submitting chains or entries

Factom protocol uses a commit/reveal commitment scheme. By default when using add the library will sequentially wait for an acknowledgment (ack) of the commit by the network and then wait for the ack of the reveal, both for up to 60s. The library allows you to customize the timeouts of those acks and also to not wait for the acks at all when creating a Chain or an Entry. Please read Factom whitepaper about commit/reveal scheme and what are the potential risks to not wait for network acknowledgments.

// Default behavior waits for both commit and reveal up to 60s
cli.add(myEntry, 'Es32PjobTxPTd73dohEFRegMFRLv3X5WZ4FXEwNN8kE2pMDfeMym');
// Change the timeout for commit ack to 120s and the timeout for reveal ack to 20s
cli.add(myEntry, 'Es32PjobTxPTd73dohEFRegMFRLv3X5WZ4FXEwNN8kE2pMDfeMym', {
    commitTimeout: 120,
    revealTimeout: 20,
});
// By providing a negative number the library will not wait for any acknowledgment.
// In below example the wait on reveal ack is disabled (it'll still wait up to 60s on the commit ack).
cli.add(myEntry, 'Es32PjobTxPTd73dohEFRegMFRLv3X5WZ4FXEwNN8kE2pMDfeMym', { revealTimeout: -1 });

Repeated commit

If you commit twice an entry or a chain and that the second time the fees paid are lower or equal to the first commit you are in a 'repeated commit' case and the second commit will be rejected (and you won't be charged for it). If this scenario happens the output of add will have the field repeatedCommit set to true and the field txId will be undefined. See Factom doc.

Getting entries and block context

The simplest and fastest way to retrieve an Entry is to query it by its hash.

cli.getEntry('caf017da212bb68ffee2ba645e1488e5834863743d50972dd3009eab2b93eb42');

You may notice that the entry returned doesn't have a timestamp populated. That's because the timestamp is actually stored in the Entry Block that contains this Entry. The library offers a convenient way to also retrieve that information:

cli.getEntryWithBlockContext('caf017da212bb68ffee2ba645e1488e5834863743d50972dd3009eab2b93eb42');

The entry returned will have its timestamp populated and an additional blockContext field that is structured as follow:

// Note that the timestamps here are in epoch seconds whereas the timestamp attribute of the Entry itself is in timestamp milliseconds
{ entryTimestamp: 1518286500,
  directoryBlockHeight: 7042,
  entryBlockTimestamp: 1518286440,
  entryBlockSequenceNumber: 1,
  entryBlockKeyMR: 'a13ac9df4153903f5a07093effe6434bdeb35fea0ff4bd402f323e486bea6ea4' }

Besides getEntryWithBlockContext entries returned by getFirstEntry and getAllEntriesOfChain also have a timestamp and blockContext populated.

Iterating entries of a chain

The FactomCli method getAllEntriesOfChain fetches all the entries of the chain before returning the result: in case of long chains in can be impractical. In some cases you may want to iterate only through a portion of the chain. For those cases FactomCli exposes the method rewindChainWhile(chainId, function predicate(entry) {}, function body(entry) {}) that iterates a chain from the most recent entry to the oldest one as long as the predicate function returns true and that the end of the chain has not been reached. At each iteration the body function is called with the current entry as its argument.

Example 1. Iterating a long chain entry by entry

await cli.rewindChainWhile('caf017da212bb68ffee2ba645e1488e5834863743d50972dd3009eab2b93eb42',
    () => true,
    entry => // Process entry

Example 2. Searching an entry in a chain

let search = true,
    found;
await cli.rewindChainWhile(
    'caf017da212bb68ffee2ba645e1488e5834863743d50972dd3009eab2b93eb42',
    () => search,
    function (entry) {
        if (entry.extId[0].toString() === 'Find me!') {
            search = false;
            found = entry;
        }
    }
);

Addresses

Factom.js offers a bunch of util functions around FCT/EC addresses and cryptographic keys, namely:

const {
    isValidAddress,
    addressToKey, // For EC, Es, Fs addresse
    addressToRcdHash, // For FA addresses
    isValidPublicAddress,
    isValidPrivateAddress,
    isValidEcAddress,
    isValidPublicEcAddress,
    isValidPrivateEcAddress,
    isValidFctAddress,
    isValidPublicFctAddress,
    isValidPrivateFctAddress,
    getPublicAddress,
    keyToPublicFctAddress,
    rcdHashToPublicFctAddress,
    seedToPrivateFctAddress,
    keyToPublicEcAddress,
    seedToPrivateEcAddress,
    generateRandomFctAddress,
    generateRandomEcAddress,
} = require('factom');

Transactions

Transaction object

Note that all the amounts are in factosh

View on GitHub
GitHub Stars22
CategoryDevelopment
Updated2y ago
Forks7

Languages

JavaScript

Security Score

80/100

Audited on Nov 29, 2023

No findings