Skip to content

Commit

Permalink
fix: error if unpacked message does not match JWE structure
Browse files Browse the repository at this point in the history
Signed-off-by: annelein <[email protected]>
  • Loading branch information
Annelein committed Feb 15, 2022
1 parent beff6b0 commit 2f4fc4e
Show file tree
Hide file tree
Showing 54 changed files with 3,402 additions and 1,510 deletions.
8 changes: 7 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,13 @@ module.exports = {
},
},
{
files: ['*.test.ts', '**/__tests__/**', '**/tests/**', 'jest.*.ts', 'samples/**'],
files: ['demo/**'],
rules: {
'no-console': 'off',
},
},
{
files: ['*.test.ts', '**/__tests__/**', '**/tests/**', 'jest.*.ts', 'samples/**', 'demo/**'],
env: {
jest: true,
node: false,
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ In order to use Aries Framework JavaScript some platform specific dependencies a
- [NodeJS](/docs/setup-nodejs.md)
- [Electron](/docs/setup-electron.md)

### Demo

To get to know the AFJ flow, we built a demo to walk through it yourself together with agents Alice and Faber.

- [Demo](/demo)

### Usage

Now that your project is setup and everything seems to be working, it is time to start building! Follow these guides below to get started!
Expand Down
89 changes: 89 additions & 0 deletions demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<h1 align="center"><b>DEMO</b></h1>

This is the Aries Framework Javascript demo. Walk through the AFJ flow yourself together with agents Alice and Faber.

Alice, a former student of Faber College, connects with the College, is issued a credential about her degree and then is asked by the College for a proof.

## Features

- ✅ Creating a connection
- ✅ Offering a credential
- ✅ Requesting a proof
- ✅ Sending basic messages

## Getting Started

### Platform Specific Setup

In order to use Aries Framework JavaScript some platform specific dependencies and setup is required. See our guides below to quickly set up you project with Aries Framework JavaScript for NodeJS, React Native and Electron.

- [NodeJS](/docs/setup-nodejs.md)

### Run the demo

These are the steps for running the AFJ demo:

Clone the AFJ git repository:

```sh
git clone https://github.com/hyperledger/aries-framework-javascript.git
```

Open two different terminals next to each other and in both, go to the demo folder:

```sh
cd aries-framework-javascript/demo
```

Install the project in one of the terminals:

```sh
yarn install
```

In the left terminal run Alice:

```sh
yarn alice
```

In the right terminal run Faber:

```sh
yarn faber
```

### Usage

To set up a connection:

- Select 'setup connection' in both Agents
- Alice will print a invitation link which you then copy and paste to Faber
- You have now set up a connection!

To offer a credential:

- Select 'offer credential' in Faber
- Faber will start with registering a schema and the credential definition accordingly
- You have now send a credential offer to Alice!
- Go to Alice to accept the incoming credential offer

To request a proof:

- Select 'request proof' in Faber
- Faber will create a new proof attribute and will then send a proof request to Alice!
- Go to Alice to accept the incoming proof request

To send a basic message:

- Select 'send message' in either one of the Agents
- Type your message and press enter
- Message sent!

Exit:

- Select 'exit' to shutdown the agent.

Restart:

- Select 'restart', to shutdown the current agent and start a new one
26 changes: 26 additions & 0 deletions demo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "afj-demo",
"version": "1.0.0",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/hyperledger/aries-framework-javascript",
"directory": "demo/"
},
"license": "Apache-2.0",
"scripts": {
"alice": "ts-node src/AliceInquirer.ts",
"faber": "ts-node src/FaberInquirer.ts",
"refresh": "rm -rf ./node_modules ./yarn.lock && npm install"
},
"devDependencies": {
"@aries-framework/core": "^0.1.0",
"@aries-framework/node": "^0.1.0",
"@types/figlet": "^1.5.4",
"@types/inquirer": "^8.1.3",
"clear": "^0.1.0",
"commander": "^8.3.0",
"figlet": "^1.5.2",
"ts-node": "^10.4.0"
}
}
84 changes: 84 additions & 0 deletions demo/src/Alice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*eslint import/no-cycle: [2, { maxDepth: 1 }]*/
import type { CredentialRecord, ProofRecord } from '@aries-framework/core'

import { BaseAgent } from './BaseAgent'
import { greenText, Output, redText } from './OutputClass'

