Dev Null Productions

The Blog

VueJS Plugin Development Guide

In this guide we will explore how to create a new VueJS plugin from scratch. While creating a new standalone vuejs project is fairly straightforward (1. install vuejs 2. vue create <project_name> 3. yarn serve), creating a reusable plugin that is able to be incorporated into any VueJS project in a generic way is a more complicated process. Furthermore due to the novelty of the entire nodejs and vuejs ecosystem, there is a plethora of documentation specific to different steps of the process scattered across the web. This guide aims to provide a unified tutorial on how to create a plugin from scratch.

Note: We will be taking the most straightforward process to accomplish this, while there may be shortcuts, utilities to assist with different stages, and some steps may change over time, this guide should provide a concise resource of how to create and use a VueJS plugin.

Terminology:

Before we begin, here are some terms that developers will need to know:

  • JavaScript: eg JS, the programming language which we will be developing in
  • vuejs: A popular JS framework for creating web-based user interfaces
  • npm: The node package manager, a framework and set of utilities used to package and upload/download reusable bundles of javascript code (known as 'packages')
  • yarn: Another package manager for javascript with a builtin command specification and execution system. Uses the npm package registry on the backend (thus all packages uploaded to the npm repository are available to yarn for installation & inclusion)

Additional Terms:

Some additional terms which are good to know though not techincally needed:

  • nodejs: the JS runtime environment that executes JS code on the local machine
  • ECMAScript: eg ES, a standardization of syntax for languages such as Javascript. Comes in two primary variants ES5 and ES6. ES6 is an improvement on ES5 but is incompatible and most major browsers do not support it. ES6 has been superseded by more recent versions but those are compatible with ES6.
  • babel: A transpiler (source-to-source compiler) that converts newer version of ES (ES6+) to ES5 for browser compatability.
  • webpack: The underlying bundler which determines dependencies amongst your JS components and assembles them together into a single/isolated/importable module.
  • rollup: Another JS module bundler with a similar feature set to webpack but different implementation & tradeoffs
  • commonjs and AMD: Older JS encapsulation systems used before modules were standardized in ES6. Developers no longer need to concern themselves with these technologies.

Project Layout:

To begin, create a new directory for the plugin you would like to create. As a standard, it is good practice to prefix vuejs plugins with the vue- moniker. So if we wanted to create a 'nyan-cat' plugin, we would start byrunning:

$ mkdir vue-nyan-cat

Inside this directory, create some subdirs which will be used to encapsulate standard vuejs constructs and build artifcats:

$ cd vue-nyan-cat
$ mkdir dist examples src src/assets

package.json:

Create a package.json file, which yarn will you will use to specify dependencies and commands for yarn to execute:

{
  "name": "vue-nyan-cat",
  "version": "0.0.2",
  "description": "Renders the Nyan Cat in a VueJS based interface",
  "keywords": [
    "vuejs",
    "plugin",
    "nyan cat"
  ],
  "main": "dist/vue-nyan-cat.common.js",
  "license": "MIT",
  "author": "Mo Morsi <devnullproductions@gmail.com>",
  "repository": "github:DevNullProd/vue-nyan-cat",
  "scripts": {
    "serve": "vue-cli-service serve examples/main.js",
    "build": "vue-cli-service build --target lib src/nyan-cat.vue"
  },
  "dependencies": {},
  "devDependencies": {
    "@vue/cli-service": "^4.1.1",
    "vue": "^2.6.11",
    "vue-template-compiler": "^2.6.11"
  }
}

package.json explained:

Lets explore each of these sections one at a time.

