hyperledger-archives / aries-toolbox

Hyperledger Aries
https://wiki.hyperledger.org/display/aries
Apache License 2.0
42 stars 45 forks source link

Use aries-framework-javascript as base for toolbox #202

Open TimoGlastra opened 3 years ago

TimoGlastra commented 3 years ago

This is just an idea, and not something I can work on at the moment, however I've been thinking lately that I may be nice to use aries-framework-javascript as the base for the toolbox.

With the addition of more and more features to Aries having a single codebase as the base for all Aries JavaScript projects seems nice to me. With the new mobile agent initiative also using the framework I think it can save a lot of work in the long run.

We still need to make some architectural changes to AFJ to make this possible, but I'm curious to know what the maintainers of this repo think about it

dbluhm commented 3 years ago

This is a fascinating idea that I'm actually surprised hasn't been raised sooner... I could see this being a significant benefit to the toolbox project. Frankly speaking, the toolbox has been in need of some serious attention for a while. Currently we're plagued by niche solutions (no shade on the other maintainers, I think most of the solutions were things I wrote lol) that make getting into the toolbox or extending the toolbox challenging for anyone other that the original developers. Giving the core agent functionality some more structure could help keep straighten out the remaining pieces.

Our overarching design goals for the toolbox have been:

  1. Easy to install (ideally just an npm or yarn install and that's it, no worrying about libindy or libsodium, etc.)
  2. Easy to implement new protocols (right now, handling new message types is basically just writing an event handler though I am partial to flask-like message handler dispatching as well)
  3. Easy to extend (Similar to 2 but extending out into the UI, data management, and framework elements; I think we're falling short of this but adding new features isn't extremely burdensome if you know what you're doing)

Not being super familiar with where things are right now in AFJ, is it possible to run without the Indy SDK? How light or otherwise would you consider the protocol handler implementations?

TimoGlastra commented 3 years ago

I totally forgot about this issue, thanks for the elaborate response!

To answer your questions:

is it possible to run without the Indy SDK?

No at the moment it is not possible to run without Indy SDK. This is something we'd like to dive deeper in. Either by replacing indy-sdk with more easy to use native dependencies (that also support WASM) or by adding a javascript only implementation of the most important crypto (stablelib seems to do a pretty good job at this).

How light or otherwise would you consider the protocol handler implementations?

Somewhat heavy I'd say. The following highlights the requirements for adding basic message (somewhat simplified from how it works in AFJ):

// BasicMessageHandler.ts

import { Handler, HandlerInboundMessage } from '../../../agent/Handler'
import { BasicMessageService } from '../services/BasicMessageService'
import { BasicMessage } from '../messages'

export class BasicMessageHandler implements Handler {
  private basicMessageService: BasicMessageService // <-- Service handles everything related to this protocol. Can be embedded in handler for simpler use cases
  public supportedMessages = [BasicMessage] // <-- Declare supported messages. Can be one or multiple

  public constructor(basicMessageService: BasicMessageService) {
    this.basicMessageService = basicMessageService
  }

  // Handle message must be implemented. Receives class instance of message
  public async handle(messageContext: HandlerInboundMessage<BasicMessageHandler>) {
    const connection = messageContext.connection

    await this.basicMessageService.save(messageContext, connection)
  }
}

Then the message looks like this:

// BasicMessage.ts

import { Equals, IsDate, IsString } from 'class-validator'
import { Expose, Type } from 'class-transformer'

import { AgentMessage } from '../../../agent/AgentMessage'
import { MessageType } from './BasicMessageMessageType'

export class BasicMessage extends AgentMessage {
  /**
   * Create new BasicMessage instance.
   * sentTime will be assigned to new Date if not passed, id will be assigned to uuid/v4 if not passed
   * @param options
   */
  public constructor(options: { content: string; sentTime?: Date; id?: string; locale?: string }) {
    super()

    if (options) {
      this.id = options.id || this.generateId()
      this.sentTime = options.sentTime || new Date()
      this.content = options.content
      this.addLocale(options.locale || 'en')
    }
  }

  @Equals(BasicMessage.type)
  public readonly type = BasicMessage.type
  public static readonly type = MessageType.BasicMessage

  @Expose({ name: 'sent_time' })
  @Type(() => Date)
  @IsDate()
  public sentTime!: Date

  @Expose({ name: 'content' })
  @IsString()
  public content!: string
}

From here you can add more complexity as required such as adding persistence.

Still a lot to be simplified in the framework, but something to keep in the back of our minds while working out the framework. We have successfully ran AFJ in electron, so that's definitely possible (demo).

TimoGlastra commented 3 years ago

@dbluhm do you know which crypto is used for the toolbox? Is it just pack/unpack? Or also sign (for connections?). I'm looking into adding a non-indy wallet to AFJ that will also work in the browser

dbluhm commented 3 years ago

@TimoGlastra The toolbox is currently using https://github.com/dbluhm/Encryption-Envelope-js/tree/fix/base64-padding for pack and unpack functionality.

It's a bit on the janky side -- partially based on some JS work I threw together 2 or 3 years ago to assist Pico Labs in getting their agent to interoperate with the Indy Reference Agent I was working on at the time.

I'll have to double check what we're using for signing :thinking:

dbluhm commented 3 years ago

Ah, we skirt around the need to sign or verify signatures by only acting as a recipient of connection invitations and not actually verifying connection responses lol

TimoGlastra commented 3 years ago

Awesome! Thanks for looking into this. I think we can also use libsodium for the signatures, and otherwise maybe something like https://www.npmjs.com/package/@stablelib/ed25519 should do the trick