Skip to content

Commit

Permalink
Revert "chore: move issuance librarary to branch (#87)"
Browse files Browse the repository at this point in the history
This reverts commit 795bd78.
  • Loading branch information
maratsh authored May 22, 2024
1 parent 795bd78 commit 6d7e4a0
Show file tree
Hide file tree
Showing 13 changed files with 3,465 additions and 6 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ The Affinidi Trust Development Kit (Affinidi TDK) is a modern interface that all
The Affinidi TDK provides three type of modules:

- [Clients](clients), which offer methods to access Affinidi services like IAM, Verifier, Wallets, and Login configuation, among others.

- [Libraries](libs), which provide high-level abstractions that combine logic and data to perform necessary business logic functionalities.

- [Packages](packages), which are commonly used utilities/helpers that are self-contained and composable.

Each module has its own README that you can check to better understand how to integrate it into your application.
Expand All @@ -17,6 +20,8 @@ The Affinidi TDK offers the following modules and programming languages:

| | Typescript | Python | Dart |
| ------------------------------------------------- | :------------------------------------------------: | :--------------------------------------------: | :------------------------------------------: |
| **Libraries** |
| [issuance](libs/issuance/README.md) | 🟢 | 🟢 | 🔴 |
| **Packages** |
| [auth-provider](packages/auth-provider/README.md) | 🟢 | 🟢 | 🔴 |
| **Clients** |
Expand Down
Empty file removed libs/.gitkeep
Empty file.
24 changes: 24 additions & 0 deletions libs/issuance/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"root": true,
"ignorePatterns": [
"*.js",
"*.d.ts",
"node_modules/"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2021,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended" // Enables eslint-plugin-prettier and eslint-config-prettier
],
"rules": {
"@typescript-eslint/no-explicit-any": "off"
}
}
34 changes: 34 additions & 0 deletions libs/issuance/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
tsconfig.json
.jsii

*.js
*.d.ts

### Node ###
# Logs
logs
*.log
npm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Dependency directories
node_modules/

# TypeScript cache
*.tsbuildinfo

# Optional eslint cache
.eslintcache

# default build output
dist/

# Temporary folders
tmp/
temp/

# Custom
.idea/
.vscode/
18 changes: 18 additions & 0 deletions libs/issuance/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# empty npmignore to ensure all required files (e.g., in the dist folder) are published by npm

node_modules
coverage
.vscode
.DS_Store
.nyc_output
.history
.idea
Thumbs.db


# Exclude jsii outdir
dist

# Include .jsii and .jsii.gz
!.jsii
!.jsii.gz
81 changes: 81 additions & 0 deletions libs/issuance/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
## @affinidi/issuance

### Build JSII

```
npm i --prefix .
npm run build
npm run package
```

The code will be generated under /dist for each language.

### Usage

### JS

```bash
npm install <path_to_issuance.jsii.tgz>
```

```ts
import { Issuance } from '@affinidi/issuance'

const config = { authProvider, apiGatewayUrl }

const issuance = new Issuance(config)

const unsignedVC = await issuance.buildUnsignedVC({
credentialSubject: {
value1: '<value-1>',
value2: '<value-2>', // these will be based on the schema
},
holderDid: '<holder-did>',
expiresAt: 'XXXX-XX-XX',
typeName: '<schema-type>',
jsonLdContextUrl: '<schema-jsonLdContextUrl>',
jsonSchemaUrl: '<schema-jsonSchemaUrl>',
})
const issuedVc = await issuance.issueVC(unsignedVC, walletId)
```

You can refer [here](../../docs/examples/typescript/auth_provider.ts) to see how to generate authProvider

You can refer [here](../../docs/examples/typescript/client-cwe.ts) to see how to get walletId

### Python

```bash
pip install <path_to_affinidi-tdk-issuance.whl>
```

```python
import affinidi_tdk.issuance

config = {
'apiGatewayUrl': '<api_gateway_url>',
'authProvider' : '<auth_provider_package>'
}

issuance = affinidi_tdk.issuance.Issuance(config)

unsigned_vc_config = {
'credentialSubject': {
'value1': '<value-1>',
'value2': '<value-2>', # these will be based on the schema
},
'holderDid': '<holder-did>',
'expiresAt': 'XXXX-XX-XX',
'typeName': '<schema-type>',
'jsonLdContextUrl': '<schema-jsonLdContextUrl>',
'jsonSchemaUrl': '<schema-jsonSchemaUrl>',
}

unsigned_vc = issuance.build_unsigned_vc(unsigned_vc_config)

signed_vc = issuance.issue_vc(unsigned_vc, walletId)
```

You can refer [here](../../docs/examples/python/auth_provider.py) to see how to generate authProvider

You can refer [here](../../docs/examples/python/client-cwe.py) to see how to get walletId
35 changes: 35 additions & 0 deletions libs/issuance/helpers/cwe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
WalletApi,
Configuration,
SignCredentialResultDto,
} from '@affinidi-tdk/wallets-client'

