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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@tgrospic/rnode-grpc-js

v0.11.0

Published

RNode gRPC helpers

Downloads

107

Readme

RNode gRPC API generator

This library helps to generate JavaScript bindings for RNode gRPC API.

Examples of how to use it with Nodejs and in the browser are in @tgrospic/rnode-client-js repository.

RNode also exposes HTTP natively with RNode Web API, for more information see @tgrospic/rnode-http-js.

Deploys sent via Web API still have to be serialized with protobuf, but it's not necessary to use this library and generate any JS code. rnode-sign.ts can be used independently in your web project.

gRPC is not supported in the browser but it can be used with the proxy. Here is the example of Envoy configuration to run your own HTTP/gRPC proxy.

It contains two parts:

  • rnode-grpc CLI to generate JS files with TypeScript definitions
  • helper functions to create JS client with Promise based RNode service methods.

Install

npm install @tgrospic/rnode-grpc-js

# gRPC and protobuf for use with Nodejs
# - compatible with native `grpc` package
npm install google-protobuf @grpc/grpc-js
# Or for use in the browser (via Envoy proxy)
npm install google-protobuf grpc-web

# For crypto operations (create private key)
npm install elliptic

Install peer dependencies needed to generate JS files from proto definitions.

npm install --save-dev grpc-tools protobufjs

Generate JS files

The purpose of rnode-grpc CLI command is to download and generate necessary files.

# Generate all files with default options (run from your package.json scripts)
rnode-grpc

# Generate with specific options
rnode-grpc --rnode-version v0.12.4 --gen-dir ./rnode-grpc-gen

# Run from your project folder
node_modules/.bin/rnode-grpc

CLI options

| Option | Default | Description | -------------------| ------------------ | ------------ | --rnode-version | v0.12.4 | Version (repo tag) of RNode to generate API. | --gen-dir | ./rnode-grpc-gen | Path to output directory.

We can generate API from not yet published RNode version. From any branch on rchain/rchain repo, e.g. dev branch.

rnode-grpc --rnode-version dev

And make requests to new DeployService method isFinalized. :smile:

interface DeployService {
  // Not yet available in v0.9.12 RNode
  isFinalized(_?: IsFinalizedQuery): Promise<IsFinalizedResponse>
  // ...existing methods
}

API

Complete API is combined from the part provided by the library and the generated part for a specific version of RNode.

Documentation for library part can be found here https://tgrospic.github.io/rnode-grpc-js/ and generated part with TypeScript definitions can be found in a directory specified by --gen-dir option.

More info for client options for @grpc/grpc-js and grpc-web.

interface Options {
  // gRPC protocol implementation
  // - `@grpc/grpc-js` for Nodejs
  // - `grpc-web` for browser
  grpcLib: any
  // Custom options for gRPC clients
  // - `credentials` can be supplied as part of `clientOptions` for `grpc-js`
  clientOptions?: any,
  // RNode host (method prefix)
  host: string,
  // Generated JSON schema
  protoSchema: Object
}

// Get deploy service methods
rnodeDeploy(opt: Options): DeployService

// Get propose service methods
rnodePropose(opt: Options): ProposeService

// Get repl service methods
rnodeRepl(opt: Options): Repl

// Get all service methods
rnodeService(opt: Options): DeployService & ProposeService & Repl

// Sign deploy data
signDeploy(key: string | Uint8Array | Buffer | ec.KeyPair, deploy: UnsignedDeployData): DeployDataProto

// Verify deploy signature
verifyDeploy(deploy: DeployDataProto): Boolean

// Protobuf serialize / deserialize operations
rnodeProtobuf({protoSchema}): TypesBinary

// Transform Par type to JSON (with meaningful defaults)
rhoParToJson(input: Par): any

TypeScript definitions

Here is an example of TypeScript definition file generated for v0.12.4 version of RNode.

# Run CLI command with an option to specify RNode version (Git repo release tag)
rnode-grpc --rnode-version v0.12.4

Generated TypeScript definitions are complete with the conversion of response errors inside the message to Promise errors. For RNode after v0.9.14 version ServiceError type is converted and on previous versions the same conversion is done on a dynamic Either type. :smile:

// Typescipt generated interface from RNode v0.12.4 protbuf definitions
interface DeployService {
  doDeploy(_?: DeployDataProto): Promise<DeployResponse>
  getBlock(_?: BlockQuery): Promise<BlockResponse>
  visualizeDag(_?: VisualizeDagQuery): Promise<VisualizeBlocksResponse[]>
  machineVerifiableDag(_?: MachineVerifyQuery): Promise<MachineVerifyResponse>
  showMainChain(_?: BlocksQuery): Promise<BlockInfoResponse[]>
  getBlocks(_?: BlocksQuery): Promise<BlockInfoResponse[]>
  listenForDataAtName(_: DataAtNameQuery): Promise<ListeningNameDataResponse>
  listenForContinuationAtName(_: ContinuationAtNameQuery): Promise<ContinuationAtNameResponse>
  findDeploy(_?: FindDeployQuery): Promise<FindDeployResponse>
  previewPrivateNames(_?: PrivateNamePreviewQuery): Promise<PrivateNamePreviewResponse>
  lastFinalizedBlock(_?: LastFinalizedBlockQuery): Promise<LastFinalizedBlockResponse>
  isFinalized(_?: IsFinalizedQuery): Promise<IsFinalizedResponse>
  bondStatus(_?: BondStatusQuery): Promise<BondStatusResponse>
  exploratoryDeploy(_?: ExploratoryDeployQuery): Promise<ExploratoryDeployResponse>
  getBlocksByHeights(_?: BlocksQueryByHeight): Promise<BlockInfoResponse[]>
  getEventByHash(_?: ReportQuery): Promise<EventInfoResponse>
}

