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

revos-sdk-js

v1.0.8

Published

revos client and wallet SDK

Downloads

68

Readme

Revofi-sdk-js

GitHub license

JavaScript implementation of REVOFI client and wallet SDK. The SDK consists of a few components:

  • REVOFI Client: Send and receive data for free between any REVOFI clients regardless their network condition without setting up a server or relying on any third party services. Data are end to end encrypted by default. Typically you might want to use multiclient instead of using client directly.

  • REVOFI MultiClient: Send and receive data using multiple REVOFI clients concurrently to improve reliability and latency. In addition, it supports session mode, a reliable streaming protocol similar to TCP based on ncp.

  • REVOFI Wallet: Wallet SDK for REVOFI blockchain. It can be used to create wallet, transfer token to REVOFI wallet address, register name, subscribe to topic, etc.

Advantages of using REVOFI client/multiclient for data transmission:

  • Network agnostic: Neither sender nor receiver needs to have public IP address or port forwarding. REVOFI clients only establish outbound (websocket) connections, so Internet access is all they need. This is ideal for client side peer to peer communication.

  • Top level security: All data are end to end authenticated and encrypted. No one else in the world except sender and receiver can see or modify the content of the data. The same public key is used for both routing and encryption, eliminating the possibility of man in the middle attack.

  • Decent performance: By aggregating multiple overlay paths concurrently, multiclient can get ~100ms end to end latency and 10+mbps end to end session throughput between international devices.

  • Everything is free, open source and decentralized. (If you are curious, node relay traffic for clients for free to earn mining rewards in NKN blockchain.)

Install

For npm:

npm install revos-sdk-js

For yarn:

yarn add revos-sdk-js

And then in your code:

const nkn = require("revos-sdk-js");

or using ES6 import:

import nkn from "revos-sdk-js";

For browser, use dist/nkn.js or dist/nkn.min.js.

For environment where cryptographically secure random number generator is not natively implemented (e.g. React Native), see Random bytes generation.

Client

REVOFI client provides the basic functions of sending and receiving data between REVOFI clients or topics regardless their network condition without setting up a server or relying on any third party services. Typically you might want to use multiclient instead of using client directly.

Create a client with a generated key pair:

let client = new nkn.Client();

Or with an identifier (used to distinguish different clients sharing the same key pair):

let client = new nkn.Client({
  identifier: "any-string",
});

Get client secret seed and public key:

console.log(client.getSeed(), client.getPublicKey());

Create a client using an existing secret seed:

let client = new nkn.Client({
  seed: "2bc5501d131696429264eb7286c44a29dd44dd66834d9471bd8b0eb875a1edb0",
});

Secret key should be kept SECRET! Never put it in version control system like here.

By default the client will use bootstrap RPC server (for getting node address) provided by REVOFI. Any REVOFI full node can serve as a bootstrap RPC server. You can create a client using customized bootstrap RPC server:

let client = new nkn.Client({
  rpcServerAddr: "https://ip:port",
});

Get client REVOFI address, which is used to receive data from other clients:

console.log(client.addr);

Listen for connection established:

client.onConnect(() => {
  console.log("Client ready.");
});

Send text message to other clients:

client.send("another-client-address", "hello world!");

You can also send byte array directly:

client.send("another-client-address", Uint8Array.from([1, 2, 3, 4, 5]));

The destination address can also be a name registered using wallet.

Publish text message to all subscribers of a topic (subscribe is done through wallet):

client.publish("topic", "hello world!");

Receive data from other clients:

client.onMessage(({ src, payload }) => {
  console.log("Receive message", payload, "from", src);
});

If a valid data (string or Uint8Array) is returned at the end of the handler, the data will be sent back to sender as reply:

client.onMessage(({ src, payload }) => {
  return "Well received!";
});

Handler can also be an async function, and reply can be byte array as well:

client.onMessage(async ({ src, payload }) => {
  return Uint8Array.from([1, 2, 3, 4, 5]);
});

Note that if multiple message handlers are added, the result returned by the first handler (in the order of being added) will be sent as reply.

The send method will return a Promise that will be resolved when sender receives a reply, or rejected if not receiving reply or acknowledgement within timeout period. Similar to message, reply can be either string or byte array:

client
  .send("another-client-address", "hello world!")
  .then((reply) => {
    // The reply here can be either string or Uint8Array
    console.log("Receive reply:", reply);
  })
  .catch((e) => {
    // This will most likely to be timeout
    console.log("Catch:", e);
  });

Client receiving data will automatically send an acknowledgement back to sender if message handler returns null or undefined so that sender will be able to know if the packet has been delivered. On the sender's side, it's almost the same as receiving a reply, except that the Promise is resolved with null:

client
  .send("another-client-address", "hello world!")
  .then(() => {
    console.log("Receive ACK");
  })
  .catch((e) => {
    // This will most likely to be timeout
    console.log("Catch:", e);
  });

If handler returns false, no reply or ACK will be sent.

Check examples/client.js for complete examples.