To start we specify package metadata. This includes:

  • name: The unique name of your plugin
  • version: The current version of your plugin, make sure to increase appropriately this on every release
  • description: A human-friendly textual description of your plugin
  • keywords: Phrases to associate with your plugin to make it easy to lookup when uploaded to the npm package repository (more on this later)
  • main: The module output by the build system which will be loaded when a developer imports your plugin into their project. Note this module just constitutes the javascript code which is included in your plugin, the developer using it may also have to include the stylesheets (more on this later)
  • license: The legal license which you are releasing your plugin under
  • author: The developer/company which you are referencing as the author of the plugin
  • repository: The location where the plugin source code can be found
{
  "name": "vue-nyan-cat",
  "version": "0.0.2",
  "description": "Renders the Nyan Cat in a VueJS based interface",
  "keywords": [
    "vuejs",
    "plugin",
    "nyan cat"
  ],
  "main": "dist/vue-nyan-cat.common.js",
  "license": "MIT",
  "author": "Mo Morsi <devnullproductions@gmail.com>",
  "repository": "github:DevNullProd/vue-nyan-cat",

Next we define scripts, or command that will be accessible via invocation with yarn, eg. yarn run example which can be abbreviated to yarn example.

Here we define two commands:

  • serve which provides access to the plugin example it via a built-in webserver. Using this you can view the plugin locally by opening a web-brower and pointing it at the provided url (more on this below)
  • build which builds our package into a format which you can upload to the npm repository for subsequent download (by yourself and others, more below)
  "scripts": {
    "serve": "vue-cli-service serve examples/main.js",
    "build": "vue-cli-service build --target lib src/nyan-cat.vue"
  },

As you can see above, configuration options are specified for both the poi and bili commands, which may be tweaked if desired

Finally we specify dependencies and devDependencies which our component requires to perform properly. Dependencies are need to execute your plugin in production and are pulled in when it is downloaded/installed from npm. devDependencies are only used during the development phase, in our case the VueJS dependencies we need to run the project commands.

  "dependencies": {},
  "devDependencies": {
    "@vue/cli-service": "^4.1.1",
    "vue": "^2.6.11",
    "vue-template-compiler": "^2.6.11"
  }
}

Plugin Implementation:

Now lets get to actually building the plugin! We won't go into too much detail as to how VueJS works here, there are plenty of docs on how to develop VueJS functionality on the web (including the excellent developer documentation), but we will discuss a few critical components:

  • src/nyan-cat.vue - the main module which will define the top level component constituting our plugin
  • src/index.js - defines the install target which will be executed when our plugin is loaded into a VueJS project
  • examples/index.js - the main entry point for the example target, recall this was referenced in the poi script in package.json

src/nyan-cat.vue

The main implementation of our plugin... do your magic here!

<template>
  <div id="nyan-cat">
    <img src="https://raw.githubusercontent.com/DevNullProd/vue-nyan-cat/master/src/assets/nyan-cat.gif" />
  </div>
</template>

<script>
export default {
  name: 'NyanCat'
}
</script>

<style scoped>
#nyan-cat{
  display: inline-block;
  padding: 10px;
  border: 1px solid black;
  border-radius: 5px;
}
</style>

Because we are referencing a static image (nyan-cat.gif) it must be downloaded and placed in the src/assets directory. You may get it from here:

src/index.js

Recall this defines install which will be executed when we import & use our plugin in a larger VueJS project.

import NyanCat from './nyan-cat.vue'

export default {
  install : function(vue, opts){
    vue.component('NyanCat', NyanCat)
  }
}

examples/index.js

This replicates the 'main' module of a larger VueJS project and will be used for demonstation / test purposes

import Vue from 'vue'
import App from './App.vue';

import NyanCat from '../src/index.js'

Vue.use(NyanCat)

new Vue({
  el: '#app',
  render(h){ return h(App) }
})

examples/App.vue

The top level component in our example project where we actually use our plugin in the UI

<template>
  <NyanCat />
</template>

<script>
export default{
}
</script>

examples/index.html

Defines the static web page in which the top level component in our example project will be mounted

<!DOCTYPE html>
<html>
<body>
  <div id="app"></div>
</body>
</html>

Test it!

And that's it! To test our plugin by running the example, do the following:

Install dependencies

$ yarn install

Build and run the example

$ yarn serve

Finally open a web browser and point it a http://localhost:4000/vue-nyan-cat/ to see your plugin!

Round out your plugin

In general it is good practice to include a README.md file, explaining how to install, import, and use your plugin, and a LICENSE file containing the full text of the license which you are releasing your package under (the same one as that referenced in package.json above).

