Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Requirements #85

Merged
merged 5 commits into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ In case you have an [openprofile](https://openprofile.dev/) with the same mail a

### Why should I add my digital wallet or agent?

We strive to create a comprehensive and unbiased platform where every provider can showcase their solution at no cost. Recognising the challenge in quantifying subjective aspects, such as user-friendliness, our focus is on objective parameters. These include resource links and compliance with specific standards, ensuring clear, fact-based comparisons. By allowing and encouraging community contributions through pull requests, we maintain an up-to-date and inclusive matrix. Your active participation by submitting updates or new entries is invaluable, as it not only ensures the overview is correct and complete, but also supports a more informed and diverse user base.
We strive to create a comprehensive and unbiased platform where every provider can showcase their solution at no cost. Recognizing the challenge in quantifying subjective aspects, such as user-friendliness, our focus is on objective parameters. These include resource links and compliance with specific standards, ensuring clear, fact-based comparisons. By allowing and encouraging community contributions through pull requests, we maintain an up-to-date and inclusive matrix. Your active participation by submitting updates or new entries is invaluable, as it not only ensures the overview is correct and complete, but also supports a more informed and diverse user base.

### How can I add my digital wallet or agent?

Contributing to the overview can be done through filling in the form provided when clicking "Add Wallet/agent" in the upper right corner of the overview. The created JSON file can be submitted via a GITHUB pull request.

## Target Audience

This overview should be usable by persons and organisations. Anyone willing to use digital wallets or agents for digital credential purposes should be able to objectively compare the characteristics of wallets/agents and create a short-list of candidates for their use case. It can also serve as resource for market awareness and visibility of wallets/agents for wallet/agent vendors.
This overview should be usable by persons and organizations. Anyone willing to use digital wallets or agents for digital credential purposes should be able to objectively compare the characteristics of wallets/agents and create a short-list of candidates for their use case. It can also serve as resource for market awareness and visibility of wallets/agents for wallet/agent vendors.

## Scoping

Expand All @@ -38,6 +39,12 @@ Included in the overview are holder agents+wallets, issuer agents and verifier a

This SIG was accepted by the TAC on [September 20, 2023](../meetings/2023/2023-09-20.md). See [Digital Wallet and Agent Overviews SIG Proposal](https://github.com/openwallet-foundation/tac/issues/56) for more details.

There is a strong connection with the [credential format comparison SIG](https://github.com/openwallet-foundation/credential-format-comparison-sig). The credential formats are incorporated as separate characterics (columns) in the overview, forming the basis of the technology stack.
There is a strong connection with the [credential format comparison SIG](https://github.com/openwallet-foundation/credential-format-comparison-sig). The credential formats are incorporated as separate characteristics (columns) in the overview, forming the basis of the technology stack.

We foresee that the safe wallet SIG provided us with new characteristics in the category of 'Security'.

## Dependencies

Each wallet and agent is capable to link to relevant dependencies like frameworks or libraries that are relevant. The linking will support the overview of the technology stack of the wallet or agent. We encourage developers to only link to relevant dependencies that are specific for the wallet or agent to avoid a long list of dependencies.

The dependencies will be add as a new object in the `dependencies` folder and then linked by the unique `name` attribute in each wallet or agent object.
7 changes: 7 additions & 0 deletions dependencies/bifold.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "../viewer/src/assets/dependency.schema.json",
"name": "Bifold",
"url": "https://github.com/openwallet-foundation/bifold-wallet",
"description": "Aries Mobile Agent React Native - Part of the Aries Bifold effort to provide SSI capabilities in a production ready app.",
"community": "https://discord.gg/openwalletfoundation"
}
7 changes: 7 additions & 0 deletions dependencies/credo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "../viewer/src/assets/dependency.schema.json",
"name": "Credo",
"url": "https://github.com/openwallet-foundation/credo-ts",
"description": "Typescript framework for building decentralized identity and verifiable credential solutions",
"community": "https://discord.gg/openwalletfoundation"
}
7 changes: 7 additions & 0 deletions dependencies/sd-jwt-js.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "../viewer/src/assets/dependency.schema.json",
"name": "SD-JWT-JS",
"url": "https://github.com/openwallet-foundation-labs/sd-jwt-js",
"description": "A TypeScript implementation of the Selective Disclosure JWT (SD-JWT) spec.",
"community": "https://discord.gg/openwalletfoundation"
}
21 changes: 17 additions & 4 deletions viewer/scripts/merge-wallets.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,29 @@ const commitHistoryBase = 'https://github.com/openwallet-foundation/digital-wall

// function to merge all the individual wallet files into a single file
const files = readdirSync('../wallets');
// const wallets = files.map(file => JSON.parse(readFileSync(`../wallets/${file}`)));
const wallets = []
for (const file of files) {
try {
const json = JSON.parse(readFileSync(`../wallets/${file}`))
json.commitHistory = commitHistoryBase + file
const json = JSON.parse(readFileSync(`../wallets/${file}`));
json.commitHistory = commitHistoryBase + file;
// for now we insert the dependencies instead of just referencing them
if(json.dependencies) {
json.dependencies = json.dependencies.map(dependencies => {
try {
const content = JSON.parse(readFileSync(`../dependencies/${dependencies}.json`));
content['$schema'] = undefined;
return content;
}
catch(e) {
console.warn(`Error parsing ${dependencies}.json: ${e}`)
return dependencies;
}
});
}
wallets.push(json)
}
catch(e) {
console.warn(`Error parsing ${file}: ${e}`)
}
}
writeFileSync('src/assets/wallets.json', JSON.stringify(wallets, null, 2));
writeFileSync('src/assets/wallets.json', JSON.stringify(wallets));
13 changes: 12 additions & 1 deletion viewer/scripts/scale-images.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ const resizeImagesInFolder = async (inputFolder, outputFolder, maxWidth) => {
}
};