MultiClient

MultiClient creates multiple REVOFI client instances by adding identifier prefix (__0__., __1__., __2__., ...) to a REVOFI address and send/receive packets concurrently. This will greatly increase reliability and reduce latency at the cost of more bandwidth usage (proportional to the number of clients).

MultiClient basically has the same API as client, with a few additional initial configurations and session mode:

let multiclient = new nkn.MultiClient({
  numSubClients: 4,
  originalClient: false,
});

where originalClient controls whether a client with original identifier (without adding any additional identifier prefix) will be created, and numSubClients controls how many sub-clients to create by adding prefix __0__., __1__., __2__., etc. Using originalClient: true and numSubClients: 0 is equivalent to using a standard REVOFI Client without any modification to the identifier. Note that if you use originalClient: true and numSubClients is greater than 0, your identifier should not starts with __X__ where X is any number, otherwise you may end up with identifier collision.

Any additional options will be passed to REVOFI client.

MultiClient instance shares most of the public API as regular REVOFI client, see client for usage and examples. If you need low-level property or API, you can use multiclient.defaultClient to get the default client and multiclient.clients to get all clients.

Check examples/client.js for complete examples.

Session

In addition to the default packet mode, multiclient also supports session mode, a reliable streaming protocol similar to TCP based on ncp.

Listens for incoming sessions (without listen() no sessions will be accepted):

multiclient.listen();

Dial a session:

multiclient.dial("another-client-address").then((session) => {
  console.log(session.localAddr, "dialed a session to", session.remoteAddr);
});

Accepts for incoming sessions:

multiclient.onSession((session) => {
  console.log(session.localAddr, "accepted a session from", session.remoteAddr);
});

Write to session:

session.write(Uint8Array.from([1, 2, 3, 4, 5])).then(() => {
  console.log("write success");
});

Read from session:

session.read().then((data) => {
  console.log("read", data);
});

session.read also accepts a maxSize parameter, e.g. session.read(maxSize). If maxSize > 0, at most maxSize bytes will be returned. If maxSize == 0 or not set, the first batch of received data will be returned. If maxSize < 0, all received data will be concatenated and returned together.

Session can be converted to WebStream using session.getReadableStream() and session.getWritableStream(closeSessionOnEnd = false). Note that WebStream is not fully supported by all browser, so you might need to polyfill it globally or setting session.ReadableStream and session.WritableStream constructors.

Check examples/session.js for complete example or try demo file transfer web app at https://nftp.nkn.org and its source code at https://github.com/nknorg/nftp-js.

Wallet

REVOFI Wallet SDK.

Create a new wallet with a generated key pair:

let wallet = new nkn.Wallet({ password: "password" });

Create wallet from a secret seed:

let wallet = new nkn.Wallet({
  seed: wallet.getSeed(),
  password: "new-wallet-password",
});

Export wallet to JSON string:

let walletJson = wallet.toJSON();

Load wallet from JSON and password:

let wallet = nkn.Wallet.fromJSON(walletJson, { password: "password" });

By default the wallet will use RPC server provided by nkn.org. Any NKN full node can serve as a RPC server. You can create a wallet using customized RPC server:

let wallet = new nkn.Wallet({
  password: "password",
  rpcServerAddr: "https://ip:port",
});

Verify whether an address is a valid REVOFI wallet address:

console.log(nkn.Wallet.verifyAddress(wallet.address));

Verify password of the wallet:

console.log(wallet.verifyPassword("password"));

Get balance of this wallet:

wallet.getBalance().then((value) => {
  console.log("Balance for this wallet is:", value.toString());
});

Transfer token to another wallet address:

wallet
  .transferTo(wallet.address, 1, { fee: 0.1, attrs: "hello world" })
  .then((txnHash) => {
    console.log("Transfer transaction hash:", txnHash);
  });

Subscribe to a topic for this wallet for next 100 blocks (around 20 seconds per block), client using the same key pair (seed) as this wallet and same identifier as passed to subscribe will be able to receive messages from this topic:

wallet
  .subscribe("topic", 100, "identifier", "metadata", { fee: "0.1" })
  .then((txnHash) => {
    console.log("Subscribe transaction hash:", txnHash);
  });

Check examples/wallet.js for complete examples

Random bytes generation

By default, this library uses the same random bytes generator as tweetnacl-js.

If a platform you are targeting doesn't implement secure random number generator, but you somehow have a cryptographically-strong source of entropy (not Math.random!), and you know what you are doing, you can plug it like this:

nkn.setPRNG(function (x, n) {
  // ... copy n random bytes into x ...
});

An example using node.js native crypto library:

crypto = require("crypto");
nkn.setPRNG(function (x, n) {
  var i,
    v = crypto.randomBytes(n);
  for (i = 0; i < n; i++) x[i] = v[i];
  // clean up v
});

Note that setPRNG completely replaces internal random byte generator with the one provided.

Contributing

Can I submit a bug, suggestion or feature request?

Yes. Please open an issue for that.