Build it!

$ yarn build

This will place your plugin output in the dist directory. Now you are ready to ship it!

Ship it!

In order for others to access your plugin you will have to upload it to NPM. First sign up for a new account. Once you have done so, login via the following command:

$ npm login

Enter the credentials you supplied when creating your account. Finally upload it with:

$ npm publish

The package will now be on NPM! You may view it at: https://www.npmjs.com/package/vue-nyan-cat.

Use it!

To use our new plugin in a larger VueJS project, first cd to the project dir and install it with yarn:

$ yarn add vue-nyan-cat
Finally import the plugin into your component and use:
<template>
  <div id="app">
    <NyanCat />
  </div>
</template>

<script>
import NyanCat from 'vue-nyan-cat'
import 'vue-nyan-cat/dist/vue-nyan-cat.css'

export default {
  name: 'app',
  components: {
    NyanCat
  }
}
</script>

Fin

You can see the complete example above on github along with other examples of Vue components under the DevNullProd organization.

DNP - 2019 Retrospective

Can you believe it's almost December already! Lets look at many of the great events and happenings that we participated in this past year.

XRP Community Meetup - Amersfoort

Earlier last spring Dev Null took a trip to the scenic country of the Netherlands to attend the XRP Community Meetup in Amersfoort, hosted by none other than Wieste of XRPL Labs and Tom Kuster. Denmark is a beautiful country, full of history and culture, especially in the financial world, as it was one of the original homes of the modern banking industry. The meetup was a great experience as it faciliated an opportunity to put faces to all the Twitter handles and form bonds which will last a lifetime.

Development Releases - XRBP, Wipple, xrp1ntel

Spring of this year also saw a flury of releases of XRBP, our Open Source interface to the XRPL, written in Ruby. Early releases included base level support for the XRP websocket API as well as related web based resources (the DataV2 API, exchange data, etc). Subsequent releases incorporated functionality allowing the client to:

  • Crawl / traverse the peer-to-peer network of XRPL nodes
  • Directly parse the XRP binary database (the nodestore)
  • Generate node and account keys pairs and addresses
  • Access the sqlite database embedded in XRPL instances
  • And much more!

Additionally, the intial prototype version of our analytics engine, dubbed Wipple (originally stemming from the combination of 'Wallet' and 'Ripple') saw much growth at the beginning of the year up to the summer. Most of this early development was spent spec'ing out and prototyping many features and ideas that we were brainstorming. Over the summer this product underwent a rewrite and redesign, and morphed into our new flagship analytics product xrp1ntel which is under active development to this day.

The evolution of the XRP Analytics Engine

Dev Null Prod relocates & the beginning of NYC/XRP

This past summer also saw the relocation of Dev Null Productions from Upstate NY to NYC. While we will always have a presence upstate and it will always have a special place in our heart, this was decision was executed so as to maximize growth of the business and network, and we have been having so much fun that we haven't looked back!

Part of the fun has included organizing and running the NYC/XRP meetup, consisting of a group of XRP enthusiasts in the tri-state area. Meetups are held at an interval of every other month and consists of a variety of social gatherings and tech talks used to bring the community together for networking and growth. To this date the meetups we've held included

  • July - Our first community social / meet & greet
  • September - Our first tech talk held in Chelsea, the presentation of the night was titled XRP - An Intro
  • November - An informal dinner which we held at a great steakhouse in midtown
The next meetup will be held in January, and most likely will be in a tech talk format again. Be sure to join the meetup group to stay in the loop!

Conference Galore

The past year has seen our attendance at several major conferences. From the 1st and 2nd SFBW conferences in San Francisco, CA, to Money 20/20 in Las Vegas, NV, to the AWS Summit in our new home city, we never missed an opportunity to promote XRP technology and #XRPCommunity efforts to build the ecosystem. We're big on conference attendance, not only are they great ways to meet a spectrum of professionals from many industries but they are excellent opportunities to quickly get our startup's brand infront of alot of organizations, both small and large. We're planning and are very eager to attend DLTCONLA (Los Angeles, CA) with several members from the NYC/XRP community this spring and will be sure to continue attending the hottest events as we hear about them!