export interface SignCredential extends SignCredentialResultDto {}

export interface ICWEParams {
authProvider: any
apiGatewayUrl: string
}

export class Cwe {
private readonly walletApi: WalletApi
constructor({ authProvider, apiGatewayUrl }: ICWEParams) {
this.walletApi = new WalletApi(
new Configuration({
apiKey: authProvider.fetchProjectScopedToken.bind(authProvider),
basePath: `${apiGatewayUrl}/cwe`,
})
)
}

public async signCredential(
walletId: string,
signCredentialInput: any
): Promise<{ [key: string]: any }> {
const signedCredential = (
await this.walletApi.signCredential(walletId, signCredentialInput)
).data

return signedCredential
}
}
1 change: 1 addition & 0 deletions libs/issuance/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ICWEParams, Cwe } from './cwe'
2 changes: 2 additions & 0 deletions libs/issuance/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './helpers'
export * from './issuance'
154 changes: 154 additions & 0 deletions libs/issuance/issuance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { Cwe } from './helpers/cwe'
import { parse } from 'did-resolver'
import { randomBytes } from 'crypto'

export interface IIssuanceParams {
projectScopedToken: string
apiGatewayUrl: string
}

export interface IBuildUnsignedCredentialInput {
jsonLdContextUrl?: string
jsonSchemaUrl?: string
id: string
credentialType: string
holderId: string
credentialSubject: Record<string, any>
issuanceDate: string
expirationDate?: string
}

export interface IUnsignedW3cCredential {
context: { [key: string]: any }
id: string
credentialType: string[]
holder: { [key: string]: any }
credentialSubject: { [key: string]: any }
issuanceDate: string
expirationDate?: string | undefined
credentialSchema?: { [key: string]: any }
}

export interface IBuildUnsignedVCInput {
/**
* @deprecated credentialType is deprecated.
Use "typeName", "jsonLdContextUrl" and "jsonSchemaUrl" instead.
*/
credentialType?: string
/** Optional only if type defined */
jsonLdContextUrl?: string
/** Optional only if type defined */
jsonSchemaUrl?: string
/** Required when type field is not given, will be used as a type of cred when passed */
typeName?: string

credentialSubject?: { [key: string]: any }

/**
* @deprecated data is deprecated.
* Use "credentialSubject" instead.
*/
data?: { [key: string]: any }

/**
* @pattern ^did:.*$
*/
holderDid: string

expiresAt?: string | undefined
}

export class Issuance {
private readonly authProvider
private readonly apiGatewayUrl: string = ''
private readonly cwe: Cwe

constructor({ authProvider, apiGatewayUrl }: { [key: string]: any }) {
this.authProvider = authProvider
this.apiGatewayUrl = apiGatewayUrl
this.cwe = new Cwe({
authProvider: this.authProvider,
apiGatewayUrl: this.apiGatewayUrl,
})
}

private buildUnsignedCredential = ({
credentialSubject,
jsonLdContextUrl,
jsonSchemaUrl,
expirationDate,
issuanceDate,
holderId,
credentialType: credType,
id,
}: IBuildUnsignedCredentialInput): IUnsignedW3cCredential => ({
context: ['https://www.w3.org/2018/credentials/v1', jsonLdContextUrl],
id,
credentialType: ['VerifiableCredential', credType],
holder: {
id: holderId,
},
credentialSubject,
...(jsonSchemaUrl && {
credentialSchema: {
id: jsonSchemaUrl,
type: 'JsonSchemaValidator2018',
},
}),
issuanceDate,
expirationDate,
})

public async buildUnsignedVC(input: any): Promise<{ [key: string]: any }> {
const {
credentialSubject,
holderDid,
expiresAt,
typeName,
credentialType,
data,
jsonLdContextUrl,
jsonSchemaUrl,
}: IBuildUnsignedVCInput = input

if ((data && credentialSubject) || (!data && !credentialSubject)) {
throw new Error('"data" or "credentialSubject" must be provided')
}

if (!holderDid) {
throw new Error('"holderDid" must be provided')
}

const {
context,
credentialType: credType,
...unsignedCredentialRaw
} = this.buildUnsignedCredential({
credentialSubject: credentialSubject ?? { data },
jsonLdContextUrl,
jsonSchemaUrl,
expirationDate: expiresAt ? new Date(expiresAt).toISOString() : undefined,
issuanceDate: new Date().toISOString(),
holderId: parse(holderDid)!.did,
credentialType: typeName || (credentialType as string),
id: `claimId:${randomBytes(8).toString('hex')}`, // This import was originally from @affinidi/common
})

const unsignedCredential = {
...unsignedCredentialRaw,
type: credType,
'@context': context,
}

return { unsignedCredential }
}
// use buildUnsignedVC before issuing a vc
public async issueVC(
vc: any,
walletId: string,
): Promise<{ [key: string]: any }> {
const signedCredential = await this.cwe.signCredential(walletId, vc)

return signedCredential
}
}
Loading

0 comments on commit 6d7e4a0

Please sign in to comment.