Skip to content

Commit

Permalink
add sdk-development compliance validation to CI (#291)
Browse files Browse the repository at this point in the history
* Add sdk-development test harness
  • Loading branch information
finn-block committed Mar 19, 2024
1 parent b0de4ff commit f92b90c
Show file tree
Hide file tree
Showing 9 changed files with 705 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/tests-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,10 @@ jobs:
- file: packages/api/src/index.ts
docsReporter: api-extractor
docsGenerator: typedoc-markdown
web5-spec:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: TBD54566975/sdk-development@v0.2.3
9 changes: 9 additions & 0 deletions .web5-spec/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM node:18-alpine
RUN apk add --no-cache git python3 make g++
ADD . /web5-js
WORKDIR /web5-js
RUN npm ci --ws
RUN npm install --no-save express express-openapi
RUN npm run build
RUN npx tsc -p .web5-spec/tsconfig.json
CMD ["node", ".web5-spec/dist/main.js"]
3 changes: 3 additions & 0 deletions .web5-spec/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# web5-spec

this directory contains glue to allow [our standardized test suite](https://github.com/TBD54566975/sdk-development) to run against the web5-js SDK.
53 changes: 53 additions & 0 deletions .web5-spec/credentials.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Request, Response } from 'express';
import { VerifiableCredential, SignOptions } from '@web5/credentials';
import { DidKeyMethod, PortableDid } from '@web5/dids';
import { Ed25519, Jose } from '@web5/crypto';
import { paths } from './openapi.js';

type Signer = (data: Uint8Array) => Promise<Uint8Array>;

let _ownDid: PortableDid;

async function getOwnDid(): Promise<PortableDid> {
if(_ownDid) {
return _ownDid;
}
_ownDid = await DidKeyMethod.create();
return _ownDid;
}

export async function credentialIssue(req: Request, res: Response) {
const body: paths["/credentials/issue"]["post"]["requestBody"]["content"]["application/json"] =
req.body;

const ownDid = await getOwnDid()

// build signing options
const [signingKeyPair] = ownDid.keySet.verificationMethodKeys!;
const privateKey = (await Jose.jwkToKey({ key: signingKeyPair.privateKeyJwk!})).keyMaterial;
const subjectIssuerDid = body.credential.credentialSubject["id"] as string;
const signer = EdDsaSigner(privateKey);
const signOptions: SignOptions = {
issuerDid : ownDid.did,
subjectDid : subjectIssuerDid,
kid : '#' + ownDid.did.split(':')[2],
signer : signer
};

const vc: VerifiableCredential = VerifiableCredential.create(body.credential.type[body.credential.type.length - 1], body.credential.issuer, subjectIssuerDid, body.credential.credentialSubject);
const vcJwt: string = await vc.sign(signOptions);

const resp: paths["/credentials/issue"]["post"]["responses"]["200"]["content"]["application/json"] =
{
verifiableCredential: {data: vcJwt}
};

res.json(resp);
}

function EdDsaSigner(privateKey: Uint8Array): Signer {
return async (data: Uint8Array): Promise<Uint8Array> => {
const signature = await Ed25519.sign({ data, key: privateKey});
return signature;
};
}
15 changes: 15 additions & 0 deletions .web5-spec/did-ion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { DidIonMethod } from "@web5/dids";
import { paths } from "./openapi.js";
import { Request, Response } from "express";


export async function didIonCreate(req: Request, res: Response) {
const did = await DidIonMethod.create({});

const resp: paths["/did-ion/create"]["post"]["responses"]["200"]["content"]["application/json"] =
{
did: did.did,
};

res.json(resp);
}
40 changes: 40 additions & 0 deletions .web5-spec/encoders.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { paths } from "./openapi.js";
import { Request, Response } from "express";
import { Convert } from "@web5/common";
import { sha256 } from "@noble/hashes/sha256";

export function encoderBase64Encode(req: Request, res: Response) {
const requestBody: paths["/encoders/base64/encode"]["post"]["requestBody"]["content"]["application/json"] =
req.body;

const resp: paths["/encoders/base64/encode"]["post"]["responses"]["200"]["content"]["application/json"] =
{
data: Convert.string(requestBody.data).toBase64Url(),
};

res.json(resp);
}

export function encoderBase64Decode(req: Request, res: Response) {
const requestBody: paths["/encoders/base64/encode"]["post"]["requestBody"]["content"]["application/json"] =
req.body;

const resp: paths["/encoders/base64/encode"]["post"]["responses"]["200"]["content"]["application/json"] =
{
data: Convert.base64Url(requestBody.data).toString(),
};

res.json(resp);
}

export function encoderSha256Encode(req: Request, res: Response) {
const requestBody: paths["/encoders/sha256/encode"]["post"]["requestBody"]["content"]["application/json"] =
req.body;

const resp: paths["/encoders/sha256/encode"]["post"]["responses"]["200"]["content"]["application/json"] =
{
data: Convert.arrayBuffer(sha256(requestBody.data)).toHex(),
};

res.json(resp);
}
53 changes: 53 additions & 0 deletions .web5-spec/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import express from "express";
import { credentialIssue } from "./credentials.js";
import { didIonCreate } from "./did-ion.js";
import {
encoderBase64Decode,
encoderBase64Encode,
encoderSha256Encode,
} from "./encoders.js";
import type * as http from "http";
import type { Request, Response } from "express";
import { paths } from "./openapi.js"; // generated with npx openapi-typescript .web5-component/openapi.yaml -o .web5-component/openapi.d.ts
import bodyparser from "body-parser";

const app: express.Application = express();
app.use(express.json());
app.use(bodyparser.json());

app.post("/did-ion/create", didIonCreate);

app.post("/credentials/issue", credentialIssue);

app.post("/encoders/base64/encode", encoderBase64Encode);
app.post("/encoders/base64/decode", encoderBase64Decode);
app.post("/encoders/sha256/encode", encoderSha256Encode);

const serverID: paths["/"]["get"]["responses"]["200"]["content"]["application/json"] =
{
name: "web5-js",
language: "JavaScript",
url: "https://github.com/TBD54566975/web5-js",
};
app.get("/", (req, res) => {
res.json(serverID);
});

let server: http.Server;
app.get("/shutdown", (req: Request, res: Response) => {
res.send("ok");
console.log("shutting down server");
server.close((e) => {
if (e) {
console.error("error shutting down server:", e.stack || e);
}
});
});

server = app.listen(8080, () => console.log("test server started"));
process.on("SIGTERM", () => {
console.log("SIGTERM signal received: closing HTTP server");
server.close(() => {
console.log("HTTP server closed");
});
});
Loading

0 comments on commit f92b90c

Please sign in to comment.