Skip to content

Commit

Permalink
feat: ECDSAKeyIdentity (#591)
Browse files Browse the repository at this point in the history
* using spki encoding for DER-encoding

* allow providing a SubtleCrypto interface

* changelog and readme

* pulling lint out to separate job

* switching to isomomorphic-fetch

* fixing authclient tests after jest update

* e2e browser tests for identity
  • Loading branch information
krpeacock committed Jul 22, 2022
1 parent 05e12ec commit 245b029
Show file tree
Hide file tree
Showing 48 changed files with 30,853 additions and 12,440 deletions.
1 change: 0 additions & 1 deletion .github/workflows/e2e-tests.yml
Expand Up @@ -31,7 +31,6 @@ jobs:
- run: npm install -g npm

- run: npm install
- run: npm run lint --workspaces --if-present

# build monorepo incl. each subpackage
- run: npm run build --workspaces --if-present
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/lint.yml
@@ -0,0 +1,30 @@
name: Check Lint
on:
pull_request:
types:
- opened
- reopened
- edited
- synchronize

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [ubuntu-18.04]
ghc: ['8.8.4']
spec:
- release-0.16 # https://github.com/dfinity-lab/ic-ref/tree/release-0.16
node:
- 14
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node }}
- run: npm install -g npm
- run: npm install
- run: npm run lint --workspaces --if-present
1 change: 0 additions & 1 deletion .github/workflows/unit-tests.yml
Expand Up @@ -33,7 +33,6 @@ jobs:
- run: npm install -g npm

- run: npm install
- run: npm run lint --workspaces --if-present

# build monorepo incl. each subpackage
- run: npm run build --workspaces --if-present
Expand Down
1 change: 1 addition & 0 deletions demos/ledgerhq/package.json
Expand Up @@ -14,6 +14,7 @@
"process": "^0.11.10",
"protobufjs": "^6.10.2",
"stream-browserify": "^3.0.0",
"ts-node": "^10.8.2",
"util": "^0.12.3",
"webpack": "^5.24.1",
"webpack-cli": "^4.5.0",
Expand Down
1 change: 1 addition & 0 deletions demos/sample-javascript/package.json
Expand Up @@ -11,6 +11,7 @@
"html-webpack-plugin": "^5.1.0",
"process": "^0.11.10",
"stream-browserify": "^3.0.0",
"ts-node": "^10.8.2",
"util": "^0.12.3",
"webpack": "^5.24.1",
"webpack-cli": "^4.5.0",
Expand Down
10 changes: 10 additions & 0 deletions docs/generated/changelog.html
Expand Up @@ -10,9 +10,19 @@
<h1>Agent-JS Changelog</h1>

<section>
<h2>Version 0.12.2</h2>
<ul>
<li>
Support for the SubtleCrypto interface in @dfinity/identity using the new ECDSAKeyIdentity
</li>
</ul>
<h2>Version 0.12.1</h2>
<ul>
<li>Adds inline sourcemaps to packages</li>
<li>
Pulls lint out to a separate job now that Node 12 is failing with latest eslint
dependencies
</li>
<li>Adds UTF-8 as an encoding option for CanisterStatus custom paths</li>
<li>
Adds a public method "createReadStateRequest" that creates the request for "readState".
Expand Down
2 changes: 2 additions & 0 deletions e2e/browser/.gitignore
@@ -0,0 +1,2 @@
.parcel-cache
src/declarations
5 changes: 5 additions & 0 deletions e2e/browser/.proxyrc
@@ -0,0 +1,5 @@
{
"/api": {
"target": "http://localhost:8000/",
}
}
12 changes: 12 additions & 0 deletions e2e/browser/cypress.config.js
@@ -0,0 +1,12 @@
/* eslint-disable no-undef */
/* eslint-disable @typescript-eslint/no-var-requires */
const { defineConfig } = require('cypress');

module.exports = defineConfig({
video: false,
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
6 changes: 6 additions & 0 deletions e2e/browser/cypress/.eslintrc.json
@@ -0,0 +1,6 @@
{
"plugins": ["cypress"],
"env": {
"cypress/globals": true
}
}
44 changes: 44 additions & 0 deletions e2e/browser/cypress/e2e/ecdsa.cy.js
@@ -0,0 +1,44 @@
import { ECDSAKeyIdentity } from '@dfinity/identity';
import { get, set } from 'idb-keyval';
import { createActor } from '../utils/actor';
import ids from '../../.dfx/local/canister_ids.json';
const canisterId = ids.whoami.local;

const setup = async () => {
const identity1 = await ECDSAKeyIdentity.generate();
const whoami1 = createActor(ids.whoami.local, { agentOptions: { identity: identity1 } });

const principal1 = await whoami1.whoami();

return { principal1, whoami1, identity1 };
};

describe('ECDSAKeyIdentity tests with SubtleCrypto', () => {
it('generates a new identity', () => {
cy.visit('http://localhost:1234');
cy.window().then(async window => {
const { principal1 } = await setup();
const str = principal1.toString();
expect(str).to.be.an('string');
});
});
it('can persist an identity in indexeddb', () => {
cy.visit('http://localhost:1234');
cy.window().then(async window => {
const { principal1, identity1 } = await setup();
const str = principal1.toString();
expect(str).to.be.an('string');

await set('keyPair', identity1.getKeyPair());
const storedKeyPair = await get('keyPair');

const identity2 = await ECDSAKeyIdentity.fromKeyPair(storedKeyPair);

const whoami2 = createActor(canisterId, { agentOptions: { identity: identity2 } });

const principal2 = await whoami2.whoami();

expect(principal2.toString()).to.equal(str);
});
});
});
5 changes: 5 additions & 0 deletions e2e/browser/cypress/fixtures/example.json
@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions e2e/browser/cypress/support/commands.js
@@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
20 changes: 20 additions & 0 deletions e2e/browser/cypress/support/e2e.js
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/e2e.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands';

// Alternatively you can use CommonJS syntax:
// require('./commands')
25 changes: 25 additions & 0 deletions e2e/browser/cypress/utils/actor.js
@@ -0,0 +1,25 @@
import { Actor, HttpAgent } from '@dfinity/agent';

// Imports and re-exports candid interface
import { idlFactory } from '../../src/declarations/whoami/whoami.did.js';
export { idlFactory } from '../../src/declarations/whoami/whoami.did.js';
// CANISTER_ID is replaced by webpack based on node environment

/**
*
* @param {string | import("@dfinity/principal").Principal} canisterId Canister ID of Agent
* @param {{agentOptions?: import("@dfinity/agent").HttpAgentOptions; actorOptions?: import("@dfinity/agent").ActorConfig}} [options]
* @return {import("@dfinity/agent").ActorSubclass<import("./whoami.did.js")._SERVICE>}
*/
export const createActor = (canisterId, options) => {
const agent = new HttpAgent({ ...options?.agentOptions });

agent.fetchRootKey();

// Creates an actor with using the candid interface and the HttpAgent
return Actor.createActor(idlFactory, {
agent,
canisterId,
...options?.actorOptions,
});
};
8 changes: 8 additions & 0 deletions e2e/browser/dfx.json
@@ -0,0 +1,8 @@
{
"canisters": {
"whoami": {
"type": "motoko",
"main": "src/whoami/main.mo"
}
}
}

0 comments on commit 245b029

Please sign in to comment.