Rippled Contributions

One final endeavor that we'd like to point out is our continued involvement in the development of the core rippled codebase driving the XRPL Blockchain. Serving dual purposes, firstly to contribute to and support the growth of the ecosystem, as well as for us to stay in the loop at the ground level (there is no better way to do that than to be working on the core repo!), we've submitted several patches/pull-requests to the codebase which have been subsequently merged / integrated into the core product (props to the Ripple Labs engineering team who are top notch and very friendly/open to development synergy). These features include:

  • Code cleanups & fixes, addressing issues as we encountered them during our source code analysis
  • Refactoring of the CMake-based build system, to faciliate modularization, compartmentalization, and easier-understanding by new contributors
  • Implementation of the consensus stream, allowing the user to subscribe to real-time updates of consensus state

Fin

And that's all for now! This past year has seen momentous growth both in terms of the #XRPCommunity and Dev Null Productions, we can't wait to continue driving things forward and seeing the ecosystem evolve next year! Until next time... Happy Zerping!

XRBP - The Ultimate XRP / Ruby Interface

Dev Null Productions is pleased to announce the general availability of XRBP a library aimed at providing an accessible, fault-tolerant interface to the XRP ledger. XRBP allows the developer to read and write data to/from the XRP network in real time, synchronizing ledger data including accounts, transactions, objects, and more. Data is presented via both synchronous and asynchronous mechanisms with multiple-connection load balancing and fault tolerance baked in behind the scenes.

But some code is worth a 1000 words! The following allows you to pull server info pertaining to the instance of rippled you are connected to:

require 'xrbp'

ws = XRBP::WebSocket::Connection.new "wss://s1.ripple.com:443"
ws.add_plugin :autoconnect, :command_dispatcher

ws.cmd XRBP::WebSocket::Cmds::ServerInfo.new

Above we see

  • the XRBP library is included
  • a new websocket connection to s1.ripple.com is established
  • and the ServerInfo command is dispatched and the results printed

To facilitate fully-customizable and configurable applications XRBP incorporates a pluggable architecture where modules customizing the request/response workflow and validating/transforming result sets may be registed with connection objects. As of the current date, plugins exist to:

  • Automatically timeout inactive connections and reestablish the link
  • Automatically retry failed requests (with configurable max tries and timeout)
  • Allow the user to register custom data parsers to transform received data
  • Paginate results behind the scenes so large data sets (transactions, account objects, etc) can all be seemlessly retrieved and aggregated before the results are returned
  • Dispatch and validate XRP specific commands, extracting specific data out of the result set for client consumption

Furthemore XRBP facilitates fault tolerant communications by implementing serveral multi-connection strategies behind these scenes. Each strategy manages an internal pool of connections and cycles through them according to different criteria.

To use multiple XRP servers in a 'round-robin' manner where subsequent connections will always be delegated to the next connection in the list:

ws = XRBP::WebSocket::RoundRobin.new "wss://s1.ripple.com:443",
                                     "wss://s2.ripple.com:443"

ws.add_plugin :command_dispatcher
ws.connect

puts ws.cmd(XRBP::WebSocket::Cmds::AccountInfo.new("rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"))
puts ws.cmd(XRBP::WebSocket::Cmds::AccountInfo.new("rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq"))

In the above example we will retrieve info pertaining to the first account (rvYAf...) from s1.ripple.com and the second account (rhub8...) from s2.ripple.com. With the RoundRobin strategy, once all connections are used, we will cycle back to the first, in this case the next request will be issued to s1.ripple.com.

To automatically leverage backup servers if a request fails, we can use the Prioritized strategy:

ws = XRBP::WebSocket::Prioritized.new "wss://s1.ripple.com:443",
                                      "wss://s2.ripple.com:443"

ws.add_plugin :command_dispatcher, :result_parser
ws.parse_results { |res|
  JSON.parse(res)["result"]["ledger"]
}
ws.connect

puts ws.cmd(XRBP::WebSocket::Cmds::Ledger.new(28327070))

