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

@proton/signing-request

v4.2.7

Published

Proton Signing Request (ESR / EEP-7) encoder and decoder

Downloads

439

Readme

proton-signing-request (PSR - Revision 3)

version license downloads

A library to assist with the Proton Signing Request (PSR) protocol.

The PSR protocol allows for an application (dapp) to generate signature requests (transactions) which can then be passed to signers (wallets) for signature creation. These signature requests can be used within URI links, QR Codes, or other transports between applications and signers.


Installation

To install via the package manager of your choice:

NPM

npm install @proton/signing-request

Yarn

yarn add @proton/signing-request


Signing Request Flow

In an environment where an application/dapp is requesting that an end user perform a transaction within their preferred signer/wallet, each of these applications will utilize the @proton/signing-request library to fulfill different roles.

  • The application/dapp will be creating and encoding the signing request.
  • The signer/wallet will be decoding and resolving the signing request.

The specification itself then allows either the signer/wallet itself to broadcast the finalized transaction, or the transaction/signature themselves can be passed back to the application/dapp to broadcast.

The @proton/signing-request library is not responsible for transporting this information between the application/dapp and signer/wallet, and so this topic will not be covered in this README.


Sample Transaction/Actions

To create a signing request, the first piece of data we need is either an EOSIO transaction or action(s). For all examples in this README we will use the eosio:voteproducer action to set a proxy of greymassvote.

The actions are as follows:

const actions = [{
    account: 'eosio',
    name: 'voteproducer',
    authorization: [{
      actor: 'taskly',
      permission: 'active'
    }],
    data: {
        voter: 'taskle',
        proxy: 'cafe',
        producers: [],
    }
}]

Two things to note:

  1. The actor and voter fields contain a placeholder which resolves to the signers account name (............1).
  2. The permission fields contain a placeholder which resolves to the signers account permission (............2).

These are optional parameters that can be passed anywhere within the authorization or data fields. If the application already knows who the end user is, the application can bypass the use of placeholders and specify that data directly.

Signing Request Options

Many of the SigningRequest method calls below will reference an opts parameter, which is a set of options that tell the signing request how to perform various tasks. For these examples, we will be using the following opts value.

const opts = {
    // string encoder
    textEncoder,
    // string decoder
    textDecoder,
    // zlib string compression (optional, recommended)
    zlib: {
        deflateRaw: (data) => new Uint8Array(zlib.deflateRawSync(Buffer.from(data))),
        inflateRaw: (data) => new Uint8Array(zlib.inflateRawSync(Buffer.from(data))),
    },
    // Customizable ABI Provider used to retrieve contract data
    abiProvider: {
        getAbi: async (account) => (await eos.getAbi(account))
    }
}

Creating a Signing Request

With the above actions established, to create the signing request itself we use the @proton/signing-request library and its create method.

(ES8 or TypeScript)

const request = await SigningRequest.create({ actions }, opts)
console.log(request)

(ES6)

SigningRequest.create({ actions }, opts).then((request) => {
  console.log(request)
})

This call will return an instance of a SigningRequest

SigningRequest {
  version: 2,
  data: {
    req: [
      'action',
      {
        account: 'eosio',
        name: 'voteproducer',
        authorization: [ { actor: '............1', permission: '............2' } ],
        data: '0100000000000000A032DD181BE9D56500'
      }
    ],
    chain_id: [ 'chain_alias', 1 ],
    flags: 1,
    callback: '',
    info: []
  }
}

Encoding a Signing Request

With an instance of a SigningRequest available, we can now call the encode method on it in order to generate a compressed payload to transport to a signing application.

const encoded = request.encode()

This encoded variable will now contain a string we can either pass directly to the signer via URI, QRCode or any other method. The string itself is:

esr://gmNgZGRkAIFXBqEFopc6760yugsVYWBggtKCMIEFRnclpF9eTWUACgAA

These encoded strings can be shared and viewed by a number of applications, including:

EOSIO.to

This website is a utility which allows the viewing of a signing request as well as the opportunity to create a signature for it. The above encoded request can be passed to the eosio.to domain:

https://eosio.to/gmNgZGRkAIFXBqEFopc6760yugsVYWBggtKCMIEFRnclpF9eTWUACgAA

EOSIO URI Builder

This web application allows for the viewing, editing, and customization of signing requests. The above encoded request can be passed to the builder via a URL parameter:

https://greymass.github.io/eosio-uri-builder/gmNgZGRkAIFXBqEFopc6760yugsVYWBggtKCMIEFRnclpF9eTWUACgAA

Decoding a Signing Request

Using the encoded signing request generated in the example above:

const uri = 'esr://gmNgZGRkAIFXBqEFopc6760yugsVYWBggtKCMIEFRnclpF9eTWUACgAA'

Another application can now decode this request into an instance of a SigningRequest with the from method.

const decoded = SigningRequest.from(uri, opts)

