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

feat: new error handling #111

Merged
merged 39 commits into from
Mar 13, 2023
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
b747d44
release(core): v1.3.0
github-actions[bot] Jan 13, 2023
582b4ba
chore: update release-please config (#99)
martines3000 Jan 13, 2023
6b02be4
feat: add resolveDID RPC method (#78)
andyv09 Jan 13, 2023
162e7af
feat: update deployment env (#91)
martines3000 Jan 13, 2023
6e8afd2
feat: add did:pkh (#76)
andyv09 Jan 13, 2023
1dc5101
fix: remove infura token (#93)
andyv09 Jan 13, 2023
49253df
chore: update snaps-cli to 0.27.1 (#92)
andyv09 Jan 14, 2023
23594fe
fix: fixes provider bug (#100)
andyv09 Jan 24, 2023
cbe57bf
feat: switch to pnpm (#80)
andyv09 Jan 24, 2023
5d14880
chore: add versions table to readme (#103)
andyv09 Jan 24, 2023
d38acef
chore: fixes docker build (#104)
martines3000 Jan 24, 2023
c68915d
chore: adds new dapp project (#105)
martines3000 Jan 25, 2023
1ca0186
chore: add team member (#106)
Vid201 Jan 26, 2023
83fd625
chore: update readme (#110)
martines3000 Feb 21, 2023
10938c2
chore: update veramo (#109)
martines3000 Feb 23, 2023
4fb7670
chore: skip Ceramic tests until fixed
martines3000 Feb 23, 2023
3099122
feat: return Result from onRpcRequest
martines3000 Feb 23, 2023
5c87d7f
chore: uncomment tests and use it.skip instead
martines3000 Feb 23, 2023
3bce162
feat: split utils into a seperate package
martines3000 Feb 23, 2023
a70bd72
chore: disable ceramic tests (#113)
martines3000 Feb 23, 2023
27dee16
chore: update deps (#112)
martines3000 Feb 23, 2023
576278b
Merge branch 'develop' into feat/new-error-handling
martines3000 Feb 23, 2023
9f8f55d
chore: merge develop
martines3000 Feb 28, 2023
8f5801c
Merge branch 'develop' into feat/new-error-handling
martines3000 Mar 7, 2023
fca21ac
fix: fxies onRpcRequests
martines3000 Mar 8, 2023
a569d17
fix: fixes some types, adds jsdoc comments
martines3000 Mar 8, 2023
42f1add
feat: finish updating connector
martines3000 Mar 8, 2023
0c4d091
chore: remove ethereum.on()
martines3000 Mar 8, 2023
78080a3
chore: undo unnecessary changes
martines3000 Mar 8, 2023
16f5dd1
fix: undo broken vcmanager test:ci
martines3000 Mar 8, 2023
8ec42b9
Merge branch 'develop' into feat/new-error-handling
martines3000 Mar 8, 2023
bdcf753
chore: update package.json
martines3000 Mar 8, 2023
00e0a25
fix: exclude website from build, lint, test steps
martines3000 Mar 8, 2023
b30208a
fix: ignore website in CI
martines3000 Mar 8, 2023
40909f6
fix: update tests, some jsdoc comments, errors
martines3000 Mar 9, 2023
2774e7a
fix: fix assertion issue
martines3000 Mar 9, 2023
f75cac7
fix: fixes tests
martines3000 Mar 9, 2023
3b39d7b
feat: add tsup and fix build issues
martines3000 Mar 10, 2023
b113e96
fix: fixes based on PR feedback
martines3000 Mar 13, 2023
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
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ jobs:
init-commands: |
pnpm nx-cloud start-ci-run --stop-agents-after="build" --agent-count=3
parallel-commands-on-agents: |
pnpm nx affected --target=lint --parallel=3
pnpm nx affected --target=test:ci --parallel=3
pnpm nx affected --target=build --parallel=3
pnpm nx affected --target=lint --exclude @blockchain-lab-um/website --parallel=3
pnpm nx affected --target=test:ci --exclude @blockchain-lab-um/website --parallel=3
pnpm nx affected --target=build --exclude @blockchain-lab-um/website --parallel=3

agents:
name: Nx Cloud - Agents
Expand Down
10 changes: 10 additions & 0 deletions libs/utils/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
root: true,
extends: ['../../.eslintrc.js'],
parserOptions: {
project: './tsconfig.eslint.json',
sourceType: 'module',
tsconfigRootDir: __dirname,
},
rules: {},
};
4 changes: 4 additions & 0 deletions libs/utils/.lintstagedrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
'*.{js,ts}': ['eslint --fix'],
'*.{md,json,yml,yaml}': ['prettier --write'],
};
4 changes: 4 additions & 0 deletions libs/utils/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dist
node_modules
coverage
CHANGELOG.md
10 changes: 10 additions & 0 deletions libs/utils/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Utils

Library containing utility functions used thought the monorepo.

## License

This project is dual-licensed under Apache 2.0 and MIT terms:

- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
38 changes: 38 additions & 0 deletions libs/utils/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "@blockchain-lab-um/utils",
"version": "1.0.0",
"private": "true",
"description": "Helper utilities for SSI Snap monorepo",
"keywords": [],
"repository": {
"type": "git",
"url": "https://github.com/blockchain-lab-um/ssi-snap.git"
},
"license": "(Apache-2.0 AND MIT)",
"author": {
"name": "Blockchain Lab:UM",
"email": "blockchain-lab@um.si",
"url": "https://blockchain-lab.um.si"
},
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist/",
"package.json",
"README.md",
"LICENSE"
],
"scripts": {
"build": "pnpm clean && pnpm compile",
"clean": "rimraf dist",
"compile": "tsc --build tsconfig.build.json",
"lint": "pnpm lint:eslint && pnpm lint:prettier",
"lint:eslint": "eslint .",
"lint:prettier": "prettier . --check"
},
"devDependencies": {
"rimraf": "^3.0.2",
"typescript": "^4.9.5"
}
}
1 change: 1 addition & 0 deletions libs/utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './result';
30 changes: 30 additions & 0 deletions libs/utils/src/result.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export type Result<T> = {
success: boolean;
} & (
| {
success: true;
data: T;
}
| {
success: false;
error: Error;
}
);

export const isError = <T>(
result: Result<T>
): result is { success: false; error: Error } => !result.success;

export const isSuccess = <T>(
result: Result<T>
): result is { success: true; data: T } => result.success;

export class ResultObject {
static success<T>(data: T): Result<T> {
return { success: true, data };
}

static error<T>(error: Error): Result<T> {
return { success: false, error };
}
}
8 changes: 8 additions & 0 deletions libs/utils/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"exclude": [
// Exclude all test files
"tests/**/*",
"*.spec.ts"
]
}
4 changes: 4 additions & 0 deletions libs/utils/tsconfig.eslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"include": ["**/*", ".eslintrc.js"]
}
13 changes: 13 additions & 0 deletions libs/utils/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"experimentalDecorators": true,
"outDir": "./dist",
"baseUrl": ".",
"typeRoots": ["./node_modules/@types", "../../node_modules/@types"],
"declaration": true,
"inlineSourceMap": true
},
"files": [],
"include": ["src/**/*", "tests/**/*"]
}
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@
"packages/*"
],
"scripts": {
"build": "pnpm nx affected --target=build",
"build": "pnpm nx affected --target=build --exclude @blockchain-lab-um/website",
"build:all": "pnpm nx run-many --target=build --all",
"build:connector": "pnpm nx build @blockchain-lab-um/ssi-snap-connector",
"build:docker": "pnpm nx run-many --target=build --projects=@blockchain-lab-um/ssi-snap-docs,@blockchain-lab-um/website && pnpm nx run @blockchain-lab-um/dapp:build:docker",
"build:docs": "pnpm nx build @blockchain-lab-um/ssi-snap-docs",
"build:vcmanager": "pnpm nx build @blockchain-lab-um/veramo-vc-manager",
"deploy:docs": "pnpm nx deploy @blockchain-lab-um/ssi-snap-docs",
"docker:build": "docker build . -t blockchain-lab-um/ssi-snap",
"lint": "pnpm prettier && pnpm nx affected --target=lint",
"lint": "pnpm prettier && pnpm nx affected --target=lint --exclude @blockchain-lab-um/website",
"lint:all": "pnpm prettier && pnpm nx run-many --target=lint --all",
"prepare": "is-ci || husky install",
"prettier": "prettier --write .",
Expand All @@ -45,9 +45,9 @@
"start:dapp": "pnpm nx start @blockchain-lab-um/website",
"start:docs": "pnpm nx start @blockchain-lab-um/ssi-snap-docs",
"start:snap": "pnpm nx start @blockchain-lab-um/ssi-snap",
"test": "pnpm nx affected --target=test",
"test": "pnpm nx affected --target=test --exclude @blockchain-lab-um/website",
"test:all": "pnpm nx run-many --target=test --all",
"test:ci": "pnpm nx affected --target=test:ci"
"test:ci": "pnpm nx affected --target=test:ci --exclude @blockchain-lab-um/website"
},
"devDependencies": {
"@commitlint/cli": "^17.4.4",
Expand Down
2 changes: 2 additions & 0 deletions packages/connector/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
},
"dependencies": {
"@blockchain-lab-um/ssi-snap-types": "*",
"@blockchain-lab-um/utils": "*",
"@metamask/detect-provider": "^2.0.0",
"@veramo/core": "^5.0.0"
},
"devDependencies": {
Expand Down
109 changes: 67 additions & 42 deletions packages/connector/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,81 +1,106 @@
import { AvailableMethods } from '@blockchain-lab-um/ssi-snap-types';

import { MetaMaskSSISnap } from './snap';
import {
hasMetaMask,
isMetamaskSnapsSupported,
isSnapInstalled,
} from './utils';
AvailableMethods,
isAvailableMethods,
} from '@blockchain-lab-um/ssi-snap-types';
import { Result, ResultObject, isError } from '@blockchain-lab-um/utils';
import detectEthereumProvider from '@metamask/detect-provider';

const defaultSnapOrigin = 'npm:@blockchain-lab-um/ssi-snap';
import { MetaMaskSSISnap } from './snap';

export { MetaMaskSSISnap } from './snap';
export {
hasMetaMask,
isMetamaskSnapsSupported,
isSnapInstalled,
} from './utils';
export { isSnapInstalled } from './utils';

export type SnapInstallationParams = {
snapId?: string;
version?: string;
supportedMethods?: Array<AvailableMethods>;
};

const defaultSnapOrigin = 'npm:@blockchain-lab-um/ssi-snap';

/**
* Install and enable SSI Snap
*
* Checks for existence of Metamask and version compatibility with snaps before installation.
*
* Checks for existence of MetaMask Flask and installs SSI Snap if not installed
*
* @param snapInstallationParams - set snapID, version and a list of supported methods
*
*
* @return MetaMaskSSISnap - adapter object that exposes snap API
*/
export async function enableSSISnap(
snapInstallationParams: SnapInstallationParams = {}
): Promise<MetaMaskSSISnap> {
): Promise<Result<MetaMaskSSISnap>> {
const {
snapId = defaultSnapOrigin,
version = 'latest',
version = '^1.4.0',
supportedMethods = ['did:ethr'],
} = snapInstallationParams;

// check all conditions
if (!hasMetaMask()) {
throw new Error('Metamask is not installed');
// This resolves to the value of window.ethereum or null
const provider = await detectEthereumProvider({ mustBeMetaMask: true });

if (!provider) {
return ResultObject.error(new Error('No provider found'));
}
if (!(await isMetamaskSnapsSupported())) {
throw new Error("Current Metamask version doesn't support snaps");

// web3_clientVersion returns the installed MetaMask version as a string
const mmVersion: string = await window.ethereum.request({
method: 'web3_clientVersion',
});

if (!mmVersion.includes('flask')) {
return ResultObject.error(
new Error('MetaMask is not supported. Please install MetaMask Flask.')
);
}

const isInstalled = await isSnapInstalled(snapId, version);
// FIXME (martin): I don't think we need this check anymore
// wallet_requestSnaps handles this and allows the use of semver ranges

// const isInstalled = await isSnapInstalled(snapId, version);

if (!isInstalled) {
// if (isError(isInstalled)) {
// return ResultObject.error(isInstalled.error);
// }

try {
await window.ethereum.request({
method: 'wallet_requestSnaps',
params: {
[snapId]: { version },
},
});
}

// create snap describer
const snap = new MetaMaskSSISnap(snapId, supportedMethods);

// initialize snap
const snapApi = await snap.getSSISnapApi();
console.log('Getting DID method...');
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
const method = await snapApi.getSelectedMethod();
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
if (!snap.supportedMethods.includes(method as AvailableMethods)) {
console.log('Switching method...', method, snap.supportedMethods[0]);
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await snapApi.switchDIDMethod(snap.supportedMethods[0]);
}
const snap = new MetaMaskSSISnap(snapId, supportedMethods);

const snapApi = snap.getSSISnapApi();

const selectedMethodsResult = await snapApi.getSelectedMethod();

if (isError(selectedMethodsResult)) {
return ResultObject.error(selectedMethodsResult.error);
}

// return snap object
return snap;
const method = selectedMethodsResult.data;

if (!isAvailableMethods(method)) {
const switchResult = await snapApi.switchDIDMethod(
snap.supportedMethods[0]
);

if (isError(switchResult)) {
return ResultObject.error(switchResult.error);
}

if (!switchResult.data) {
return ResultObject.error(
new Error('Could not switch to supported DID method')
);
}
}

return ResultObject.success(snap);
} catch (err: unknown) {
return ResultObject.error(err as Error);
}
}
Loading