export class Alice extends BaseAgent {
public connectionRecordFaberId?: string
public connected: boolean

public constructor(port: number, name: string) {
super(port, name)
this.connected = false
}

public static async build(): Promise<Alice> {
const alice = new Alice(9000, 'alice')
await alice.initializeAgent()
return alice
}

private async getConnectionRecord() {
if (!this.connectionRecordFaberId) {
throw Error(redText(Output.missingConnectionRecord))
}
return await this.agent.connections.getById(this.connectionRecordFaberId)
}

private async printConnectionInvite() {
const invite = await this.agent.connections.createConnection()
this.connectionRecordFaberId = invite.connectionRecord.id

console.log(Output.connectionLink, invite.invitation.toUrl({ domain: `http://localhost:${this.port}` }), '\n')
return invite.connectionRecord
}

private async waitForConnection() {
const connectionRecord = await this.getConnectionRecord()

console.log('Waiting for Faber to finish connection...')
try {
await this.agent.connections.returnWhenIsConnected(connectionRecord.id)
} catch (e) {
console.log(redText(`\nTimeout of 20 seconds reached.. Returning to home screen.\n`))
return
}
console.log(greenText(Output.connectionEstablished))
this.connected = true
}

public async setupConnection() {
await this.printConnectionInvite()
await this.waitForConnection()
}

public async acceptCredentialOffer(credentialRecord: CredentialRecord) {
await this.agent.credentials.acceptOffer(credentialRecord.id)
console.log(greenText('\nCredential offer accepted!\n'))
}

public async acceptProofRequest(proofRecord: ProofRecord) {
const retrievedCredentials = await this.agent.proofs.getRequestedCredentialsForProofRequest(proofRecord.id, {
filterByPresentationPreview: true,
})
const requestedCredentials = this.agent.proofs.autoSelectCredentialsForProofRequest(retrievedCredentials)
await this.agent.proofs.acceptRequest(proofRecord.id, requestedCredentials)
console.log(greenText('\nProof request accepted!\n'))
}

public async sendMessage(message: string) {
const connectionRecord = await this.getConnectionRecord()
await this.agent.basicMessages.sendMessage(connectionRecord.id, message)
}

public async exit() {
console.log(Output.exit)
await this.agent.shutdown()
process.exit()
}

public async restart() {
await this.agent.shutdown()
}
}
130 changes: 130 additions & 0 deletions demo/src/AliceInquirer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import type { CredentialRecord, ProofRecord } from '@aries-framework/core'

import { clear } from 'console'
import { textSync } from 'figlet'
import inquirer from 'inquirer'

import { Alice } from './Alice'
import { BaseInquirer, ConfirmOptions } from './BaseInquirer'
import { Listener } from './Listener'
import { Title } from './OutputClass'

export const runAlice = async () => {
clear()
console.log(textSync('Alice', { horizontalLayout: 'full' }))
const alice = await AliceInquirer.build()
alice.processAnswer()
}

enum PromptOptions {
CreateConnection = 'Create connection invitation',
SendMessage = 'Send message',
Exit = 'Exit',
Restart = 'Restart',
}

export class AliceInquirer extends BaseInquirer {
public alice: Alice
public promptOptionsString: string[]
public listener: Listener

public constructor(alice: Alice) {
super()
this.alice = alice
this.listener = new Listener()
this.promptOptionsString = Object.values(PromptOptions)
this.listener.messageListener(this.alice.agent, this.alice.name)
}

public static async build(): Promise<AliceInquirer> {
const alice = await Alice.build()
return new AliceInquirer(alice)
}

private async getPromptChoice() {
if (this.alice.connectionRecordFaberId !== undefined) {
return inquirer.prompt([this.inquireOptions(this.promptOptionsString)])
}
const reducedOption = [PromptOptions.CreateConnection, PromptOptions.Exit, PromptOptions.Restart]
return inquirer.prompt([this.inquireOptions(reducedOption)])
}

public async processAnswer() {
const choice = await this.getPromptChoice()
if (this.listener.on === true) {
return
}
switch (choice.options) {
case PromptOptions.CreateConnection:
await this.connection()
break
case PromptOptions.SendMessage:
await this.message()
break
case PromptOptions.Exit:
await this.exit()
break
case PromptOptions.Restart:
await this.restart()
return
}
this.processAnswer()
}

public async acceptCredentialOffer(credentialRecord: CredentialRecord) {
const confirm = await inquirer.prompt([this.inquireConfirmation(Title.credentialOfferTitle)])
if (confirm.options === ConfirmOptions.No) {
await this.alice.agent.credentials.declineOffer(credentialRecord.id)
} else if (confirm.options === ConfirmOptions.Yes) {
await this.alice.acceptCredentialOffer(credentialRecord)
}
}

public async acceptProofRequest(proofRecord: ProofRecord) {
const confirm = await inquirer.prompt([this.inquireConfirmation(Title.proofRequestTitle)])
if (confirm.options === ConfirmOptions.No) {
await this.alice.agent.proofs.declineRequest(proofRecord.id)
} else if (confirm.options === ConfirmOptions.Yes) {
await this.alice.acceptProofRequest(proofRecord)
}
}

public async connection() {
await this.alice.setupConnection()
if (this.alice.connected === false) {
return
}
this.listener.credentialOfferListener(this.alice, this)
this.listener.proofRequestListener(this.alice, this)
}

public async message() {
const message = await this.inquireMessage()
if (message === null) {
return
}
this.alice.sendMessage(message)
}

public async exit() {
const confirm = await inquirer.prompt([this.inquireConfirmation(Title.confirmTitle)])
if (confirm.options === ConfirmOptions.No) {
return
} else if (confirm.options === ConfirmOptions.Yes) {
await this.alice.exit()
}
}

public async restart() {
const confirm = await inquirer.prompt([this.inquireConfirmation(Title.confirmTitle)])
if (confirm.options === ConfirmOptions.No) {
this.processAnswer()
return
} else if (confirm.options === ConfirmOptions.Yes) {
await this.alice.restart()
runAlice()
}
}
}

runAlice()
Loading

0 comments on commit 2f4fc4e

Please sign in to comment.