GithubHelp home page GithubHelp logo

tgrospic / rnode-grpc-js Goto Github PK

View Code? Open in Web Editor NEW
9.0 4.0 6.0 870 KB

RNode gRPC/HTTP API generator for Nodejs and the browser

Home Page: https://tgrospic.github.io/rnode-grpc-js/

License: MIT License

JavaScript 32.55% TypeScript 67.45%
rchain rnode client grpc testnet api typescript generator rnode-grpc

rnode-grpc-js's Introduction

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.
Additional use for RNode version option

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. ๐Ÿ˜„

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. ๐Ÿ˜„

// 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.

rnode-grpc-js's People

Contributors

dependabot[bot] avatar tgrospic avatar zsluedem avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

rnode-grpc-js's Issues

not found grpc_tools_node_protoc

$ ./node_modules/.bin/rnode-grpc --rnode-version dev
RNode gRPC versions { 'rnode-version': 'dev', 'grpc-web-version': '1.0.6' }
Startinmg downloads...
Downloading https://github.com/grpc/grpc-web/releases/download/1.0.6/protoc-gen-grpc-web-1.0.6-darwin-x86_64
Downloading https://raw.githubusercontent.com/rchain/rchain/dev/models/src/main/protobuf/CasperMessage.proto
Downloading https://raw.githubusercontent.com/rchain/rchain/dev/models/src/main/protobuf/DeployServiceCommon.proto
Downloading https://raw.githubusercontent.com/rchain/rchain/dev/models/src/main/protobuf/DeployServiceV1.proto
Downloading https://raw.githubusercontent.com/rchain/rchain/dev/models/src/main/protobuf/ProposeServiceCommon.proto
Downloading https://raw.githubusercontent.com/rchain/rchain/dev/models/src/main/protobuf/ProposeServiceV1.proto
Downloading https://raw.githubusercontent.com/rchain/rchain/dev/models/src/main/protobuf/RhoTypes.proto
Downloading https://raw.githubusercontent.com/rchain/rchain/dev/models/src/main/protobuf/ServiceError.proto
Downloading https://raw.githubusercontent.com/rchain/rchain/dev/node/src/main/protobuf/repl.proto
Downloading https://raw.githubusercontent.com/scalapb/ScalaPB/master/protobuf/scalapb/scalapb.proto
Generating JS files...
(node:49188) UnhandledPromiseRejectionWarning: Error: not found: grpc_tools_node_protoc
    at getNotFoundError (/Users/willqiu/work/pull/playq/node_modules/which/which.js:13:12)
    at F (/Users/willqiu/work/pull/playq/node_modules/which/which.js:68:19)
    at E (/Users/willqiu/work/pull/playq/node_modules/which/which.js:80:29)
    at /Users/willqiu/work/pull/playq/node_modules/which/which.js:89:16
    at /Users/willqiu/work/pull/playq/node_modules/isexe/index.js:42:5
    at /Users/willqiu/work/pull/playq/node_modules/isexe/mode.js:8:5
    at FSReqCallback.oncomplete (fs.js:158:21)
(node:49188) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:49188) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Method not found: /casper.v1.DeployService/doDeploy

Uncaught (in promise) 
Object
code: 12
message: "Method not found: /casper.v1.DeployService/doDeploy"
metadata:
content-length: "0"
content-type: "application/grpc-web+proto"
grpc-message: "Method not found: /casper.v1.DeployService/doDeploy"
grpc-status: "12"
__proto__: Object
__proto__: Object

When I do deploy, I got this error.

UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED

$ node_modules/.bin/rnode-grpc
RNode gRPC versions { 'rnode-version': 'v0.9.12' }
Startinmg downloads...
Downloading https://raw.githubusercontent.com/rchain/rchain/v0.9.12/models/src/main/protobuf/CasperMessage.proto
Downloading https://raw.githubusercontent.com/rchain/rchain/v0.9.12/models/src/main/protobuf/DeployService.proto
Downloading https://raw.githubusercontent.com/rchain/rchain/v0.9.12/models/src/main/protobuf/Either.proto
Downloading https://raw.githubusercontent.com/rchain/rchain/v0.9.12/models/src/main/protobuf/ProposeService.proto
Downloading https://raw.githubusercontent.com/rchain/rchain/v0.9.12/models/src/main/protobuf/RhoTypes.proto
Downloading https://raw.githubusercontent.com/rchain/rchain/v0.9.12/node/src/main/protobuf/repl.proto
Downloading https://raw.githubusercontent.com/scalapb/ScalaPB/master/protobuf/scalapb/scalapb.proto
(node:9889) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 151.101.0.133:443
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1126:14)
(node:9889) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:9889) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I have trouble installing on my MAC. But it's OK on ubuntu servers.

verifyRevAddr on illegal addree would return undefine

reproduce codes

const { verifyRevAddr } = require("@tgrospic/rnode-grpc-js");
verifyRevAddr("1111engqbx5d85yltnx6btfbl8429sxtqytflsj7jcn2qcn192vM8")

"1111engqbx5d85yltnx6btfbl8429sxtqytflsj7jcn2qcn192vM8" is not a valid Base58 from pyrchain

package generated protobuf code

It would be really handy to be able to just npm install rchain-probuf and get the stuff generated files with the rnode-grpc-js tool.

Package versions could correspond to rnode versions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.