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

json-xdr

v0.1.1

Published

Easily convert between XDR and JSON.

Downloads

32

Readme

JSON <-> XDR

Build Status

This library extends js-xdr to let you convert XDR to JSON and JSON to XDR.

Installation

via npm:

npm install --save json-xdr

Usage

The examples below will use the following XDR definition:

const XDR = require('js-xdr')

const types = XDR.config((xdr) => {
  xdr.typedef("Hash", xdr.opaque(2));
  xdr.typedef('Int32', xdr.int());

  xdr.struct("Price", [
    ["n", xdr.lookup("Int32")],
    ["d", xdr.lookup("Int32")],
  ]);

  xdr.enum("MemoType", {
      memoNone: 0,
      memoText: 1,
      memoId: 2,
      memoHash: 3,
      memoReturn: 4,
  });

  xdr.union("Memo", {
    switchOn: xdr.lookup("MemoType"),
    switchName: "type",
    switches: [
      ["memoNone", xdr.void()],
      ["memoText", "text"],
      ["memoId", "id"]
    ],
    arms: {
      text: xdr.string(28),
      id: xdr.lookup("Int32")
    },
  });

  xdr.typedef('CounterInt', xdr.option(xdr.int()));

  xdr.struct('Event', [
    ["attendees", xdr.int()],
    ["eventName", xdr.string(50)],
    ["secretSpeakers", xdr.array(xdr.lookup("Hash"), 2)],
    ["speakers", xdr.varArray(xdr.string())],
    ["price", xdr.lookup("Price")],
    ["memo", xdr.lookup("Memo")],
    ['meta', xdr.lookup('TransactionMeta')],
    ['counter', xdr.lookup("CounterInt")]
  ])

  xdr.enum("TransactionMetaType", {
    none: 0,
    paid: 1
  });

  xdr.union("TransactionMeta", {
    switchOn: xdr.lookup("TransactionMetaType"),
    switches: [
      ["none", xdr.void()],
      ["paid", "price"]
    ],
    arms: {
      price: xdr.lookup("Price")
    },
    defaultArm: xdr.void()
  });
})

Serializing from XDR to JSON

You can convert an XDR struct to JSON using the function toJSON.

import { toJSON } from 'json-xdr';

let event = new types.Event({
  attendees: 5,
  eventName: "Lumenauts get together",
  secretSpeakers: [Buffer.from([0, 0]), Buffer.from([0, 1])],
  speakers: ['Jed', 'Tom', 'Zac'],
  price: new types.Price({
    n: 2,
    d: 1
  }),
  memo: types.Memo.memoText("foo"),
  meta: types.TransactionMeta.paid(new types.Price({
    n: 2,
    d: 1
  })),
  counter: 2
})

let payload = toJSON(event);

console.log(payload)

// Output
// {
//   "attendees": 5,
//   "eventName": "Lumenauts get together",
//   "secretSpeakers": [
//     "AAA=",
//     "AAE="
//   ],
//   "speakers": [
//     "Jed",
//     "Tom",
//     "Zac"
//   ],
//   "price": {
//     "n": 2,
//     "d": 1
//   },
//   "memo": {
//     "_type": "memoText",
//     "text": "foo"
//   },
//   "meta": {
//     "_type": "paid",
//     "price": {
//       "n": 2,
//       "d": 1
//     }
//   },
//   "counter": 2
// }

Serializing from JSON to XDR

Given a JSON object representing a struct from your types definition, you can convert it to XDR using the function toXDR.

import { toXDR } from 'json-xdr';

let payload = {
  "attendees": 5,
  "eventName": "Lumenauts get together",
  "secretSpeakers": [
    "AAA=",
    "AAE="
  ],
  "speakers": [
    "Jed",
    "Tom",
    "Zac"
  ],
  "price": {
    "n": 2,
    "d": 1
  },
  "memo": {
    "_type": "memoText",
    "text": "foo"
  },
  "meta": {
    "_type": "paid",
    "price": {
      "n": 2,
      "d": 1
    }
  },
  "counter": 2
}

