@docknetwork/wallet-sdk-core 0.4.19
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/LICENSE +39 -0
- package/babel.config.js +16 -0
- package/jest.config.ts +39 -0
- package/lib/account-provider.d.ts +8 -0
- package/lib/account-provider.d.ts.map +1 -0
- package/lib/account-provider.js +15 -0
- package/lib/account-provider.js.map +1 -0
- package/lib/biometric-provider.d.ts +29 -0
- package/lib/biometric-provider.d.ts.map +1 -0
- package/lib/biometric-provider.js +54 -0
- package/lib/biometric-provider.js.map +1 -0
- package/lib/credential-provider.d.ts +58 -0
- package/lib/credential-provider.d.ts.map +1 -0
- package/lib/credential-provider.js +198 -0
- package/lib/credential-provider.js.map +1 -0
- package/lib/did-provider.d.ts +79 -0
- package/lib/did-provider.d.ts.map +1 -0
- package/lib/did-provider.js +215 -0
- package/lib/did-provider.js.map +1 -0
- package/lib/ecosystem-tools.d.ts +11 -0
- package/lib/ecosystem-tools.d.ts.map +1 -0
- package/lib/ecosystem-tools.js +33 -0
- package/lib/ecosystem-tools.js.map +1 -0
- package/lib/helpers.d.ts +8 -0
- package/lib/helpers.d.ts.map +1 -0
- package/lib/helpers.js +63 -0
- package/lib/helpers.js.map +1 -0
- package/lib/message-provider.d.ts +36 -0
- package/lib/message-provider.d.ts.map +1 -0
- package/lib/message-provider.js +172 -0
- package/lib/message-provider.js.map +1 -0
- package/lib/messages/message-helpers.d.ts +110 -0
- package/lib/messages/message-helpers.d.ts.map +1 -0
- package/lib/messages/message-helpers.js +106 -0
- package/lib/messages/message-helpers.js.map +1 -0
- package/lib/network-resolver.d.ts +19 -0
- package/lib/network-resolver.d.ts.map +1 -0
- package/lib/network-resolver.js +80 -0
- package/lib/network-resolver.js.map +1 -0
- package/lib/types.d.ts +63 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +3 -0
- package/lib/types.js.map +1 -0
- package/lib/v1-helpers.d.ts +20 -0
- package/lib/v1-helpers.d.ts.map +1 -0
- package/lib/v1-helpers.js +147 -0
- package/lib/v1-helpers.js.map +1 -0
- package/lib/verification-controller.d.ts +48 -0
- package/lib/verification-controller.d.ts.map +1 -0
- package/lib/verification-controller.js +219 -0
- package/lib/verification-controller.js.map +1 -0
- package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.d.ts +20 -0
- package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.d.ts.map +1 -0
- package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.js +140 -0
- package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.js.map +1 -0
- package/lib/wallet-wasm.d.ts +10 -0
- package/lib/wallet-wasm.d.ts.map +1 -0
- package/lib/wallet-wasm.js +62 -0
- package/lib/wallet-wasm.js.map +1 -0
- package/lib/wallet.d.ts +11 -0
- package/lib/wallet.d.ts.map +1 -0
- package/lib/wallet.js +173 -0
- package/lib/wallet.js.map +1 -0
- package/package.json +34 -0
- package/setup-tests.ts +1 -0
- package/src/account-provider.ts +18 -0
- package/src/biometric-provider.ts +82 -0
- package/src/credential-provider.test.ts +164 -0
- package/src/credential-provider.ts +272 -0
- package/src/did-provider.test.ts +203 -0
- package/src/did-provider.ts +263 -0
- package/src/ecosystem-tools.ts +37 -0
- package/src/fixtures/any-credential-proof-request.json +30 -0
- package/src/fixtures/biometrics-credential-bbs-revocation.json +62 -0
- package/src/fixtures/customer-credential.json +39 -0
- package/src/fixtures/iiw-credential.json +59 -0
- package/src/fixtures/iiw-template.json +33 -0
- package/src/fixtures/university-degree-bbs.json +57 -0
- package/src/fixtures/university-degree-proof-request.json +32 -0
- package/src/helpers.ts +61 -0
- package/src/message-provider.test.ts +115 -0
- package/src/message-provider.ts +221 -0
- package/src/messages/message-helpers.ts +125 -0
- package/src/messages/relay-service-mocks/demo-app-messages.json +450 -0
- package/src/network-resolver.test.ts +142 -0
- package/src/network-resolver.ts +122 -0
- package/src/types.ts +75 -0
- package/src/v1-helpers.ts +160 -0
- package/src/verification-controller.test.ts +149 -0
- package/src/verification-controller.ts +276 -0
- package/src/wallet-to-wallet-verification/walletToWalletVerificationProvider.ts +216 -0
- package/src/wallet-wasm.ts +74 -0
- package/src/wallet.test.ts +72 -0
- package/src/wallet.ts +211 -0
- package/tsconfig.build.json +26 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +30 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import {getJSON} from './helpers';
|
|
2
|
+
import {pexService} from '@docknetwork/wallet-sdk-wasm/src/services/pex';
|
|
3
|
+
import {credentialServiceRPC} from '@docknetwork/wallet-sdk-wasm/src/services/credential';
|
|
4
|
+
import {
|
|
5
|
+
createCredentialProvider,
|
|
6
|
+
ICredentialProvider,
|
|
7
|
+
} from './credential-provider';
|
|
8
|
+
import {IWallet} from './types';
|
|
9
|
+
import {EventEmitter} from 'events';
|
|
10
|
+
import axios from 'axios';
|
|
11
|
+
import assert from 'assert';
|
|
12
|
+
import {createDIDProvider, IDIDProvider} from './did-provider';
|
|
13
|
+
import { getWallet } from '@docknetwork/wallet-sdk-data-store/src/entities/wallet.entity';
|
|
14
|
+
|
|
15
|
+
export enum VerificationStatus {
|
|
16
|
+
Started = 'Started',
|
|
17
|
+
LoadingTemplate = 'LoadingTemplate',
|
|
18
|
+
Filtering = 'Filtering',
|
|
19
|
+
FetchingProvingKey = 'FetchingProvingKey',
|
|
20
|
+
Error = 'Error',
|
|
21
|
+
NoCredentialsInTheWallet = 'NoCredentialsInTheWallet',
|
|
22
|
+
SelectingCredentials = 'SelectingCredentials',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function isRangeProofTemplate(templateJSON) {
|
|
26
|
+
return templateJSON.proving_key;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type CredentialId = string;
|
|
30
|
+
type CredentialSelection = {
|
|
31
|
+
credential: any;
|
|
32
|
+
attributesToReveal?: string[];
|
|
33
|
+
};
|
|
34
|
+
type CredentialSelectionMap = Map<CredentialId, CredentialSelection>;
|
|
35
|
+
|
|
36
|
+
export function createVerificationController({
|
|
37
|
+
wallet,
|
|
38
|
+
credentialProvider,
|
|
39
|
+
didProvider,
|
|
40
|
+
}: {
|
|
41
|
+
wallet: IWallet;
|
|
42
|
+
credentialProvider?: ICredentialProvider;
|
|
43
|
+
didProvider?: IDIDProvider;
|
|
44
|
+
}) {
|
|
45
|
+
const emitter = new EventEmitter();
|
|
46
|
+
let templateJSON = null;
|
|
47
|
+
let status = VerificationStatus.Started;
|
|
48
|
+
/**
|
|
49
|
+
* Extra data to give better context to the current state
|
|
50
|
+
* Can be used to show error messages, or more specific information about the state
|
|
51
|
+
*/
|
|
52
|
+
let statusData = null;
|
|
53
|
+
let filteredCredentials = [];
|
|
54
|
+
let selectedCredentials: CredentialSelectionMap = new Map();
|
|
55
|
+
let selectedDID = null;
|
|
56
|
+
let provingKey = null;
|
|
57
|
+
|
|
58
|
+
if (!credentialProvider) {
|
|
59
|
+
credentialProvider = createCredentialProvider({wallet});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!didProvider) {
|
|
63
|
+
didProvider = createDIDProvider({wallet});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function fetchProvingKey(templateJSON: any) {
|
|
67
|
+
if (templateJSON.proving_key) {
|
|
68
|
+
setState(VerificationStatus.FetchingProvingKey);
|
|
69
|
+
try {
|
|
70
|
+
provingKey = await axios
|
|
71
|
+
.get(templateJSON.proving_key)
|
|
72
|
+
.then(res => res.data);
|
|
73
|
+
} catch (err) {
|
|
74
|
+
setState(VerificationStatus.Error, {
|
|
75
|
+
message: 'failed_to_fetch_proving_key',
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
throw err;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function start({template}: {template: string | any}) {
|
|
84
|
+
setState(VerificationStatus.LoadingTemplate);
|
|
85
|
+
|
|
86
|
+
// check for dids
|
|
87
|
+
const dids = await didProvider.getAll();
|
|
88
|
+
|
|
89
|
+
if (!dids.length) {
|
|
90
|
+
setState(VerificationStatus.Error, {
|
|
91
|
+
message: 'no_dids_in_the_wallet',
|
|
92
|
+
});
|
|
93
|
+
throw new Error('No DIDs in the wallet');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// the application needs to verify if there are more DIDs available, and allow the user to change this selection before creating a presentation
|
|
97
|
+
selectedDID = dids[0].didDocument.id;
|
|
98
|
+
templateJSON = await getJSON(template);
|
|
99
|
+
|
|
100
|
+
await fetchProvingKey(templateJSON);
|
|
101
|
+
await loadCredentials();
|
|
102
|
+
|
|
103
|
+
setState(VerificationStatus.SelectingCredentials);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function setState(_status: VerificationStatus, data?: any) {
|
|
107
|
+
status = _status;
|
|
108
|
+
statusData = data;
|
|
109
|
+
emitter.emit(_status, data);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function loadCredentials() {
|
|
113
|
+
setState(VerificationStatus.Filtering);
|
|
114
|
+
|
|
115
|
+
// get wallet credentials and apply pex filter
|
|
116
|
+
const allCredentials = await credentialProvider.getCredentials();
|
|
117
|
+
|
|
118
|
+
if (!allCredentials.length) {
|
|
119
|
+
setState(VerificationStatus.NoCredentialsInTheWallet);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const result = await pexService.filterCredentials({
|
|
125
|
+
credentials: allCredentials,
|
|
126
|
+
presentationDefinition: getPresentationDefinition(),
|
|
127
|
+
holderDIDs: [],
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
filteredCredentials = result.verifiableCredential;
|
|
131
|
+
} catch (err) {
|
|
132
|
+
console.error(
|
|
133
|
+
`Unable to filter credentials using the template: \n ${JSON.stringify(
|
|
134
|
+
templateJSON,
|
|
135
|
+
null,
|
|
136
|
+
2,
|
|
137
|
+
)}`,
|
|
138
|
+
);
|
|
139
|
+
console.error(err);
|
|
140
|
+
|
|
141
|
+
setState(VerificationStatus.Error);
|
|
142
|
+
throw err;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function getPresentationDefinition() {
|
|
147
|
+
return templateJSON.request;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function isBBSPlusCredential(credential) {
|
|
151
|
+
return credentialServiceRPC.isBBSPlusCredential({credential});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function createPresentation() {
|
|
155
|
+
assert(!!selectedDID, 'No DID selected');
|
|
156
|
+
assert(!!selectedCredentials.size, 'No credentials selected');
|
|
157
|
+
|
|
158
|
+
if (isRangeProofTemplate(templateJSON)) {
|
|
159
|
+
// TODO: Implement proving key usage for range-proofs
|
|
160
|
+
assert(!!provingKey, 'No proving key found');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const credentials = [];
|
|
164
|
+
|
|
165
|
+
for (const credentialSelection of selectedCredentials.values()) {
|
|
166
|
+
const isBBS = await isBBSPlusCredential(credentialSelection.credential);
|
|
167
|
+
|
|
168
|
+
if (!isBBS) {
|
|
169
|
+
credentials.push(credentialSelection.credential);
|
|
170
|
+
} else {
|
|
171
|
+
// derive BBS credential
|
|
172
|
+
const derivedCredentials =
|
|
173
|
+
await credentialServiceRPC.deriveVCFromBBSPresentation({
|
|
174
|
+
proofRequest: templateJSON,
|
|
175
|
+
|
|
176
|
+
credentials: [
|
|
177
|
+
{
|
|
178
|
+
credential: credentialSelection.credential,
|
|
179
|
+
witness: await credentialProvider.getMembershipWitness(credentialSelection.credential.id),
|
|
180
|
+
attributesToReveal: [
|
|
181
|
+
...(credentialSelection.attributesToReveal || []),
|
|
182
|
+
'id',
|
|
183
|
+
],
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
console.log('Credential derived');
|
|
189
|
+
|
|
190
|
+
credentials.push(derivedCredentials[0]);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const didKeyPairList = await didProvider.getDIDKeyPairs();
|
|
195
|
+
const keyDoc = didKeyPairList.find(doc => doc.controller === selectedDID);
|
|
196
|
+
|
|
197
|
+
assert(keyDoc, `No key pair found for the selected DID ${selectedDID}`);
|
|
198
|
+
|
|
199
|
+
const presentation = await credentialServiceRPC.createPresentation({
|
|
200
|
+
credentials,
|
|
201
|
+
challenge: templateJSON.nonce,
|
|
202
|
+
keyDoc,
|
|
203
|
+
id: keyDoc.controller.startsWith('did:key:')
|
|
204
|
+
? keyDoc.id
|
|
205
|
+
: `${keyDoc.controller}#keys-1`,
|
|
206
|
+
domain: 'dock.io',
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
return presentation;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Filtered credentials
|
|
214
|
+
*/
|
|
215
|
+
function getFilteredCredentials() {
|
|
216
|
+
return filteredCredentials;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function getStatus() {
|
|
220
|
+
return status;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function getStatusData() {
|
|
224
|
+
return statusData;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function setSelectedDID(did: string) {
|
|
228
|
+
selectedDID = did;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Use pex to evaluate presentation
|
|
233
|
+
*
|
|
234
|
+
* @param presentation
|
|
235
|
+
*/
|
|
236
|
+
function evaluatePresentation(presentation) {
|
|
237
|
+
const definition = getPresentationDefinition();
|
|
238
|
+
const result = credentialServiceRPC.evaluatePresentation({
|
|
239
|
+
presentation,
|
|
240
|
+
presentationDefinition: definition,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
isValid: result.errors.length === 0,
|
|
245
|
+
errors: result.errors,
|
|
246
|
+
warnings: result.warnings,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function submitPresentation(presentation) {
|
|
251
|
+
return axios
|
|
252
|
+
.post(templateJSON.response_url, presentation)
|
|
253
|
+
.then(res => res.data);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
emitter,
|
|
258
|
+
selectedCredentials,
|
|
259
|
+
getStatus,
|
|
260
|
+
getStatusData,
|
|
261
|
+
submitPresentation,
|
|
262
|
+
getSelectedDID() {
|
|
263
|
+
return selectedDID;
|
|
264
|
+
},
|
|
265
|
+
setSelectedDID,
|
|
266
|
+
start,
|
|
267
|
+
isBBSPlusCredential,
|
|
268
|
+
loadCredentials,
|
|
269
|
+
getFilteredCredentials,
|
|
270
|
+
createPresentation,
|
|
271
|
+
evaluatePresentation,
|
|
272
|
+
getTemplateJSON() {
|
|
273
|
+
return templateJSON;
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
import {IDIDProvider} from '../did-provider';
|
|
3
|
+
import {
|
|
4
|
+
Goals,
|
|
5
|
+
MessageTypes,
|
|
6
|
+
buildAckWalletToWalletVerificationMessage,
|
|
7
|
+
buildVerificationFlowInviteMessage,
|
|
8
|
+
buildRequestVerifiablePresentationMessage,
|
|
9
|
+
buildVerifiablePresentationAckMessage,
|
|
10
|
+
buildVerifiablePresentationMessage,
|
|
11
|
+
} from '../messages/message-helpers';
|
|
12
|
+
import {IWallet} from '../types';
|
|
13
|
+
import {IMessageProvider} from '../message-provider';
|
|
14
|
+
import {logger} from '@docknetwork/wallet-sdk-data-store/src/logger';
|
|
15
|
+
|
|
16
|
+
const ProofRequestTemplateType = 'ProofRequestTemplate';
|
|
17
|
+
|
|
18
|
+
export interface IWalletToWalletVerificationProvider {
|
|
19
|
+
getInvitationOOBMessage: ({templateId}: {templateId: string}) => Promise<any>;
|
|
20
|
+
setProofRequestHandler: (
|
|
21
|
+
handler: (proofRequest: any) => any,
|
|
22
|
+
) => Promise<void>;
|
|
23
|
+
setPresentationHandler: (
|
|
24
|
+
handler: (presentation: any, proofRequest: any) => any,
|
|
25
|
+
) => Promise<void>;
|
|
26
|
+
setPresentationAckHandler: (
|
|
27
|
+
handler: (proofRequest: any) => any,
|
|
28
|
+
) => Promise<void>;
|
|
29
|
+
addProofRequestTemplate: (proofRequestTemplate: any) => Promise<any>;
|
|
30
|
+
getProofRequestTemplates: () => Promise<any[]>;
|
|
31
|
+
handleMessage: (message: any) => Promise<boolean>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createWalletToWalletVerificationProvider({
|
|
35
|
+
wallet,
|
|
36
|
+
didProvider,
|
|
37
|
+
messageProvider,
|
|
38
|
+
}: {
|
|
39
|
+
wallet: IWallet;
|
|
40
|
+
didProvider: IDIDProvider;
|
|
41
|
+
messageProvider: IMessageProvider;
|
|
42
|
+
}): IWalletToWalletVerificationProvider {
|
|
43
|
+
// Should be used by the HOLDER to create a presentation for the verifier
|
|
44
|
+
let proofRequestHandler;
|
|
45
|
+
// Should be used by the VERIFIER verify a presentation received by the holder
|
|
46
|
+
let presentationHandler;
|
|
47
|
+
// Can be used by the HOLDER to render the verification results sent by the verifier
|
|
48
|
+
let presentationAckHandler;
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
getInvitationOOBMessage: async ({templateId}) => {
|
|
52
|
+
const defaultDID = await didProvider.getDefaultDID();
|
|
53
|
+
const template = await wallet.getDocumentById(templateId);
|
|
54
|
+
|
|
55
|
+
assert(!!template, `Template with id ${templateId} not found`);
|
|
56
|
+
|
|
57
|
+
return buildVerificationFlowInviteMessage({
|
|
58
|
+
proofRequestId: templateId,
|
|
59
|
+
verifierDID: defaultDID,
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
setProofRequestHandler: async (handler: (proofRequest: any) => any) => {
|
|
63
|
+
proofRequestHandler = handler;
|
|
64
|
+
},
|
|
65
|
+
setPresentationHandler: async (handler: (presentation: any, proofRequest: any) => any) => {
|
|
66
|
+
presentationHandler = handler;
|
|
67
|
+
},
|
|
68
|
+
setPresentationAckHandler: async (handler: (proofRequest: any) => any) => {
|
|
69
|
+
presentationAckHandler = handler;
|
|
70
|
+
},
|
|
71
|
+
addProofRequestTemplate: async (proofRequestTemplate: any) => {
|
|
72
|
+
assert(
|
|
73
|
+
!!proofRequestTemplate.input_descriptors,
|
|
74
|
+
'Input descriptions are required',
|
|
75
|
+
);
|
|
76
|
+
return wallet.addDocument({
|
|
77
|
+
type: ProofRequestTemplateType,
|
|
78
|
+
template: proofRequestTemplate,
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
getProofRequestTemplates: async () => {
|
|
82
|
+
return wallet.getDocumentsByType(ProofRequestTemplateType);
|
|
83
|
+
},
|
|
84
|
+
handleMessage: async (message: any) => {
|
|
85
|
+
logger.debug('Received message');
|
|
86
|
+
logger.debug(message);
|
|
87
|
+
if (
|
|
88
|
+
message.type === MessageTypes.Invitation &&
|
|
89
|
+
message?.body?.goal_code === Goals.WalletToWalletVerification
|
|
90
|
+
) {
|
|
91
|
+
// Received a verification invitation from the verifier
|
|
92
|
+
// Sends back an ack message to the verifier
|
|
93
|
+
const defaultDID = await didProvider.getDefaultDID();
|
|
94
|
+
logger.debug('Received invitation');
|
|
95
|
+
logger.debug('Sending ack message to the verifier');
|
|
96
|
+
messageProvider.sendMessage(
|
|
97
|
+
buildAckWalletToWalletVerificationMessage({
|
|
98
|
+
holderDID: defaultDID,
|
|
99
|
+
proofRequestId: message.body.proofRequestId,
|
|
100
|
+
verifierDID: message.from,
|
|
101
|
+
}),
|
|
102
|
+
);
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// The holder sent an ack message to the verifier invite
|
|
107
|
+
// Now the verifier knows the holder did and can offer a proof request
|
|
108
|
+
if (
|
|
109
|
+
message.type === MessageTypes.Ack &&
|
|
110
|
+
message?.body?.goal_code === Goals.WalletToWalletVerification
|
|
111
|
+
) {
|
|
112
|
+
async function process() {
|
|
113
|
+
logger.debug(message);
|
|
114
|
+
const templateId = message.body.proofRequestId;
|
|
115
|
+
assert(!!templateId, 'Template ID not found in ack message');
|
|
116
|
+
const defaultDID = await didProvider.getDefaultDID();
|
|
117
|
+
const proofRequestTemplate = await wallet.getDocumentById(templateId);
|
|
118
|
+
|
|
119
|
+
assert(!!proofRequestTemplate, 'Proof request template not found');
|
|
120
|
+
|
|
121
|
+
logger.debug('Sending proof request to the holder');
|
|
122
|
+
|
|
123
|
+
const proofRequest = proofRequestTemplate.template;
|
|
124
|
+
|
|
125
|
+
assert(!!proofRequest, 'Proof request not found');
|
|
126
|
+
|
|
127
|
+
messageProvider.sendMessage(
|
|
128
|
+
buildRequestVerifiablePresentationMessage({
|
|
129
|
+
proofRequestId: templateId,
|
|
130
|
+
proofRequest: proofRequestTemplate.template,
|
|
131
|
+
holderDID: message.from,
|
|
132
|
+
verifierDID: defaultDID,
|
|
133
|
+
}),
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
process();
|
|
138
|
+
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// The holder received a proof request from the verifier
|
|
143
|
+
if (message.type === MessageTypes.RequestPresentation) {
|
|
144
|
+
logger.debug('Received proof request from the verifier');
|
|
145
|
+
|
|
146
|
+
assert(!!proofRequestHandler, 'No proof request handler set');
|
|
147
|
+
|
|
148
|
+
logger.debug(
|
|
149
|
+
'Waiting for proofRequest handler to return a presentation',
|
|
150
|
+
);
|
|
151
|
+
Promise.resolve(proofRequestHandler(message.body.proofRequest)).then(
|
|
152
|
+
async presentation => {
|
|
153
|
+
logger.debug('Presentation received from handler');
|
|
154
|
+
const defaultDID = await didProvider.getDefaultDID();
|
|
155
|
+
logger.debug('Sending presentation to the verifier');
|
|
156
|
+
messageProvider.sendMessage(
|
|
157
|
+
buildVerifiablePresentationMessage({
|
|
158
|
+
holderDID: defaultDID,
|
|
159
|
+
presentation,
|
|
160
|
+
proofRequestId: message.body.proofRequestId,
|
|
161
|
+
verifierDID: message.from,
|
|
162
|
+
}),
|
|
163
|
+
);
|
|
164
|
+
},
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// The verifier received a presentation from the holder
|
|
171
|
+
if (message.type === MessageTypes.Presentation) {
|
|
172
|
+
logger.debug('Received presentation from the holder');
|
|
173
|
+
|
|
174
|
+
const proofRequestTemplate = await wallet.getDocumentById(message.body.proofRequestId);
|
|
175
|
+
const proofRequest = proofRequestTemplate?.template;
|
|
176
|
+
|
|
177
|
+
assert(!!proofRequest, 'Proof request template not found');
|
|
178
|
+
|
|
179
|
+
logger.debug(
|
|
180
|
+
'Waiting for presentation handler to return a presentation',
|
|
181
|
+
);
|
|
182
|
+
assert(!!presentationHandler, 'No presentation handler set');
|
|
183
|
+
|
|
184
|
+
Promise.resolve(presentationHandler(message.body.presentation, proofRequest)).then(
|
|
185
|
+
async presentationResult => {
|
|
186
|
+
const defaultDID = await didProvider.getDefaultDID();
|
|
187
|
+
logger.debug('Sending presentation ack to the holder');
|
|
188
|
+
messageProvider.sendMessage(
|
|
189
|
+
buildVerifiablePresentationAckMessage({
|
|
190
|
+
holderDID: message.from,
|
|
191
|
+
presentationResult,
|
|
192
|
+
proofRequestId: message.body.proofRequestId,
|
|
193
|
+
verifierDID: defaultDID,
|
|
194
|
+
}),
|
|
195
|
+
);
|
|
196
|
+
},
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// The holder received a presentation ack from the verifier
|
|
203
|
+
if (
|
|
204
|
+
message.type === MessageTypes.Ack &&
|
|
205
|
+
message.body.goal_code === Goals.PresentationAckFromVerifier
|
|
206
|
+
) {
|
|
207
|
+
logger.debug('Received presentation ack from the verifier');
|
|
208
|
+
logger.debug('Presentation ack received');
|
|
209
|
+
if (presentationAckHandler) {
|
|
210
|
+
presentationAckHandler(message.body.presentationResult);
|
|
211
|
+
}
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import {keyringService} from '@docknetwork/wallet-sdk-wasm/src/services/keyring';
|
|
2
|
+
import {utilCryptoService} from '@docknetwork/wallet-sdk-wasm/src/services/util-crypto';
|
|
3
|
+
import {dockService} from '@docknetwork/wallet-sdk-wasm/src/services/dock';
|
|
4
|
+
|
|
5
|
+
import {IWallet} from './types';
|
|
6
|
+
import {Network} from '@docknetwork/wallet-sdk-data-store/src/types';
|
|
7
|
+
import {WalletEvents} from '@docknetwork/wallet-sdk-wasm/src/modules/wallet';
|
|
8
|
+
import { captureException } from './helpers';
|
|
9
|
+
|
|
10
|
+
function isSubstrateNetwork(network: Network) {
|
|
11
|
+
return !!network.configs.substrateUrl;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Update existing substrate network connection
|
|
16
|
+
* Compare connected substrate connection with the current walle network
|
|
17
|
+
* Disconnect and Establish a new connection if the network is different
|
|
18
|
+
*/
|
|
19
|
+
export async function handleSubstrateNetworkChange(
|
|
20
|
+
wallet: IWallet,
|
|
21
|
+
): Promise<void> {
|
|
22
|
+
const currentSubstrateAddress = await dockService.getAddress();
|
|
23
|
+
const substrateNetworkId = wallet.dataStore.networks.find(
|
|
24
|
+
network => network.configs.substrateUrl === currentSubstrateAddress,
|
|
25
|
+
)?.id;
|
|
26
|
+
const currentNetworkId = wallet.dataStore.network?.id;
|
|
27
|
+
|
|
28
|
+
if (substrateNetworkId === currentNetworkId) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
await dockService.disconnect();
|
|
33
|
+
await setSubstrateNetwork(wallet);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function setSubstrateNetwork(wallet: IWallet) {
|
|
37
|
+
const network = wallet.dataStore.network;
|
|
38
|
+
const networkConfigs = network.configs;
|
|
39
|
+
|
|
40
|
+
await keyringService.initialize({
|
|
41
|
+
ss58Format: networkConfigs.addressPrefix,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
dockService
|
|
45
|
+
.init({
|
|
46
|
+
address: networkConfigs.substrateUrl,
|
|
47
|
+
})
|
|
48
|
+
.then(() => {
|
|
49
|
+
wallet.eventManager.emit(WalletEvents.networkConnected);
|
|
50
|
+
})
|
|
51
|
+
.catch(err => {
|
|
52
|
+
captureException(new Error('Unable to connect to substrate node'));
|
|
53
|
+
captureException(err);
|
|
54
|
+
console.error(err);
|
|
55
|
+
wallet.eventManager.emit(WalletEvents.networkError, err);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function initWalletWasm(wallet: IWallet) {
|
|
60
|
+
await utilCryptoService.cryptoWaitReady();
|
|
61
|
+
const network = wallet.dataStore.network;
|
|
62
|
+
|
|
63
|
+
if (isSubstrateNetwork(network)) {
|
|
64
|
+
await setSubstrateNetwork(wallet);
|
|
65
|
+
|
|
66
|
+
wallet.eventManager.on(WalletEvents.networkUpdated, async () => {
|
|
67
|
+
handleSubstrateNetworkChange(wallet);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
wallet.setStatus('ready');
|
|
72
|
+
|
|
73
|
+
wallet.eventManager.emit(WalletEvents.ready);
|
|
74
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {createDIDProvider} from './did-provider';
|
|
2
|
+
import {createWallet, ensureDocumentContext, IWallet} from './wallet';
|
|
3
|
+
|
|
4
|
+
describe('Wallet', () => {
|
|
5
|
+
let wallet: IWallet;
|
|
6
|
+
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
wallet = await createWallet({
|
|
9
|
+
databasePath: ':memory:',
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('expect to create a wallet', async () => {
|
|
14
|
+
expect(wallet).toBeDefined();
|
|
15
|
+
expect(wallet.dataStore).toBeDefined();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('expect to add missing @context on documents', () => {
|
|
19
|
+
const documents = [
|
|
20
|
+
{
|
|
21
|
+
id: 1,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 2,
|
|
25
|
+
'@context': 'test',
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const result = documents.map(ensureDocumentContext);
|
|
30
|
+
|
|
31
|
+
expect(result[0]['@context']).toStrictEqual(['https://w3id.org/wallet/v1']);
|
|
32
|
+
expect(result[1]['@context']).toEqual('test');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('expect to create default dids', async () => {
|
|
36
|
+
const mainnetDIDs = await createDIDProvider({wallet}).getAll();
|
|
37
|
+
expect(mainnetDIDs.length).toBe(1);
|
|
38
|
+
await wallet.setNetwork('testnet');
|
|
39
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
40
|
+
const testnetDIDs = await createDIDProvider({wallet}).getAll();
|
|
41
|
+
expect(testnetDIDs.length).toBe(1);
|
|
42
|
+
expect(mainnetDIDs[0]).not.toEqual(testnetDIDs[0]);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('document CRUD', () => {
|
|
46
|
+
const mockDocument = {
|
|
47
|
+
id: 'test',
|
|
48
|
+
type: 'VerifiableCredential',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
beforeEach(async () => {
|
|
52
|
+
await wallet.addDocument(mockDocument);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('expect to get a document by id', async () => {
|
|
56
|
+
const result = await wallet.getDocumentById(mockDocument.id);
|
|
57
|
+
expect(result.id).toEqual(mockDocument.id);
|
|
58
|
+
expect(result).toStrictEqual(mockDocument);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('expect to get document by type', async () => {
|
|
62
|
+
const result = await wallet.getDocumentsByType(mockDocument.type);
|
|
63
|
+
expect(result[0]).toStrictEqual(mockDocument);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('expect to remove a document', async () => {
|
|
67
|
+
await wallet.removeDocument(mockDocument.id);
|
|
68
|
+
const result = await wallet.getDocumentById(mockDocument.id);
|
|
69
|
+
expect(result).toBeNull();
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|