Sample code for gRPC requests to RNode

NOTE: RNode also exposes HTTP natively with RNode Web API, for more information see @tgrospic/rnode-http-js.

Using gRPC in the browser is not supported but it's possible with gRPC-HTTP proxy and grpc-web library.

Working version of these examples can be found in @tgrospic/rnode-client-js/src/nodejs.

/// <reference path="../rnode-grpc-gen/js/rnode-grpc-js.d.ts" />
import grpcLib from '@grpc/grpc-js'
// import grpcLib from 'grpc-web' // when using gRPC-HTTP proxy
import { ec } from 'elliptic'
import { rnodeDeploy, rnodePropose, signDeploy, verifyDeploy, LightBlockInfo } from '@tgrospic/rnode-grpc-js'

// Generated files with rnode-grpc-js tool
import protoSchema from '../rnode-grpc-gen/js/pbjs_generated.json'
// Import generated protobuf types (in global scope)
import '../rnode-grpc-gen/js/DeployServiceV1_pb'
import '../rnode-grpc-gen/js/ProposeServiceV1_pb'

// RNode validator address (or any read-only RNode if we don't use _deploy_ and _propose_)
const rnodeExternalUrl = 'node2.testnet.rchain.coop:40401'
// const rnodeInternalUrl = 'localhost:40402'
// const rnodeExternalUrl = 'https://<host>:<port>' // when using gRPC-HTTP proxy

// gRPC client options
const options = { grpcLib: grpcLib, host: rnodeExternalUrl, protoSchema }

// Get RNode service methods
const { getBlocks, DoDeploy } = rnodeDeploy(options)
const { propose }             = rnodePropose(options)

// Get blocks from RNode
const blocks: LightBlockInfo[] = await getBlocks({ depth: 2 })

// Generate sample KeyPair (private/public keys) to sign the deploy
const secp256k1 = new ec('secp256k1')
const key = secp256k1.genKeyPair()
// Or use existing as hex string or Uint8Array
// const key = '1bf36a3d89c27ddef7955684b97667c75454317d8964528e57b2308947b250b0'

// Sample Rholang code we want to deploy
const deployData = {
  term: 'new out(`rho:io:stdout`) in { out!("Browser deploy test") }',
  timestamp: Date.now(),      // nonce
  phloprice: 1,               // price of tinny REV for phlogiston (gas)
  phlolimit: 10e3,            // max phlogiston (gas) for deploy execution
  validafterblocknumber: 123, // latest block number
}

// Helper function to sign a deploy
// - this can be done when offline and save the signed deploy as JSON
const deploy = signDeploy(key, deployData)

// and to check the signature
const isValidDeploy = verifyDeploy(deploy)

// Send signed deploy to RNode
const { message } = await DoDeploy(deploy)

// Propose deploys to the rest of the network
// - this is done by the validator and allowed only on internal (private) port
await propose()

// Get result from deploy (after deploy is added to a block)
const { payload: { blockinfoList } } = await listenForDataAtName({
  depth: 1,
  name: { unforgeablesList: [{gDeployIdBody: { sig: deploy.sig }}] },
})

Protobuf serialize and deserialize operations

The small wrapper rnodeProtobuf allows easier access to protobuf generated types and serialize/deserialize operations.

/// <reference path="../rnode-grpc-gen/js/rnode-grpc-js.d.ts" />
// Generated protobuf files must be loaded to instantiate a global proto object
// needed for `rnodeProtobuf`
require('../rnode-grpc-gen/js/DeployServiceV1_pb')
require('../rnode-grpc-gen/js/ProposeServiceV1_pb')
require('../rnode-grpc-gen/js/repl_pb')
const protoSchema = require('../rnode-grpc-gen/js/pbjs_generated.json')

const { rnodeProtobuf } = require('@tgrospic/rnode-grpc-js')

// Get types with serialize and deserialize operations
const { DeployDataProto, CmdRequest } = rnodeProtobuf({ protoSchema })

const deployBytes = DeployDataProto.serialize({ term: 'Nil', phlolimit: 1000 })

const deployObj: DeployDataProto = DeployDataProto.deserialize(deployBytes)

What is the difference with RChain-API?

The main difference is that this library does not depend on any specific version of RNode nor the schema definition (with minor caveats). RNode version is an input parameter and the goal is to generate JS and TS code for any RNode version.

Example for Node.js (with web)

Sample static site to test requests from the browser https://tgrospic.github.io/rnode-client-js. It's published as part of the example repository @tgrospic/rnode-client-js. It also contains protobuf/gRPC examples for Node.js.