let event = toXDR(types.Event, payload)

assert.ok(xdrEvent instanceof types.Event)

Serialization format

JavaScript native types are used when possible, for example, String, Integer, Array and null. However there are some types which don't have an equivalent representation. For those types the serialization and deserialization is done using the following rules.

Opaque and VarOpaque

Opaque and Variable Opaque data are represented in js-xdr using a binary data buffer. Buffers are serializer as a base64 encoded string.

For the following definition:

const types = XDR.config((xdr) => {
  xdr.struct('withOpaque', [
    ['opaque', xdr.opaque(3)],
    ['varOpaque', xdr.varOpaque(2)]
  ])
})

let withOpaque = new types.withOpaque({
  opaque: Buffer.from([0, 0, 1]),
  varOpaque: Buffer.from([0, 1])
})

Calling #toJSON will result in:

{
  opaque: 'AAAB',
  varOpaque: 'AAE='
}

Array

Array and VarArray are serialized as a JavaScript Arrays and then for each element we apply the serialization rules defined in this library.

For the following definition:

const types = XDR.config((xdr) => {
  xdr.typedef("Hash", xdr.opaque(2));

  xdr.struct('Event', [
    ["attendees", xdr.int()],
    ["eventName", xdr.string(50)],
    ["secretSpeakers", xdr.array(xdr.lookup("Hash"), 2)],
    ["speakers", xdr.varArray(xdr.string())]
  ])
})

let event = new types.Event({
  attendees: 5,
  eventName: "Lumenauts get together",
  secretSpeakers: [Buffer.from([0, 0]), Buffer.from([0, 1])],
  speakers: ['Jed', 'Tom', 'Zac']
})

Calling #toJSON will result in:

{
  attendees: 5,
  eventName: 'Lumenauts get together',
  secretSpeakers: [ 'AAA=', 'AAE=' ],
  speakers: [ 'Jed', 'Tom', 'Zac' ]
}

Notice how speakers get serialized as a JavaScript String while secretSpeakers which is an Opaque, get serialized as base64, which is documented above.

Union

Unions are serialized as a JavaScript object, the discriminant is store in the property _type. If there is an arm for the given discriminant, then a property with the arm's name is set in the object and its value should contain a type as defined in the XDR declaration.

The following struct has two property of type union: memo and meta.

let event = new types.Event({
  attendees: 5,
  eventName: "Lumenauts get together",
  secretSpeakers: [Buffer.from([0, 0]), Buffer.from([0, 1])],
  speakers: ['Jed', 'Tom', 'Zac'],
  price: new types.Price({
    n: 2,
    d: 1
  }),
  memo: types.Memo.memoText("foo"),
  meta: types.TransactionMeta.paid(new types.Price({
    n: 2,
    d: 1
  })),
  counter: 2
})

The code below shows the result after calling toJSON(event), notice how the memo property has an object with the key _type: "memoText" and a property matching the arm declaration text with a string value of foo.

Similarly, the property meta has an object with _type: "paid", with the arm price which contains a Struct of type Price.

{
  ...,
  "memo": {
    "_type": "memoText",
    "text": "foo"
  },
  "meta": {
    "_type": "paid",
    "price": {
      "n": 2,
      "d": 1
    }
  }
}

Default Arms

Given the following definition:

xdr.union("TransactionMeta", {
  switchOn: xdr.lookup("TransactionMetaType"),
  switches: [
    ["none", xdr.void()],
    ["paid", "price"]
  ],
  arms: {
    price: xdr.lookup("Price")
  },
  defaultArm: xdr.string(3)
});

If the union instance uses the default arm, it will be serialized like the following:

{
  ...,
  "meta": {
    "_type": "pending",
    "default": "foo"
  }
}

Void Arms

If there is no arm for the discriminant, only the _type property will appear on the object.

{
  ...,
  "meta": {
    "_type": "withVoidArm",
  }
}

Examples

You can find more examples in the test here.