In this example we see that we establish a Prioritized connection set, and register a plugin to automatically parse data retrieved from the server. If we are not able to retrieve a valid ledger, the parser will throw an error and we will automaticlaly try the next connection behind the scenes. Thus if we query for a ledger which has been deleted from our primary rippled server, we can fall back to a full-history node.

This is just the icing on the cake as far as multi-connection strategies, there are several more included in the public XRBP API and developing custom strategies is as simple as inheriting XRBP::WebSocket::MultiConnection and defining next_connection.

XRBP can do much more ontop of all this. We can sync validators, gateways, etc from the DataV2 API, sync market quotes from exchanges, crawl the network and much more!

Listing Validators

connection = XRBP::WebClient::Connection.new
XRBP::Model::Validator.all(:connection => connection)
                      .each do |v|
  puts v
end

Crawling Nodes

connection = XRBP::WebClient::Connection.new
connection.timeout = 3

connection.on :peer do |node, peer|
  puts "#{node.url} peer: #{peer.url}"
end

XRBP::Model::Node.crawl("wss://s1.ripple.com:51235",
                        :connection => connection)

See project documentation and examples/ for complete details. And make sure to stay tuned there are alot more great features coming!

Wipple Version 0.13.1 - Now Available!

We are pleased to announce the general availability of Wipple 0.13.1, now live. This release brings many exciting new features and more stabilizations to the entire application.

To start off, we've made many improvements to the general look and feel of the website. The account, tips, and transactions pages have been updated to streamline data delivery in an aesthetically pleasing manner.


On the accounts page we've added an experimental new widget allowing to to explore account transactions by time. It may be activated by clicking 'Timeline' under the list of account transactions.
Note this is an early prototype, and it will receive fixes / enhancements in the near future.

New enhancements to the transactions page include:

  • A compact description of listed transactions, providing a quick visual overview of what's happening on the network at a glance. The original detailed view can be toggled via the settings (⚙️ ) icon in the upper right.

  • A title bar allowing you to monitor and filter transactions by specific category as well as those present in any given ledger. This navigational component presents the tally of received transactions and allows the user to simply view just those transactions.

  • New settings allowing you to highlight particular transaction categories for increased visibility in the ledger. Also toggleable via the settings in the upper right

In the Reporting section, we've added the ability to view higher timeframes of data. By default our analytics engine samples the XRP network every five minutes for ledger activity, which we've taken and resampled to hourly, daily, weekly, and monthly timeframes which can now be selected in the UI. Now you can monitor trends and patterns on much longer timescales!

The report metrics UI has received some general enhancements including additional hover/click effects and the ability to blow up graphs, by clicing on the expand icon in the lower right

Overall the application has received many improvements including but not limited to:

  • Expanded help, which can be accessed via the ? icon in the upper right of the UI, provides more information as to what is represented on each page and how to use the application.

  • Mobile improvements: our goal is for 100% mobile compatability. We ask that anything that looks "wrong" on mobile interfaces be reported to devnullproductions@gmail.com so that we can promply address. If you've experienced issues w/ mobile access in the past, you may want to revisit the site as many outstanding issues have been fixed in this release (including incorrect styling in the research section).

  • Better backend improvements: our data collection and aggregation system has been thoroughly tested and vetted to ensure all ledger edge cases have been handled and our database stays consistently in sync with the XRP network. We've written scripts and verification logic to provide us confidence that our data and metrics and accurate. This release sets the basis for running our analytics engine against the last several years worth of ledger traffic to generate long term stats (coming in the near future).

And that wraps up another successful release! Make sure to stay tuned, 0.13.2 is not that far away!

Dev Null - The Blog

We're please to announce the Dev Null Blog a one-stop shop for everything Dev Null. With this blog we aim to provide latest news and updates about all things Dev Null, from products and features we release, solutions delivered, bugfixes, and more. The intent is to provide content of interest to a wide-variety of readers, from users who are interested in the content we provide, to developers looking to build upon our services + many more. Be sure to stay tuned as we're just getting started and lots of great content is coming soon!