Decoding the signing request will return the same instance as when it was originally created, as follows:

SigningRequest {
  version: 2,
  data: {
    chain_id: [ 'chain_alias', 1 ],
    req: [
      'action[]',
      [
        {
          account: 'eosio',
          name: 'voteproducer',
          authorization: [ { actor: '............1', permission: '............2' } ],
          data: '0100000000000000A032DD181BE9D56500'
        }
      ]
    ],
    flags: 1,
    callback: '',
    info: []
  },
  textEncoder: TextEncoder { encoding: 'utf-8' },
  textDecoder: TextDecoder { encoding: 'utf-8', fatal: false, ignoreBOM: false },
  zlib: {
    deflateRaw: [Function: deflateRaw],
    inflateRaw: [Function: inflateRaw]
  },
  abiProvider: { getAbi: [AsyncFunction: getAbi] },
  signature: undefined
}

This SigningRequest can then be used within signing applications to start interacting with the request itself.

Resolving a Signing Request

With an instance of a SigningRequest available, a signing application can now resolve the specific request into a transaction. The resolving step does a few things:

  • Generates a transaction with valid TAPOS values.
  • Templates the transaction, removing any placeholders and resolving it to be used by a specific end user.
  • Serializes the transaction for use within the signer.

This step now requires that the application understand who the user is, and have access to the blockchain itself to retrieve TAPOS values.

// An encoded eosio:voteproducer transaction
const uri = 'esr://gmNgZGRkAIFXBqEFopc6760yugsVYWBggtKCMIEFRnclpF9eTWUACgAA'

// Decode the URI
const decoded = SigningRequest.from(uri, opts)

// In order to resolve the transaction, we need a recent block
const head = (await rpc.get_info(true)).head_block_num;
const block = await rpc.get_block(head);

// Fetch the ABIs needed for decoding
const abis = await decoded.fetchAbis();

// An authorization to resolve the transaction to
const authorization = {
    actor: 'teamgreymass',
    permission: 'active',
}

// Resolve the transaction as a specific user
const resolved = await decoded.resolve(abis, authorization, block);

The resolve method will return an instance of a ResolvedSigningRequest, which contains:

  • The original SigningRequest as request.
  • The signer that was used to template the transaction.
  • The transaction which has been templated and is ready to use.
  • The transaction already serialized as serializedTransaction.

Below is the representation of an instance of this object.

ResolvedSigningRequest {
  request: SigningRequest {
    version: 2,
    data: {
      chain_id: [ 'chain_alias', 1 ],
      req: [
        'action[]',
        [
          {
            account: 'eosio',
            name: 'voteproducer',
            authorization: [ { actor: '............1', permission: '............2' } ],
            data: '0100000000000000A032DD181BE9D56500'
          }
        ]
      ],
      flags: 1,
      callback: '',
      info: []
    },
    textEncoder: TextEncoder { encoding: 'utf-8' },
    textDecoder: TextDecoder { encoding: 'utf-8', fatal: false, ignoreBOM: false },
    zlib: {
      deflateRaw: [Function: deflateRaw],
      inflateRaw: [Function: inflateRaw]
    },
    abiProvider: { getAbi: [AsyncFunction: getAbi] },
    signature: undefined
  },
  signer: { actor: 'teamgreymass', permission: 'active' },
  transaction: {
    actions: [
      {
        account: 'eosio',
        name: 'voteproducer',
        authorization: [ { actor: 'teamgreymass', permission: 'active' } ],
        data: { voter: 'teamgreymass', proxy: 'greymassvote', producers: [] }
      }
    ],
    context_free_actions: [],
    transaction_extensions: [],
    expiration: '2020-01-08T18:44:57.000',
    ref_block_num: 1423,
    ref_block_prefix: 4278398322,
    max_cpu_usage_ms: 0,
    max_net_usage_words: 0,
    delay_sec: 0
  },
  serializedTransaction: Uint8Array [
    41,  35,  22,  94, 143,  5, 114,  45,   3, 255,   0,   0,
     0,   0,   1,   0,   0,  0,   0,   0, 234,  48,  85, 112,
    21, 210, 137, 222, 170, 50, 221,   1, 128, 177, 145,  94,
    93,  38, 141, 202,   0,  0,   0,   0, 168, 237,  50,  50,
    17, 128, 177, 145,  94, 93,  38, 141, 202, 160,  50, 221,
    24,  27, 233, 213, 101,  0,   0
  ]
}

The transaction or serializedTransaction can now be used within any signature provider to generate a signature for this transaction, and ultimately broadcast the signed transaction to the blockchain.

Further Usage

This README will be updated further to provide more usage as time progresses. The library itself already supports sessions, identities, callbacks, signature generation, and more. It will just take time to properly document every use case.

Developer Chat

We have a telegram channel dedicated to the development of this protocol which you can find here:

https://t.me/eosio_signing_request