@docknetwork/wallet-sdk-core 0.4.19 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/account-provider.d.ts +1 -1
- package/lib/account-provider.js +1 -1
- package/lib/biometric-provider.d.ts +1 -1
- package/lib/biometric-provider.d.ts.map +1 -1
- package/lib/biometric-provider.js +1 -0
- package/lib/biometric-provider.js.map +1 -1
- package/lib/cloud-wallet.d.ts +20 -0
- package/lib/cloud-wallet.d.ts.map +1 -0
- package/lib/cloud-wallet.js +154 -0
- package/lib/cloud-wallet.js.map +1 -0
- package/lib/credential-provider.d.ts +10 -0
- package/lib/credential-provider.d.ts.map +1 -1
- package/lib/credential-provider.js +31 -10
- package/lib/credential-provider.js.map +1 -1
- package/lib/credentials/oidvc.d.ts +14 -0
- package/lib/credentials/oidvc.d.ts.map +1 -0
- package/lib/credentials/oidvc.js +84 -0
- package/lib/credentials/oidvc.js.map +1 -0
- package/lib/did-provider.js +1 -1
- package/lib/ecosystem-tools.d.ts +8 -6
- package/lib/ecosystem-tools.d.ts.map +1 -1
- package/lib/ecosystem-tools.js +27 -13
- package/lib/ecosystem-tools.js.map +1 -1
- package/lib/helpers.d.ts +1 -0
- package/lib/helpers.d.ts.map +1 -1
- package/lib/helpers.js +9 -1
- package/lib/helpers.js.map +1 -1
- package/lib/message-provider.d.ts +2 -19
- package/lib/message-provider.d.ts.map +1 -1
- package/lib/message-provider.js +69 -13
- package/lib/message-provider.js.map +1 -1
- package/lib/messages/message-helpers.js +2 -2
- package/lib/messages/message-helpers.js.map +1 -1
- package/lib/network-resolver.d.ts +2 -1
- package/lib/network-resolver.d.ts.map +1 -1
- package/lib/network-resolver.js +37 -6
- package/lib/network-resolver.js.map +1 -1
- package/lib/types.d.ts +10 -7
- package/lib/types.d.ts.map +1 -1
- package/lib/v1-helpers.js +9 -9
- package/lib/v1-helpers.js.map +1 -1
- package/lib/verification-controller.d.ts.map +1 -1
- package/lib/verification-controller.js +12 -8
- package/lib/verification-controller.js.map +1 -1
- package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.d.ts +7 -0
- package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.d.ts.map +1 -1
- package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.js +11 -2
- package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.js.map +1 -1
- package/lib/wallet-wasm.js +5 -5
- package/lib/wallet-wasm.js.map +1 -1
- package/lib/wallet.d.ts +1 -1
- package/lib/wallet.d.ts.map +1 -1
- package/lib/wallet.js +17 -53
- package/lib/wallet.js.map +1 -1
- package/package.json +6 -6
- package/src/biometric-provider.ts +1 -0
- package/src/cloud-wallet.ts +189 -0
- package/src/credential-provider.test.ts +11 -5
- package/src/credential-provider.ts +78 -25
- package/src/credentials/oidvc.test.ts +124 -0
- package/src/credentials/oidvc.ts +115 -0
- package/src/did-provider.test.ts +19 -11
- package/src/ecosystem-tools.ts +36 -11
- package/src/fixtures/biometrics-credential-bbs-revocation.json +2 -2
- package/src/fixtures/iiw-credential.json +1 -1
- package/src/fixtures/iiw-template.json +2 -2
- package/src/helpers.ts +10 -0
- package/src/message-provider.test.ts +9 -3
- package/src/message-provider.ts +97 -25
- package/src/messages/message-helpers.test.ts +15 -0
- package/src/messages/message-helpers.ts +2 -2
- package/src/network-resolver.test.ts +73 -4
- package/src/network-resolver.ts +41 -6
- package/src/types.ts +11 -5
- package/src/v1-helpers.ts +6 -6
- package/src/verification-controller.test.ts +8 -3
- package/src/verification-controller.ts +10 -6
- package/src/wallet-to-wallet-verification/walletToWalletVerificationProvider.ts +15 -0
- package/src/wallet-wasm.ts +1 -1
- package/src/wallet.test.ts +4 -1
- package/src/wallet.ts +22 -75
- package/tsconfig.build.tsbuildinfo +1 -1
- package/LICENSE +0 -39
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import {credentialServiceRPC} from '@docknetwork/wallet-sdk-wasm/src/services/credential';
|
|
2
2
|
import {IWallet} from './types';
|
|
3
3
|
import assert from 'assert';
|
|
4
|
-
import {
|
|
4
|
+
import {dockService} from '@docknetwork/wallet-sdk-wasm/src/services/dock';
|
|
5
|
+
import {acquireOpenIDCredentialFromURI} from './credentials/oidvc';
|
|
6
|
+
import {IDIDProvider} from './did-provider';
|
|
5
7
|
|
|
6
8
|
export type Credential = any;
|
|
7
9
|
|
|
10
|
+
|
|
8
11
|
export interface ICredentialProvider {
|
|
9
12
|
getCredentials(type?: string): Credential[];
|
|
10
13
|
getById(id: string): Credential;
|
|
@@ -12,8 +15,15 @@ export interface ICredentialProvider {
|
|
|
12
15
|
isBBSPlusCredential(credential: any): boolean;
|
|
13
16
|
isValid(credential: any, forceFetch?: boolean): Promise<boolean>;
|
|
14
17
|
addCredential(credential: any): Promise<Credential>;
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
importCredentialFromURI(
|
|
19
|
+
params: importCredentialFromUriParams,
|
|
20
|
+
): Promise<Credential>;
|
|
21
|
+
syncCredentialStatus(
|
|
22
|
+
params: SyncCredentialStatusParams,
|
|
23
|
+
): Promise<CredentialStatusDocument[]>;
|
|
24
|
+
getCredentialStatus(
|
|
25
|
+
credential: Credential,
|
|
26
|
+
): Promise<{status: string; error?: string}>;
|
|
17
27
|
}
|
|
18
28
|
|
|
19
29
|
export function isBBSPlusCredential(credential) {
|
|
@@ -27,8 +37,38 @@ export function isBBSPlusCredential(credential) {
|
|
|
27
37
|
);
|
|
28
38
|
}
|
|
29
39
|
|
|
40
|
+
type importCredentialFromUriParams = {
|
|
41
|
+
uri: string;
|
|
42
|
+
didProvider: IDIDProvider;
|
|
43
|
+
getAuthCode?: (authorizationURL: string) => Promise<string>;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export async function importCredentialFromURI({
|
|
47
|
+
uri,
|
|
48
|
+
wallet,
|
|
49
|
+
didProvider,
|
|
50
|
+
getAuthCode,
|
|
51
|
+
}: importCredentialFromUriParams & {
|
|
52
|
+
wallet: IWallet;
|
|
53
|
+
}) {
|
|
54
|
+
// TODO: unify the impl with the existing import credential flow
|
|
55
|
+
// if the URI is an OpenID credential offer, use the OpenID flow
|
|
56
|
+
// if the URI is a dock credential, then get user password and import that
|
|
57
|
+
// we can add support for other types of credentials later
|
|
58
|
+
const credential = await acquireOpenIDCredentialFromURI({
|
|
59
|
+
didProvider,
|
|
60
|
+
uri,
|
|
61
|
+
getAuthCode,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
await addCredential({wallet, credential});
|
|
65
|
+
}
|
|
66
|
+
|
|
30
67
|
export function isCredentialExpired(credential) {
|
|
31
|
-
return
|
|
68
|
+
return (
|
|
69
|
+
!!credential.expirationDate &&
|
|
70
|
+
new Date(credential.expirationDate) < new Date()
|
|
71
|
+
);
|
|
32
72
|
}
|
|
33
73
|
|
|
34
74
|
/**
|
|
@@ -52,10 +92,12 @@ export async function isValid({
|
|
|
52
92
|
};
|
|
53
93
|
}
|
|
54
94
|
|
|
55
|
-
const membershipWitness =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
95
|
+
const membershipWitness =
|
|
96
|
+
credential[ACUMM_WITNESS_PROP_KEY] ||
|
|
97
|
+
(await getMembershipWitness({
|
|
98
|
+
credentialId: credential.id,
|
|
99
|
+
wallet,
|
|
100
|
+
}));
|
|
59
101
|
|
|
60
102
|
delete credential[ACUMM_WITNESS_PROP_KEY];
|
|
61
103
|
|
|
@@ -64,10 +106,13 @@ export async function isValid({
|
|
|
64
106
|
membershipWitness,
|
|
65
107
|
});
|
|
66
108
|
|
|
67
|
-
const {
|
|
68
|
-
|
|
109
|
+
const {verified, error} = verificationResult;
|
|
110
|
+
|
|
69
111
|
if (!verified) {
|
|
70
|
-
if (
|
|
112
|
+
if (
|
|
113
|
+
typeof error === 'string' &&
|
|
114
|
+
error.toLowerCase().includes('revocation')
|
|
115
|
+
) {
|
|
71
116
|
return {
|
|
72
117
|
status: CredentialStatus.Revoked,
|
|
73
118
|
error,
|
|
@@ -113,7 +158,7 @@ export async function addCredential({wallet, credential}) {
|
|
|
113
158
|
});
|
|
114
159
|
}
|
|
115
160
|
|
|
116
|
-
syncCredentialStatus({
|
|
161
|
+
syncCredentialStatus({wallet, credentialIds: [credential.id]});
|
|
117
162
|
|
|
118
163
|
return response;
|
|
119
164
|
}
|
|
@@ -123,7 +168,6 @@ async function getMembershipWitness({credentialId, wallet}) {
|
|
|
123
168
|
return document?.value;
|
|
124
169
|
}
|
|
125
170
|
|
|
126
|
-
|
|
127
171
|
export const CredentialStatus = {
|
|
128
172
|
Invalid: 'invalid',
|
|
129
173
|
Expired: 'expired',
|
|
@@ -134,28 +178,32 @@ export const CredentialStatus = {
|
|
|
134
178
|
|
|
135
179
|
type SyncCredentialStatusParams = {
|
|
136
180
|
// Optional credential IDs to sync
|
|
137
|
-
credentialIds?: string[]
|
|
181
|
+
credentialIds?: string[];
|
|
138
182
|
// Skip the cache and re-fetch from the chain
|
|
139
|
-
forceFetch?: boolean
|
|
183
|
+
forceFetch?: boolean;
|
|
140
184
|
};
|
|
141
185
|
|
|
142
186
|
type CredentialStatusDocument = {
|
|
143
187
|
id: string;
|
|
144
188
|
status: string;
|
|
145
189
|
error: string;
|
|
146
|
-
}
|
|
190
|
+
};
|
|
147
191
|
|
|
148
192
|
/**
|
|
149
193
|
* Fetch credential status from the chain and update the wallet
|
|
150
194
|
* Store a new document <credentialId>#status in the wallet
|
|
151
195
|
* Returns a list of CredentialStatusDocument
|
|
152
|
-
*
|
|
196
|
+
*
|
|
153
197
|
* @param param0
|
|
154
198
|
* @returns CredentialStatusDocument[]
|
|
155
199
|
*/
|
|
156
|
-
async function syncCredentialStatus({
|
|
200
|
+
async function syncCredentialStatus({
|
|
201
|
+
wallet,
|
|
202
|
+
credentialIds,
|
|
203
|
+
forceFetch,
|
|
204
|
+
}: SyncCredentialStatusParams & {
|
|
157
205
|
wallet: IWallet;
|
|
158
|
-
}
|
|
206
|
+
}): Promise<CredentialStatusDocument[]> {
|
|
159
207
|
let credentials;
|
|
160
208
|
|
|
161
209
|
if (credentialIds && credentialIds.length) {
|
|
@@ -167,7 +215,7 @@ async function syncCredentialStatus({ wallet, credentialIds, forceFetch }: SyncC
|
|
|
167
215
|
let statusDocs = [];
|
|
168
216
|
|
|
169
217
|
let isApiConnected;
|
|
170
|
-
|
|
218
|
+
|
|
171
219
|
for (const credential of credentials) {
|
|
172
220
|
let shouldFetch = !!forceFetch;
|
|
173
221
|
let statusDoc = await wallet.getDocumentById(`${credential.id}#status`);
|
|
@@ -214,10 +262,10 @@ async function syncCredentialStatus({ wallet, credentialIds, forceFetch }: SyncC
|
|
|
214
262
|
if (!isApiConnected) {
|
|
215
263
|
await dockService.ensureDockReady();
|
|
216
264
|
isApiConnected = true;
|
|
217
|
-
}
|
|
265
|
+
}
|
|
218
266
|
|
|
219
|
-
const result = await isValid({
|
|
220
|
-
statusDoc.status = result?.status
|
|
267
|
+
const result = await isValid({credential, wallet});
|
|
268
|
+
statusDoc.status = result?.status;
|
|
221
269
|
statusDoc.error = result?.error;
|
|
222
270
|
statusDoc.updatedAt = new Date().toISOString();
|
|
223
271
|
|
|
@@ -237,6 +285,11 @@ export function createCredentialProvider({
|
|
|
237
285
|
}
|
|
238
286
|
|
|
239
287
|
return {
|
|
288
|
+
importCredentialFromURI: async (params: importCredentialFromUriParams) =>
|
|
289
|
+
importCredentialFromURI({
|
|
290
|
+
...params,
|
|
291
|
+
wallet,
|
|
292
|
+
}),
|
|
240
293
|
getCredentials,
|
|
241
294
|
getMembershipWitness: async (credentialId: string) =>
|
|
242
295
|
getMembershipWitness({credentialId, wallet}),
|
|
@@ -261,10 +314,10 @@ export function createCredentialProvider({
|
|
|
261
314
|
return {
|
|
262
315
|
status: statusDoc?.status || CredentialStatus.Pending,
|
|
263
316
|
error: statusDoc?.error,
|
|
264
|
-
}
|
|
317
|
+
};
|
|
265
318
|
},
|
|
266
319
|
syncCredentialStatus: async (props: SyncCredentialStatusParams) => {
|
|
267
|
-
return syncCredentialStatus({
|
|
320
|
+
return syncCredentialStatus({wallet, ...props});
|
|
268
321
|
},
|
|
269
322
|
addCredential: credential => addCredential({wallet, credential}),
|
|
270
323
|
// TODO: move import credential from json or URL to this provider
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import {
|
|
2
|
+
acquireOpenIDCredentialFromURI,
|
|
3
|
+
getAuthURL,
|
|
4
|
+
decodeRequestJWT,
|
|
5
|
+
getPresentationSubmision,
|
|
6
|
+
} from './oidvc'; // replace with your actual file path
|
|
7
|
+
import {credentialServiceRPC} from '@docknetwork/wallet-sdk-wasm/src/services/credential';
|
|
8
|
+
import {MetadataClient} from '@sphereon/oid4vci-client';
|
|
9
|
+
import jwtDecode from 'jwt-decode';
|
|
10
|
+
import axios from 'axios';
|
|
11
|
+
import {pexService} from '@docknetwork/wallet-sdk-wasm/src/services/pex';
|
|
12
|
+
|
|
13
|
+
jest.mock('@docknetwork/wallet-sdk-wasm/src/services/credential');
|
|
14
|
+
jest.mock('@sphereon/oid4vci-client');
|
|
15
|
+
jest.mock('jwt-decode');
|
|
16
|
+
jest.mock('axios');
|
|
17
|
+
jest.mock('@docknetwork/wallet-sdk-wasm/src/services/pex');
|
|
18
|
+
|
|
19
|
+
describe('acquireOpenIDCredentialFromURI', () => {
|
|
20
|
+
const didProvider: any = {
|
|
21
|
+
getDIDKeyPairs: jest.fn(),
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const uri = 'https://example.com/credential';
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
didProvider.getDIDKeyPairs.mockResolvedValue([{id: 'did:example:123'}]);
|
|
28
|
+
(credentialServiceRPC.acquireOIDCredential as jest.Mock).mockResolvedValue({
|
|
29
|
+
credential: 'fake-credential',
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should acquire OID credential without authorization URL', async () => {
|
|
34
|
+
const response = await acquireOpenIDCredentialFromURI({didProvider, uri});
|
|
35
|
+
expect(didProvider.getDIDKeyPairs).toHaveBeenCalled();
|
|
36
|
+
expect(credentialServiceRPC.acquireOIDCredential).toHaveBeenCalledWith({
|
|
37
|
+
uri,
|
|
38
|
+
holderKeyDocument: {id: 'did:example:123'},
|
|
39
|
+
});
|
|
40
|
+
expect(response).toBe('credential');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should acquire OID credential with authorization URL', async () => {
|
|
44
|
+
const getAuthCode = jest.fn().mockResolvedValue('auth-code');
|
|
45
|
+
(credentialServiceRPC.acquireOIDCredential as jest.Mock).mockResolvedValueOnce({
|
|
46
|
+
authorizationURL: 'https://example.com/auth',
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const response = await acquireOpenIDCredentialFromURI({
|
|
50
|
+
didProvider,
|
|
51
|
+
uri,
|
|
52
|
+
getAuthCode,
|
|
53
|
+
});
|
|
54
|
+
expect(getAuthCode).toHaveBeenCalledWith('https://example.com/auth');
|
|
55
|
+
expect(credentialServiceRPC.acquireOIDCredential).toHaveBeenCalledWith({
|
|
56
|
+
uri,
|
|
57
|
+
holderKeyDocument: {id: 'did:example:123'},
|
|
58
|
+
authorizationCode: 'auth-code',
|
|
59
|
+
});
|
|
60
|
+
expect(response).toBe('credential');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('getAuthURL', () => {
|
|
65
|
+
it('should generate an auth URL', async () => {
|
|
66
|
+
const uri = 'https://example.com?client_id=fake-client';
|
|
67
|
+
const metadata = {
|
|
68
|
+
authorizationServerMetadata: {
|
|
69
|
+
request_object_signing_alg_values_supported: ['RS256'],
|
|
70
|
+
},
|
|
71
|
+
authorization_endpoint: 'https://auth.example.com/authorize',
|
|
72
|
+
};
|
|
73
|
+
(MetadataClient.retrieveAllMetadata as jest.Mock).mockResolvedValue(metadata);
|
|
74
|
+
|
|
75
|
+
const result = await getAuthURL(uri);
|
|
76
|
+
expect(MetadataClient.retrieveAllMetadata).toHaveBeenCalledWith(
|
|
77
|
+
'fake-client',
|
|
78
|
+
);
|
|
79
|
+
expect(result).toContain('https://auth.example.com/authorize?');
|
|
80
|
+
expect(result).toContain('client_id=dock-wallet');
|
|
81
|
+
expect(result).toContain('redirect_uri=dockwallet://vp');
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('decodeRequestJWT', () => {
|
|
86
|
+
it('should decode JWT from the request URI', async () => {
|
|
87
|
+
const uri = 'https://example.com?request_uri=https://example.com/jwt';
|
|
88
|
+
const jwt = 'some-jwt';
|
|
89
|
+
const decodedJWT = {sub: '1234567890', name: 'Testing', admin: true};
|
|
90
|
+
(axios.get as jest.Mock).mockResolvedValue({data: jwt});
|
|
91
|
+
(jwtDecode as jest.Mock).mockReturnValue(decodedJWT);
|
|
92
|
+
|
|
93
|
+
const result = await decodeRequestJWT(uri);
|
|
94
|
+
expect(axios.get).toHaveBeenCalledWith('https://example.com/jwt');
|
|
95
|
+
expect(jwtDecode).toHaveBeenCalledWith(jwt);
|
|
96
|
+
expect(result).toEqual(decodedJWT);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe('getPresentationSubmision', () => {
|
|
101
|
+
it('should get presentation submission', async () => {
|
|
102
|
+
const credentials = [{id: 'credential-1'}];
|
|
103
|
+
const presentationDefinition = {id: 'presentation-definition-1'};
|
|
104
|
+
const holderDID = 'did:example:123';
|
|
105
|
+
const presentationSubmission = {definition_id: 'presentation-submission-1'};
|
|
106
|
+
|
|
107
|
+
(pexService.presentationFrom as jest.Mock).mockResolvedValue({
|
|
108
|
+
presentation_submission: presentationSubmission,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const result = await getPresentationSubmision({
|
|
112
|
+
credentials,
|
|
113
|
+
presentationDefinition,
|
|
114
|
+
holderDID,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
expect(pexService.presentationFrom).toHaveBeenCalledWith({
|
|
118
|
+
presentationDefinition,
|
|
119
|
+
credentials,
|
|
120
|
+
holderDID,
|
|
121
|
+
});
|
|
122
|
+
expect(result).toEqual(presentationSubmission);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import {IWallet} from '../types';
|
|
2
|
+
import {IDIDProvider} from '../did-provider';
|
|
3
|
+
import {credentialServiceRPC} from '@docknetwork/wallet-sdk-wasm/src/services/credential';
|
|
4
|
+
import {MetadataClient} from '@sphereon/oid4vci-client';
|
|
5
|
+
import jwtDecode from 'jwt-decode';
|
|
6
|
+
import axios from 'axios';
|
|
7
|
+
import {pexService} from '@docknetwork/wallet-sdk-wasm/src/services/pex';
|
|
8
|
+
import {WellKnownEndpoints} from '@sphereon/oid4vci-common';
|
|
9
|
+
|
|
10
|
+
export async function acquireOpenIDCredentialFromURI({
|
|
11
|
+
didProvider,
|
|
12
|
+
uri,
|
|
13
|
+
getAuthCode,
|
|
14
|
+
}: {
|
|
15
|
+
didProvider: IDIDProvider;
|
|
16
|
+
uri: string;
|
|
17
|
+
getAuthCode?: (authorizationURL: string) => Promise<string>;
|
|
18
|
+
}) {
|
|
19
|
+
const [holderKeyDocument] = await didProvider.getDIDKeyPairs();
|
|
20
|
+
|
|
21
|
+
let response = await credentialServiceRPC.acquireOIDCredential({
|
|
22
|
+
uri,
|
|
23
|
+
holderKeyDocument,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (response.authorizationURL) {
|
|
27
|
+
const authorizationCode = await getAuthCode(response.authorizationURL);
|
|
28
|
+
response = await credentialServiceRPC.acquireOIDCredential({
|
|
29
|
+
uri,
|
|
30
|
+
holderKeyDocument,
|
|
31
|
+
authorizationCode,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return response.credential;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function getAuthURL(
|
|
39
|
+
uri: string,
|
|
40
|
+
walletClientId: string = 'dock-wallet',
|
|
41
|
+
requestedRedirectURI: string = 'dockwallet://vp',
|
|
42
|
+
) {
|
|
43
|
+
function buildOID4VPRequestURL(params, prefix = 'dockwallet://') {
|
|
44
|
+
return `${prefix}?${Object.keys(params)
|
|
45
|
+
.map(
|
|
46
|
+
key =>
|
|
47
|
+
`${encodeURIComponent(key)}=${encodeURIComponent(
|
|
48
|
+
typeof params[key] === 'object'
|
|
49
|
+
? JSON.stringify(params[key])
|
|
50
|
+
: params[key],
|
|
51
|
+
)}`,
|
|
52
|
+
)
|
|
53
|
+
.join('&')}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const searchParams = new URL(uri).searchParams;
|
|
57
|
+
const params = new URLSearchParams(searchParams);
|
|
58
|
+
const clientId = params.get('client_id');
|
|
59
|
+
// We need to investigate why MetadataClient.retrieveAllMetadata(clientId); is not working on android
|
|
60
|
+
// Follow up bug ticket: https://dock-team.atlassian.net/browse/DCKM-600
|
|
61
|
+
const metadataURI = `${clientId}${WellKnownEndpoints.OPENID_CONFIGURATION}`;
|
|
62
|
+
const {data: metadata} = await axios.get(metadataURI);
|
|
63
|
+
|
|
64
|
+
const requestedAlg =
|
|
65
|
+
metadata?.authorizationServerMetadata
|
|
66
|
+
?.request_object_signing_alg_values_supported[0];
|
|
67
|
+
const requestParams = {
|
|
68
|
+
scope: 'openid vp_token',
|
|
69
|
+
redirect_uri: requestedRedirectURI,
|
|
70
|
+
client_metadata:
|
|
71
|
+
requestedAlg && requestedAlg !== 'EdDSA'
|
|
72
|
+
? JSON.stringify({
|
|
73
|
+
vp_formats_supported: {
|
|
74
|
+
vc_json: {
|
|
75
|
+
alg_values_supported: [requestedAlg],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
: ['EdDSA'],
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
return buildOID4VPRequestURL(
|
|
83
|
+
{
|
|
84
|
+
...requestParams,
|
|
85
|
+
client_id: walletClientId,
|
|
86
|
+
},
|
|
87
|
+
metadata.authorization_endpoint,
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export async function decodeRequestJWT(uri: string) {
|
|
92
|
+
const searchParams = new URL(uri).searchParams;
|
|
93
|
+
const params = new URLSearchParams(searchParams);
|
|
94
|
+
const requestUri = params.get('request_uri');
|
|
95
|
+
const jwt = await axios.get(requestUri).then(res => res.data);
|
|
96
|
+
const decoded = jwtDecode(jwt);
|
|
97
|
+
|
|
98
|
+
return decoded;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export async function getPresentationSubmision({
|
|
102
|
+
credentials,
|
|
103
|
+
presentationDefinition,
|
|
104
|
+
holderDID,
|
|
105
|
+
}) {
|
|
106
|
+
const presentation = await pexService.presentationFrom({
|
|
107
|
+
presentationDefinition,
|
|
108
|
+
credentials,
|
|
109
|
+
holderDID,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return presentation.presentation_submission;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
pexService.evaluatePresentation;
|
package/src/did-provider.test.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import {IWallet} from './types';
|
|
2
2
|
import {createWallet} from './wallet';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createDIDock,
|
|
5
|
+
createDIDKey,
|
|
6
|
+
createDIDProvider,
|
|
7
|
+
IDIDProvider,
|
|
8
|
+
} from './did-provider';
|
|
4
9
|
import {createAccountProvider} from './account-provider';
|
|
5
10
|
import {didServiceRPC} from '@docknetwork/wallet-sdk-wasm/src/services/dids';
|
|
11
|
+
import {createDataStore} from '@docknetwork/wallet-sdk-data-store-typeorm/src';
|
|
6
12
|
|
|
7
13
|
describe('DID Provider', () => {
|
|
8
14
|
let wallet: IWallet;
|
|
@@ -49,7 +55,9 @@ describe('DID Provider', () => {
|
|
|
49
55
|
|
|
50
56
|
beforeEach(async () => {
|
|
51
57
|
wallet = await createWallet({
|
|
52
|
-
|
|
58
|
+
dataStore: await createDataStore({
|
|
59
|
+
databasePath: ':memory:',
|
|
60
|
+
}),
|
|
53
61
|
});
|
|
54
62
|
accountProvider = createAccountProvider({wallet});
|
|
55
63
|
didProvider = createDIDProvider({wallet});
|
|
@@ -149,18 +157,19 @@ describe('DID Provider', () => {
|
|
|
149
157
|
|
|
150
158
|
describe('create DID Key', () => {
|
|
151
159
|
it('expect to create a DID Key', async () => {
|
|
152
|
-
|
|
153
160
|
jest.spyOn(didServiceRPC, 'generateKeyDoc').mockResolvedValueOnce({
|
|
154
161
|
id: 'did:key:abcde#key-1',
|
|
155
162
|
type: 'KeyDocument',
|
|
156
163
|
});
|
|
157
164
|
|
|
158
|
-
jest
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
165
|
+
jest
|
|
166
|
+
.spyOn(didServiceRPC, 'keypairToDIDKeyDocument')
|
|
167
|
+
.mockResolvedValueOnce({
|
|
168
|
+
didDocument: {
|
|
169
|
+
id: 'did:key:abcde#key-2',
|
|
170
|
+
type: 'DidDocument',
|
|
171
|
+
},
|
|
172
|
+
});
|
|
164
173
|
|
|
165
174
|
jest.spyOn(didServiceRPC, 'getDIDResolution').mockResolvedValueOnce({
|
|
166
175
|
id: new Date().getTime().toString(),
|
|
@@ -185,10 +194,9 @@ describe('DID Provider', () => {
|
|
|
185
194
|
expect(didDocument.length).toBe(2);
|
|
186
195
|
});
|
|
187
196
|
it('expect to assert parameters', async () => {
|
|
188
|
-
|
|
189
197
|
await expect(
|
|
190
198
|
didProvider.createDIDKey({
|
|
191
|
-
name: ''
|
|
199
|
+
name: '',
|
|
192
200
|
}),
|
|
193
201
|
).rejects.toThrowError('name is required');
|
|
194
202
|
|
package/src/ecosystem-tools.ts
CHANGED
|
@@ -1,35 +1,60 @@
|
|
|
1
1
|
import {dockService} from '@docknetwork/wallet-sdk-wasm/src/services/dock';
|
|
2
2
|
import {trustRegistryService} from '@docknetwork/wallet-sdk-wasm/src/services/trust-registry';
|
|
3
|
+
import assert from 'assert';
|
|
4
|
+
import axios from 'axios';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
function getApiURL(networkId) {
|
|
8
|
+
return networkId === 'mainnet' ? 'https://api.dock.io' : 'https://api-testnet.dock.io';
|
|
9
|
+
}
|
|
3
10
|
|
|
4
11
|
export async function getEcosystems({
|
|
5
12
|
issuerDID,
|
|
6
13
|
verifierDID,
|
|
7
14
|
schemaId,
|
|
15
|
+
networkId,
|
|
8
16
|
}: {
|
|
17
|
+
networkId: string;
|
|
9
18
|
issuerDID?: string;
|
|
10
19
|
verifierDID?: string;
|
|
11
20
|
schemaId?: string;
|
|
12
21
|
}) {
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
assert(!!networkId, 'networkId is required');
|
|
23
|
+
|
|
15
24
|
try {
|
|
16
|
-
|
|
25
|
+
// TODO: Use the SDK to fetch ecosystems when it's available
|
|
26
|
+
const {data} = await axios.post(`${getApiURL(networkId)}/trust-registries/query`,{
|
|
27
|
+
issuerDID,
|
|
28
|
+
verifierDID,
|
|
29
|
+
schemaId,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const registries = {}
|
|
33
|
+
|
|
34
|
+
data.forEach((registry) => {
|
|
35
|
+
registries[registry.id] = registry;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return registries;
|
|
17
39
|
} catch (error) {
|
|
18
40
|
console.log('error', error);
|
|
19
41
|
return [];
|
|
20
42
|
}
|
|
21
43
|
}
|
|
22
44
|
|
|
23
|
-
export async function getVerifiers({trustRegistryId, issuerDID, schemaId}
|
|
24
|
-
|
|
45
|
+
export async function getVerifiers({trustRegistryId, issuerDID, schemaId, networkId}: {
|
|
46
|
+
trustRegistryId: string;
|
|
47
|
+
issuerDID?: string;
|
|
48
|
+
schemaId?: string;
|
|
49
|
+
networkId: string;
|
|
50
|
+
}) {
|
|
51
|
+
assert(!!networkId, 'networkId is required');
|
|
52
|
+
assert(!!trustRegistryId, 'trustRegistryId is required');
|
|
25
53
|
|
|
26
54
|
try {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
trustRegistryId,
|
|
31
|
-
});
|
|
32
|
-
return verifiers;
|
|
55
|
+
// TODO: Use the SDK to fetch verifiers when it's available
|
|
56
|
+
const { data } = await axios.get(`${getApiURL(networkId)}/trust-registries/${trustRegistryId}/verifiers?schemaId=${encodeURIComponent(schemaId)}&issuerDID=${issuerDID}`);
|
|
57
|
+
return data;
|
|
33
58
|
} catch (error) {
|
|
34
59
|
console.log('error', error);
|
|
35
60
|
return [];
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"revocationCheck": "membership",
|
|
14
14
|
"revocationId": "9"
|
|
15
15
|
},
|
|
16
|
-
"id": "https://creds-
|
|
16
|
+
"id": "https://creds-example.dock.io/83e0641f88e7ae5b18e8ae4a9ca616d23df8370501375269db9e21d857d6ce55",
|
|
17
17
|
"type": [
|
|
18
18
|
"VerifiableCredential",
|
|
19
19
|
"BiometricsCredential"
|
|
@@ -59,4 +59,4 @@
|
|
|
59
59
|
"proofValue": "zY4LVnbLxwjnk2En988EVHvqsysjELpAcD3A72832JUHS3DreVjv2P9fN6J4CyWo9qC1qiiqBWkNzKP73ZF6tdSzTLzYgByqsXKDxLoyW7LqU2byPjAhHx2GKXTkKVqB3P3WtwxMGCcXR1tQqNhz91do5h"
|
|
60
60
|
},
|
|
61
61
|
"$$accum__witness$$": "0xb2249e8faadb33015bfc2dbe74bbd916f5efacff92d0e1235827e4e1b23438d9c45e427376cbcc164ab41c3bd0ace3c8"
|
|
62
|
-
}
|
|
62
|
+
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"https://ld.dock.io/credentials/prettyvc"
|
|
14
14
|
],
|
|
15
|
-
"id": "https://creds-
|
|
15
|
+
"id": "https://creds-example.dock.io/d02cc3892ae688dae923dd470443b1ee41a046206a6ae1775e4dbff25abccc6f",
|
|
16
16
|
"type": [
|
|
17
17
|
"VerifiableCredential",
|
|
18
18
|
"IIW",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"qr": "https://creds-
|
|
2
|
+
"qr": "https://creds-example.dock.io/proof/f6b0c6a7-ae27-4044-80a3-07f5af6e61c8",
|
|
3
3
|
"id": "f6b0c6a7-ae27-4044-80a3-07f5af6e61c8",
|
|
4
4
|
"name": "boolean",
|
|
5
5
|
"nonce": "e2cb13292035d73e97543c8f463c3f06",
|
|
6
6
|
"created": "2023-08-17T17:38:38.276Z",
|
|
7
7
|
"updated": "2023-08-17T17:38:38.276Z",
|
|
8
8
|
"verified": false,
|
|
9
|
-
"response_url": "
|
|
9
|
+
"response_url": "${TESTING_API_URL}/proof-requests/f6b0c6a7-ae27-4044-80a3-07f5af6e61c8/send-presentation",
|
|
10
10
|
"request": {
|
|
11
11
|
"id": "f6b0c6a7-ae27-4044-80a3-07f5af6e61c8",
|
|
12
12
|
"input_descriptors": [
|
package/src/helpers.ts
CHANGED
|
@@ -59,3 +59,13 @@ export function getJSON(jsonOrURL: string | any) {
|
|
|
59
59
|
|
|
60
60
|
throw new Error(`Invalid data ${jsonOrURL}`);
|
|
61
61
|
}
|
|
62
|
+
|
|
63
|
+
export function replaceResponseURL(templateRequest){
|
|
64
|
+
assert(process.env.TESTING_API_URL, "Please configure the TESTING_API_URL env var.");
|
|
65
|
+
|
|
66
|
+
if (templateRequest?.response_url){
|
|
67
|
+
templateRequest.response_url = templateRequest.response_url.replace("${TESTING_API_URL}", process.env.TESTING_API_URL);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return templateRequest;
|
|
71
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createDataStore } from '@docknetwork/wallet-sdk-data-store-typeorm/src';
|
|
1
2
|
import {IDIDProvider, createDIDProvider} from './did-provider';
|
|
2
3
|
import {IMessageProvider, createMessageProvider} from './message-provider';
|
|
3
4
|
import {IWallet, createWallet} from './wallet';
|
|
@@ -25,17 +26,20 @@ describe('MessageProvider', () => {
|
|
|
25
26
|
beforeEach(async () => {
|
|
26
27
|
relayService = {
|
|
27
28
|
sendMessage: jest.fn(),
|
|
29
|
+
ackMessages: jest.fn(),
|
|
28
30
|
getMessages: jest.fn().mockResolvedValue(didCommMessages),
|
|
29
31
|
resolveDidcommMessage: jest.fn().mockImplementation(({ message }) => message),
|
|
30
32
|
};
|
|
31
33
|
|
|
32
34
|
wallet = await createWallet({
|
|
33
|
-
|
|
35
|
+
dataStore: await createDataStore({
|
|
36
|
+
databasePath: ':memory:',
|
|
37
|
+
})
|
|
34
38
|
});
|
|
35
39
|
didProvider = createDIDProvider({
|
|
36
40
|
wallet,
|
|
37
41
|
});
|
|
38
|
-
didProvider.getDIDKeyPairs = jest.fn().mockResolvedValue([{controller: "
|
|
42
|
+
didProvider.getDIDKeyPairs = jest.fn().mockResolvedValue([{controller: "did:key:z6MkoQzWru66w91EH7U9Xsv5eYXQabw9U3ZJd5GkatMWkmZT"}])
|
|
39
43
|
messageProvider = createMessageProvider({
|
|
40
44
|
wallet,
|
|
41
45
|
didProvider,
|
|
@@ -51,6 +55,8 @@ describe('MessageProvider', () => {
|
|
|
51
55
|
const walletMessage = await wallet.getDocumentById(message._id);
|
|
52
56
|
expect(walletMessage.encryptedMessage).toEqual(message);
|
|
53
57
|
}
|
|
58
|
+
|
|
59
|
+
expect(relayService.ackMessages).toBeCalledWith({did: 'did:key:z6MkoQzWru66w91EH7U9Xsv5eYXQabw9U3ZJd5GkatMWkmZT', messageIds: didCommMessages.map(m => m._id)});
|
|
54
60
|
});
|
|
55
61
|
|
|
56
62
|
it('should decrypt encrypted messages in the wallet', async () => {
|
|
@@ -75,7 +81,7 @@ describe('MessageProvider', () => {
|
|
|
75
81
|
|
|
76
82
|
await expect(
|
|
77
83
|
messageProvider.sendMessage({
|
|
78
|
-
did: '
|
|
84
|
+
did: 'did:key:z6MkoQzWru66w91EH7U9Xsv5eYXQabw9U3ZJd5GkatMWkmZT',
|
|
79
85
|
message: 'someMessage',
|
|
80
86
|
recipientDid: 'recipientDid',
|
|
81
87
|
})
|