const overrideFolder = (inputFolder, outputFolder) => {
// move all files from inputFolder to outputFolder
const files = fs.readdirSync(inputFolder);
for (const file of files) {
const inputPath = path.join(inputFolder, file);
const outputPath = path.join(outputFolder, file);
fs.copyFileSync(inputPath, outputPath);
}
fs.rmSync(inputFolder, { recursive: true });
}

resizeImagesInFolder(inputFolder, outputFolder, maxWidth)
.then(() => console.log('Image resizing completed.'))
.then(() => overrideFolder(outputFolder, inputFolder))
.catch(error => console.error('An error occurred:', error));
77 changes: 59 additions & 18 deletions viewer/scripts/validate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,65 @@ import axios from 'axios';

const ajv = new Ajv({allowUnionTypes: true});
addFormats(ajv);
const profileSIGSchema = await axios.get('https://openwallet-foundation.github.io/credential-format-comparison-sig/assets/schemas/fields.json').then(res => res.data);
ajv.addSchema(profileSIGSchema, "https://openwallet-foundation.github.io/credential-format-comparison-sig/assets/schemas/fields.json");
const validate = ajv.compile(JSON.parse(readFileSync('src/assets/schema.json')));
const files = readdirSync('../wallets');
let success = true;
files.map(file => {
const wallet = JSON.parse(readFileSync(`../wallets/${file}`))
if(!validate(wallet)) {
console.error(`Error validating ${file}:`);
console.error(JSON.stringify(validate.errors, null, 2));
success = false;
const dependencyNames = [];

// validate dependencies
function validateDependencies() {
const validate = ajv.compile(JSON.parse(readFileSync('src/assets/dependency.schema.json')));
const files = readdirSync('../dependencies');
let success = true;
files.map(file => {
const dependency = JSON.parse(readFileSync(`../dependencies/${file}`))
if(!validate(dependency)) {
console.error(`Error validating ${file}:`);
console.error(JSON.stringify(validate.errors, null, 2));
success = false;
}
if(dependencyNames.includes(dependency.name)) {
console.error(`Duplicate dependency name: ${dependency.name}`);
success = false;
}
dependencyNames.push(dependency.name);
});
if(success) {
console.info('All dependencies are valid');
} else {
console.error('Some dependencies are invalid');
process.exit(1);
}
});
if(success) {
console.info('All wallets are valid');
} else {
console.error('Some wallets are invalid');
//TODO: Since all wallet entries are not updated yet, do not finish with an exit code 1
// process.exit(1);
}

validateDependencies();
validateWallets();

async function validateWallets() {
const profileSIGSchema = await axios.get('https://openwallet-foundation.github.io/credential-format-comparison-sig/assets/schemas/fields.json').then(res => res.data);
ajv.addSchema(profileSIGSchema, "https://openwallet-foundation.github.io/credential-format-comparison-sig/assets/schemas/fields.json");
const validate = ajv.compile(JSON.parse(readFileSync('src/assets/schema.json')));
const files = readdirSync('../wallets');
let success = true;
files.map(file => {
const wallet = JSON.parse(readFileSync(`../wallets/${file}`))
if(!validate(wallet)) {
console.error(`Error validating ${file}:`);
console.error(JSON.stringify(validate.errors, null, 2));
success = false;
}
// validate the dependencies if the key is a valid one
if(wallet.dependencies) {
for(const dependency of wallet.dependencies) {
if(!dependencyNames.includes(dependency)) {
console.error(`dependency ${dependency} not found in dependencies`);
success = false;
}
}
}

});
if(success) {
console.info('All wallets are valid');
} else {
console.error('Some wallets are invalid');
process.exit(1);
}
}
27 changes: 21 additions & 6 deletions viewer/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
<mat-toolbar color="primary" fxLayout="row" fxLayoutAlign="start center">
<span>Digital Wallet and Agent overview</span>
<div class="spacer"></div>
<button mat-button (click)="addWallet()">Add Wallet</button>
<button mat-button (click)="showInfo()">Info</button>
<div class="github">
<div fxLayout="row" fxLayoutAlign="start center" fxHide.xs="true">
<button mat-button (click)="addWallet()">Add Wallet</button>
<button mat-button (click)="showInfo()">Info</button>
<div class="github">
<a
mat-button
href="https://github.com/openwallet-foundation/digital-wallet-and-agent-overviews-sig"
><img src="assets/github.svg" alt="Github" /> <span>Github</span></a
>
</div>
</div>
<button mat-icon-button [matMenuTriggerFor]="menu" fxHide.gt-xs="true">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="addWallet()">Add Wallet</button>
<button mat-menu-item (click)="showInfo()">Info</button>
<a
mat-button
mat-menu-item
href="https://github.com/openwallet-foundation/digital-wallet-and-agent-overviews-sig"
><img src="assets/github.svg" alt="Github" /> <span>Github</span></a
>
</div>
<span>Github</span>
</a>
</mat-menu>
</mat-toolbar>
<router-outlet></router-outlet>
16 changes: 13 additions & 3 deletions viewer/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, RouterOutlet } from '@angular/router';
import { RouterModule } from '@angular/router';
import { MatToolbarModule } from '@angular/material/toolbar';
import {} from '@angular/common/http';
import { MatDialog } from '@angular/material/dialog';
import { InfoComponent } from './info/info.component';
import { MatButtonModule } from '@angular/material/button';
import { WalletsAddComponent } from './wallets-add/wallets-add.component';
import { FlexLayoutModule } from '@ngbracket/ngx-layout';
import { MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';

@Component({
selector: 'app-root',
standalone: true,
imports: [RouterModule, CommonModule, MatToolbarModule, MatButtonModule],
imports: [
RouterModule,
CommonModule,
MatToolbarModule,
MatButtonModule,
FlexLayoutModule,
MatMenuModule,
MatIconModule,
],
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
})
Expand Down
19 changes: 18 additions & 1 deletion viewer/src/app/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,25 @@ export interface Wallet {
// which trust management from the trust management comparison SIG are supported
trustManagements?: string[];
// link to Github to see the commit history of the file (generated by scripts/merge-wallets.mjs)
commitHistory?: string
commitHistory?: string;
// list of relevant dependencies that should be mentioned
dependencies?: Dependency[];
}

/**
* A dependency of a wallet
*/
export class Dependency {
// a unique name of the dependency
name!: string;
// a link to the dependency, ideally to the github repository to fetch the latest version
url!: string;
// a short description of the dependency
description?: string;
// a link to interact with the community of the dependency, e.g. a link to the slack or discord channel
community?: string;
}

export interface Definition {
description: string;
type: string;
Expand Down
20 changes: 20 additions & 0 deletions viewer/src/app/wallets-list/wallets-list.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<td mat-cell *matCellDef="let element">
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
<img
fxHide.xs="true"
[src]="walletsService.getLogo(element.logo)"
class="logo"
alt="Logo of the wallet"
Expand Down Expand Up @@ -173,6 +174,25 @@
{{ element.portability }}
</td>
</ng-container>
<ng-container matColumnDef="dependencies">
<th
mat-header-cell
*matHeaderCellDef
mat-sort-header
[matTooltip]="walletsService.getTooltip('dependencies')"
>
Dependencies
</th>
<td mat-cell *matCellDef="let element">
<div fxLayout="column" fxLayoutGap="16px">
@for (dependency of element.dependencies; track dependency) {
<a matListItemLine target="_blank" [href]="dependency.url">{{
dependency.name
}}</a>
}
</div>
</td>
</ng-container>
@for (resource of walletsService.resources; track resource) {
<ng-container [matColumnDef]="resource.id">
<th
Expand Down
12 changes: 10 additions & 2 deletions viewer/src/app/wallets-list/wallets-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
WalletFilter,
WalletsListFilterComponent,
} from '../wallets-list-filter/wallets-list-filter.component';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';

type Colums =
| 'name'
Expand Down Expand Up @@ -62,6 +63,7 @@ export class WalletsListComponent implements OnInit, AfterViewInit {
'capability',
'portability',
'linkToApp',
'dependencies',
];

//reference to the paginator to be added to the table
Expand All @@ -72,13 +74,19 @@ export class WalletsListComponent implements OnInit, AfterViewInit {
//columns to be displayed in the table, not implemeneted yet
displayedColumns: string[] = [];
filter?: WalletFilter;
mobile = false;

constructor(
public walletsService: WalletsService,
private dialog: MatDialog,
private route: ActivatedRoute,
private router: Router
) {}
private router: Router,
private breakpointObserver: BreakpointObserver
) {
this.breakpointObserver
.observe([Breakpoints.XSmall])
.subscribe((res) => (this.mobile = res.matches));
}

/**
* Fetches the wallets from the json file and sets the dataSource to the wallets
Expand Down
Loading