@dwn-protocol/id-sdk 0.2.5 → 0.2.6
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/package.json +2 -3
- package/src/agent/app-data-store.ts +0 -365
- package/src/agent/did-manager.ts +0 -393
- package/src/agent/dwn-manager.ts +0 -548
- package/src/agent/identity-manager.ts +0 -165
- package/src/agent/index.ts +0 -19
- package/src/agent/json-rpc.ts +0 -107
- package/src/agent/key-manager.ts +0 -302
- package/src/agent/kms-local.ts +0 -412
- package/src/agent/outbox.ts +0 -128
- package/src/agent/rpc-client.ts +0 -223
- package/src/agent/store-managed-did.ts +0 -295
- package/src/agent/store-managed-identity.ts +0 -243
- package/src/agent/store-managed-key.ts +0 -754
- package/src/agent/sync-manager.ts +0 -631
- package/src/agent/test-managed-agent.ts +0 -299
- package/src/agent/types/agent.ts +0 -145
- package/src/agent/types/managed-key.ts +0 -442
- package/src/agent/utils.ts +0 -190
- package/src/common/convert.ts +0 -424
- package/src/common/index.ts +0 -9
- package/src/common/multicodec.ts +0 -176
- package/src/common/object.ts +0 -43
- package/src/common/stores.ts +0 -125
- package/src/common/stream-node.ts +0 -381
- package/src/common/stream.ts +0 -406
- package/src/common/type-utils.ts +0 -117
- package/src/common/types.ts +0 -48
- package/src/credentials/credential-bbs.ts +0 -419
- package/src/credentials/credential.ts +0 -324
- package/src/credentials/index.ts +0 -5
- package/src/credentials/presentation.ts +0 -182
- package/src/credentials/status-list.ts +0 -365
- package/src/credentials/utils.ts +0 -58
- package/src/credentials/validators.ts +0 -52
- package/src/crypto/algorithms-api/aes/base.ts +0 -49
- package/src/crypto/algorithms-api/aes/ctr.ts +0 -51
- package/src/crypto/algorithms-api/aes/index.ts +0 -2
- package/src/crypto/algorithms-api/crypto-algorithm.ts +0 -127
- package/src/crypto/algorithms-api/crypto-key.ts +0 -56
- package/src/crypto/algorithms-api/ec/base.ts +0 -39
- package/src/crypto/algorithms-api/ec/ecdh.ts +0 -53
- package/src/crypto/algorithms-api/ec/ecdsa.ts +0 -37
- package/src/crypto/algorithms-api/ec/eddsa.ts +0 -30
- package/src/crypto/algorithms-api/ec/index.ts +0 -4
- package/src/crypto/algorithms-api/errors.ts +0 -29
- package/src/crypto/algorithms-api/index.ts +0 -6
- package/src/crypto/algorithms-api/pbkdf/index.ts +0 -1
- package/src/crypto/algorithms-api/pbkdf/pbkdf2.ts +0 -91
- package/src/crypto/crypto-algorithms/aes-ctr.ts +0 -70
- package/src/crypto/crypto-algorithms/bbs.ts +0 -110
- package/src/crypto/crypto-algorithms/ecdh.ts +0 -115
- package/src/crypto/crypto-algorithms/ecdsa.ts +0 -111
- package/src/crypto/crypto-algorithms/eddsa.ts +0 -110
- package/src/crypto/crypto-algorithms/index.ts +0 -6
- package/src/crypto/crypto-algorithms/pbkdf2.ts +0 -54
- package/src/crypto/crypto-primitives/aes-ctr.ts +0 -131
- package/src/crypto/crypto-primitives/aes-gcm.ts +0 -138
- package/src/crypto/crypto-primitives/bbs.ts +0 -183
- package/src/crypto/crypto-primitives/concat-kdf.ts +0 -207
- package/src/crypto/crypto-primitives/ed25519.ts +0 -201
- package/src/crypto/crypto-primitives/index.ts +0 -10
- package/src/crypto/crypto-primitives/pbkdf2.ts +0 -78
- package/src/crypto/crypto-primitives/secp256k1.ts +0 -322
- package/src/crypto/crypto-primitives/x25519.ts +0 -101
- package/src/crypto/crypto-primitives/xchacha20-poly1305.ts +0 -46
- package/src/crypto/crypto-primitives/xchacha20.ts +0 -34
- package/src/crypto/index.ts +0 -8
- package/src/crypto/jose.ts +0 -948
- package/src/crypto/types/crypto-key.ts +0 -4
- package/src/crypto/types/iddwn-crypto.ts +0 -119
- package/src/crypto/utils.ts +0 -200
- package/src/did-api.ts +0 -72
- package/src/dids/dht.ts +0 -412
- package/src/dids/did-dht.ts +0 -436
- package/src/dids/did-ion.ts +0 -613
- package/src/dids/did-key.ts +0 -791
- package/src/dids/did-resolver.ts +0 -107
- package/src/dids/index.ts +0 -9
- package/src/dids/resolver-cache-level.ts +0 -82
- package/src/dids/resolver-cache-noop.ts +0 -25
- package/src/dids/types.ts +0 -278
- package/src/dids/utils.ts +0 -129
- package/src/dwn-api.ts +0 -584
- package/src/iddwn.ts +0 -241
- package/src/identity-agent/index.ts +0 -270
- package/src/index.ts +0 -26
- package/src/interfaces/metadata.ts +0 -163
- package/src/interfaces/queue.ts +0 -108
- package/src/interfaces/services.ts +0 -122
- package/src/interfaces/transactions.ts +0 -220
- package/src/protocol.ts +0 -68
- package/src/proxy-agent/index.ts +0 -255
- package/src/record.ts +0 -521
- package/src/service-options.ts +0 -62
- package/src/typings/decentralized-identity__ion-pow-sdk.d.ts +0 -7
- package/src/user-agent/index.ts +0 -295
- package/src/utils.ts +0 -29
- package/src/vc-api.ts +0 -505
package/src/dwn-api.ts
DELETED
|
@@ -1,584 +0,0 @@
|
|
|
1
|
-
import type { DwnResponse, IDAgent } from './agent/index.js';
|
|
2
|
-
import type {
|
|
3
|
-
RecordsReadOptions,
|
|
4
|
-
RecordsQueryOptions,
|
|
5
|
-
RecordsWriteMessage,
|
|
6
|
-
RecordsWriteOptions,
|
|
7
|
-
RecordsDeleteOptions,
|
|
8
|
-
ProtocolsQueryOptions,
|
|
9
|
-
RecordsQueryReplyEntry,
|
|
10
|
-
ProtocolsConfigureMessage,
|
|
11
|
-
ProtocolsConfigureOptions,
|
|
12
|
-
ProtocolsConfigureDescriptor,
|
|
13
|
-
} from '@dwn-protocol/id';
|
|
14
|
-
|
|
15
|
-
import { isEmptyObject } from './common/index.js';
|
|
16
|
-
import { DwnInterfaceName, DwnMethodName, RecordsWrite } from '@dwn-protocol/id';
|
|
17
|
-
|
|
18
|
-
import { Record } from './record.js';
|
|
19
|
-
import { Protocol } from './protocol.js';
|
|
20
|
-
import { dataToBlob } from './utils.js';
|
|
21
|
-
|
|
22
|
-
import { getServiceDwnEndpoints } from './service-options.js';
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Status code and detailed message for a response.
|
|
26
|
-
*
|
|
27
|
-
* @beta
|
|
28
|
-
*/
|
|
29
|
-
export type ResponseStatus = {
|
|
30
|
-
status: {
|
|
31
|
-
code: number;
|
|
32
|
-
detail: string;
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Request to setup a protocol with its definitions
|
|
38
|
-
*
|
|
39
|
-
* @beta
|
|
40
|
-
*/
|
|
41
|
-
export type ProtocolsConfigureRequest = {
|
|
42
|
-
message: Omit<ProtocolsConfigureOptions, 'signer'>;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Response for the protocol configure request
|
|
47
|
-
*
|
|
48
|
-
* @beta
|
|
49
|
-
*/
|
|
50
|
-
export type ProtocolsConfigureResponse = ResponseStatus & {
|
|
51
|
-
protocol?: Protocol;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Represents each entry on the protocols query reply
|
|
56
|
-
*
|
|
57
|
-
* @beta
|
|
58
|
-
*/
|
|
59
|
-
export type ProtocolsQueryReplyEntry = {
|
|
60
|
-
descriptor: ProtocolsConfigureDescriptor;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Request to query protocols
|
|
65
|
-
*
|
|
66
|
-
* @beta
|
|
67
|
-
*/
|
|
68
|
-
export type ProtocolsQueryRequest = {
|
|
69
|
-
from?: string;
|
|
70
|
-
message: Omit<ProtocolsQueryOptions, 'signer'>
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Response with the retrieved protocols
|
|
75
|
-
*
|
|
76
|
-
* @beta
|
|
77
|
-
*/
|
|
78
|
-
export type ProtocolsQueryResponse = ResponseStatus & {
|
|
79
|
-
protocols: Protocol[];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Type alias for {@link RecordsWriteRequest}
|
|
84
|
-
*
|
|
85
|
-
* @beta
|
|
86
|
-
*/
|
|
87
|
-
export type RecordsCreateRequest = RecordsWriteRequest;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Type alias for {@link RecordsWriteResponse}
|
|
91
|
-
*
|
|
92
|
-
* @beta
|
|
93
|
-
*/
|
|
94
|
-
export type RecordsCreateResponse = RecordsWriteResponse;
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Request to create a record from an existing one (useful for updating an existing record)
|
|
98
|
-
*
|
|
99
|
-
* @beta
|
|
100
|
-
*/
|
|
101
|
-
export type RecordsCreateFromRequest = {
|
|
102
|
-
author: string;
|
|
103
|
-
data: unknown;
|
|
104
|
-
message?: Omit<RecordsWriteOptions, 'signer'>;
|
|
105
|
-
record: Record;
|
|
106
|
-
target?: string;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Request to delete a record from the DWN
|
|
111
|
-
*
|
|
112
|
-
* @beta
|
|
113
|
-
*/
|
|
114
|
-
export type RecordsDeleteRequest = {
|
|
115
|
-
from?: string;
|
|
116
|
-
message: Omit<RecordsDeleteOptions, 'signer'>;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Response for the read request
|
|
121
|
-
*
|
|
122
|
-
* @beta
|
|
123
|
-
*/
|
|
124
|
-
export type RecordsQueryRequest = {
|
|
125
|
-
/** The from property indicates the DID to query from and return results. */
|
|
126
|
-
from?: string;
|
|
127
|
-
message: Omit<RecordsQueryOptions, 'signer'>;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Response for the query request
|
|
132
|
-
*
|
|
133
|
-
* @beta
|
|
134
|
-
*/
|
|
135
|
-
export type RecordsQueryResponse = ResponseStatus & {
|
|
136
|
-
records?: Record[],
|
|
137
|
-
/** If there are additional results, the messageCid of the last record will be returned as a pagination cursor. */
|
|
138
|
-
cursor?: string;
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Request to read a record from the DWN
|
|
143
|
-
*
|
|
144
|
-
* @beta
|
|
145
|
-
*/
|
|
146
|
-
export type RecordsReadRequest = {
|
|
147
|
-
/** The from property indicates the DID to read from and return results fro. */
|
|
148
|
-
from?: string;
|
|
149
|
-
message: Omit<RecordsReadOptions, 'signer'>;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Response for the read request
|
|
154
|
-
*
|
|
155
|
-
* @beta
|
|
156
|
-
*/
|
|
157
|
-
export type RecordsReadResponse = ResponseStatus & {
|
|
158
|
-
record: Record;
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Request to write a record to the DWN
|
|
163
|
-
*
|
|
164
|
-
* @beta
|
|
165
|
-
*/
|
|
166
|
-
export type RecordsWriteRequest = {
|
|
167
|
-
data: unknown;
|
|
168
|
-
message?: Omit<Partial<RecordsWriteOptions>, 'signer'>;
|
|
169
|
-
store?: boolean;
|
|
170
|
-
target?: string;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Response for the write request
|
|
175
|
-
*
|
|
176
|
-
* @beta
|
|
177
|
-
*/
|
|
178
|
-
export type RecordsWriteResponse = ResponseStatus & {
|
|
179
|
-
record?: Record
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Interface to interact with DWN Records and Protocols
|
|
184
|
-
*
|
|
185
|
-
* @beta
|
|
186
|
-
*/
|
|
187
|
-
export class DwnApi {
|
|
188
|
-
private agent: IDAgent;
|
|
189
|
-
private connectedDid: string;
|
|
190
|
-
|
|
191
|
-
constructor(options: { agent: IDAgent, connectedDid: string }) {
|
|
192
|
-
this.agent = options.agent;
|
|
193
|
-
this.connectedDid = options.connectedDid;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* API to interact with DWN protocols (e.g., `dwn.protocols.configure()`).
|
|
198
|
-
*/
|
|
199
|
-
get protocols() {
|
|
200
|
-
return {
|
|
201
|
-
/**
|
|
202
|
-
* Configure method, used to setup a new protocol (or update) with the passed definitions
|
|
203
|
-
*/
|
|
204
|
-
configure: async (request: ProtocolsConfigureRequest): Promise<ProtocolsConfigureResponse> => {
|
|
205
|
-
const agentResponse = await this.agent.processDwnRequest({
|
|
206
|
-
target : this.connectedDid,
|
|
207
|
-
author : this.connectedDid,
|
|
208
|
-
messageOptions : request.message,
|
|
209
|
-
messageType : DwnInterfaceName.Protocols + DwnMethodName.Configure
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
const { message, messageCid, reply: { status }} = agentResponse;
|
|
213
|
-
const response: ProtocolsConfigureResponse = { status };
|
|
214
|
-
|
|
215
|
-
if (status.code < 300) {
|
|
216
|
-
const metadata = { author: this.connectedDid, messageCid };
|
|
217
|
-
response.protocol = new Protocol(this.agent, message as ProtocolsConfigureMessage, metadata);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return response;
|
|
221
|
-
},
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Query the available protocols
|
|
225
|
-
*/
|
|
226
|
-
query: async (request: ProtocolsQueryRequest): Promise<ProtocolsQueryResponse> => {
|
|
227
|
-
const agentRequest = {
|
|
228
|
-
author : this.connectedDid,
|
|
229
|
-
messageOptions : request.message,
|
|
230
|
-
messageType : DwnInterfaceName.Protocols + DwnMethodName.Query,
|
|
231
|
-
target : request.from || this.connectedDid
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
let agentResponse: DwnResponse;
|
|
235
|
-
|
|
236
|
-
if (request.from) {
|
|
237
|
-
agentResponse = await this.agent.sendDwnRequest(agentRequest);
|
|
238
|
-
} else {
|
|
239
|
-
agentResponse = await this.agent.processDwnRequest(agentRequest);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const { reply: { entries = [], status } } = agentResponse;
|
|
243
|
-
|
|
244
|
-
const protocols = entries.map((entry: ProtocolsQueryReplyEntry) => {
|
|
245
|
-
const metadata = { author: this.connectedDid, };
|
|
246
|
-
//@ts-ignore
|
|
247
|
-
return new Protocol(this.agent, entry as ProtocolsConfigureMessage, metadata);
|
|
248
|
-
// @todo fix the type, then remove `as ProtocolsConfigureMessage ^
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
return { protocols, status };
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* API to interact with DWN records (e.g., `dwn.records.create()`).
|
|
258
|
-
*/
|
|
259
|
-
get records() {
|
|
260
|
-
return {
|
|
261
|
-
/**
|
|
262
|
-
* Alias for the `write` method
|
|
263
|
-
*/
|
|
264
|
-
create: async (request: RecordsCreateRequest): Promise<RecordsCreateResponse> => {
|
|
265
|
-
return this.records.write(request);
|
|
266
|
-
},
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Write a record based on an existing one (useful for updating an existing record)
|
|
270
|
-
*/
|
|
271
|
-
createFrom: async (request: RecordsCreateFromRequest): Promise<RecordsWriteResponse> => {
|
|
272
|
-
const { author: inheritedAuthor, ...inheritedProperties } = request.record.toJSON();
|
|
273
|
-
|
|
274
|
-
// Remove target from inherited properties since target is being explicitly defined in method parameters.
|
|
275
|
-
delete inheritedProperties.target;
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
// If `data` is being updated then `dataCid` and `dataSize` must not be present.
|
|
279
|
-
if (request.data !== undefined) {
|
|
280
|
-
delete inheritedProperties.dataCid;
|
|
281
|
-
delete inheritedProperties.dataSize;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Ensure update gets a new messageTimestamp so it's always "newer" than the original.
|
|
285
|
-
// Mirrors @abaxxtech/id RecordsWrite.createFrom behavior.
|
|
286
|
-
delete inheritedProperties.messageTimestamp;
|
|
287
|
-
|
|
288
|
-
// If `published` is set to false, ensure that `datePublished` is undefined. Otherwise, DWN SDK's schema validation
|
|
289
|
-
// will throw an error if `published` is false but `datePublished` is set.
|
|
290
|
-
if (request.message?.published === false && inheritedProperties.datePublished !== undefined) {
|
|
291
|
-
delete inheritedProperties.datePublished;
|
|
292
|
-
delete inheritedProperties.published;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// If the request changes the `author` or message `descriptor` then the deterministic `recordId` will change.
|
|
296
|
-
// As a result, we will discard the `recordId` if either of these changes occur.
|
|
297
|
-
// NOTE: `isEmptyObject(undefined)` returns false, so we must guard against undefined/null
|
|
298
|
-
// to avoid discarding `recordId` when no message overrides are provided (update case).
|
|
299
|
-
const hasMessageOverrides = request.message != null && !isEmptyObject(request.message);
|
|
300
|
-
const hasAuthorChange = request.author && request.author !== inheritedAuthor;
|
|
301
|
-
if (hasMessageOverrides || hasAuthorChange) {
|
|
302
|
-
delete inheritedProperties.recordId;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
return this.records.write({
|
|
306
|
-
data : request.data,
|
|
307
|
-
target : request.target,
|
|
308
|
-
message : {
|
|
309
|
-
...inheritedProperties,
|
|
310
|
-
...request.message,
|
|
311
|
-
},
|
|
312
|
-
});
|
|
313
|
-
},
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* Delete a record
|
|
317
|
-
*/
|
|
318
|
-
delete: async (request: RecordsDeleteRequest): Promise<ResponseStatus> => {
|
|
319
|
-
const agentRequest = {
|
|
320
|
-
author : this.connectedDid,
|
|
321
|
-
messageOptions : request.message,
|
|
322
|
-
messageType : DwnInterfaceName.Records + DwnMethodName.Delete,
|
|
323
|
-
target : request.from || this.connectedDid
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
let agentResponse: DwnResponse;
|
|
327
|
-
|
|
328
|
-
if (request.from) {
|
|
329
|
-
agentResponse = await this.agent.sendDwnRequest(agentRequest);
|
|
330
|
-
} else {
|
|
331
|
-
agentResponse = await this.agent.processDwnRequest(agentRequest);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
const { reply: { status } } = agentResponse;
|
|
335
|
-
return { status };
|
|
336
|
-
},
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Query a single or multiple records based on the given filter
|
|
340
|
-
*/
|
|
341
|
-
query: async (request: RecordsQueryRequest): Promise<RecordsQueryResponse> => {
|
|
342
|
-
const agentRequest = {
|
|
343
|
-
author : this.connectedDid,
|
|
344
|
-
messageOptions : request.message,
|
|
345
|
-
messageType : DwnInterfaceName.Records + DwnMethodName.Query,
|
|
346
|
-
target : request.from || this.connectedDid
|
|
347
|
-
};
|
|
348
|
-
|
|
349
|
-
let agentResponse: DwnResponse;
|
|
350
|
-
|
|
351
|
-
if (request.from) {
|
|
352
|
-
agentResponse = await this.agent.sendDwnRequest(agentRequest);
|
|
353
|
-
} else {
|
|
354
|
-
agentResponse = await this.agent.processDwnRequest(agentRequest);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const { reply: { entries, status, cursor } } = agentResponse;
|
|
358
|
-
|
|
359
|
-
const records = entries.map((entry: RecordsQueryReplyEntry) => {
|
|
360
|
-
const recordOptions = {
|
|
361
|
-
/**
|
|
362
|
-
* Extract the `author` DID from the record entry since records may be signed by the
|
|
363
|
-
* tenant owner or any other entity.
|
|
364
|
-
*/
|
|
365
|
-
author : RecordsWrite.getAuthor(entry),
|
|
366
|
-
/**
|
|
367
|
-
* Set the `target` DID to currently connected DID so that subsequent calls to
|
|
368
|
-
* {@link Record} instance methods, such as `record.update()` are executed on the
|
|
369
|
-
* local DWN even if the record was returned by a query of a remote DWN.
|
|
370
|
-
*/
|
|
371
|
-
target : this.connectedDid,
|
|
372
|
-
...entry as RecordsWriteMessage
|
|
373
|
-
};
|
|
374
|
-
const record = new Record(this.agent, recordOptions);
|
|
375
|
-
return record;
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
return { records, status, cursor };
|
|
379
|
-
},
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Read a single record based on the given filter
|
|
383
|
-
*/
|
|
384
|
-
read: async (request: RecordsReadRequest): Promise<RecordsReadResponse> => {
|
|
385
|
-
const agentRequest = {
|
|
386
|
-
author : this.connectedDid,
|
|
387
|
-
messageOptions : request.message,
|
|
388
|
-
messageType : DwnInterfaceName.Records + DwnMethodName.Read,
|
|
389
|
-
target : request.from || this.connectedDid
|
|
390
|
-
};
|
|
391
|
-
|
|
392
|
-
let agentResponse: DwnResponse;
|
|
393
|
-
|
|
394
|
-
if (request.from) {
|
|
395
|
-
agentResponse = await this.agent.sendDwnRequest(agentRequest);
|
|
396
|
-
} else {
|
|
397
|
-
agentResponse = await this.agent.processDwnRequest(agentRequest);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
const { reply: { record: responseRecord, status } } = agentResponse;
|
|
401
|
-
|
|
402
|
-
let record: Record;
|
|
403
|
-
if (200 <= status.code && status.code <= 299) {
|
|
404
|
-
const recordOptions = {
|
|
405
|
-
author : RecordsWrite.getAuthor(responseRecord),
|
|
406
|
-
target : this.connectedDid,
|
|
407
|
-
...responseRecord,
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
record = new Record(this.agent, recordOptions);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
return { record, status };
|
|
414
|
-
},
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Writes a record to the DWN
|
|
418
|
-
*
|
|
419
|
-
* As a convenience, the Record instance returned will cache a copy of the data if the
|
|
420
|
-
* data size, in bytes, is less than the DWN 'max data size allowed to be encoded'
|
|
421
|
-
* parameter of 10KB. This is done to maintain consistency with other DWN methods,
|
|
422
|
-
* like RecordsQuery, that include relatively small data payloads when returning
|
|
423
|
-
* RecordsWrite message properties. Regardless of data size, methods such as
|
|
424
|
-
* `record.data.stream()` will return the data when called even if it requires fetching
|
|
425
|
-
* from the DWN datastore.
|
|
426
|
-
*/
|
|
427
|
-
write: async (request: RecordsWriteRequest): Promise<RecordsWriteResponse> => {
|
|
428
|
-
const messageOptions: Partial<RecordsWriteOptions> = {
|
|
429
|
-
...request.message
|
|
430
|
-
};
|
|
431
|
-
|
|
432
|
-
const { dataBlob, dataFormat } = dataToBlob(request.data, messageOptions.dataFormat);
|
|
433
|
-
messageOptions.dataFormat = dataFormat;
|
|
434
|
-
|
|
435
|
-
const target = request.target || this.connectedDid;
|
|
436
|
-
const isRemote = target !== this.connectedDid;
|
|
437
|
-
|
|
438
|
-
let agentResponse: DwnResponse;
|
|
439
|
-
|
|
440
|
-
if (isRemote) {
|
|
441
|
-
agentResponse = await this.agent.sendDwnRequest({
|
|
442
|
-
author : this.connectedDid,
|
|
443
|
-
dataStream : dataBlob,
|
|
444
|
-
messageOptions,
|
|
445
|
-
messageType : DwnInterfaceName.Records + DwnMethodName.Write,
|
|
446
|
-
target : target
|
|
447
|
-
});
|
|
448
|
-
} else {
|
|
449
|
-
agentResponse = await this.agent.processDwnRequest({
|
|
450
|
-
author : this.connectedDid,
|
|
451
|
-
dataStream : dataBlob,
|
|
452
|
-
messageOptions,
|
|
453
|
-
messageType : DwnInterfaceName.Records + DwnMethodName.Write,
|
|
454
|
-
store : request.store,
|
|
455
|
-
target : this.connectedDid
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
const { message, reply: { status } } = agentResponse;
|
|
460
|
-
const responseMessage = message as RecordsWriteMessage;
|
|
461
|
-
|
|
462
|
-
let record: Record;
|
|
463
|
-
if (200 <= status.code && status.code <= 299) {
|
|
464
|
-
const recordOptions = {
|
|
465
|
-
author : this.connectedDid,
|
|
466
|
-
encodedData : dataBlob,
|
|
467
|
-
target : target,
|
|
468
|
-
...responseMessage,
|
|
469
|
-
};
|
|
470
|
-
|
|
471
|
-
record = new Record(this.agent, recordOptions);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
return { record, status };
|
|
475
|
-
},
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* API to retrieve the service nodes via did:web:dwn.x.id.
|
|
481
|
-
*/
|
|
482
|
-
async getServiceNodes(): Promise<any> {
|
|
483
|
-
return await getServiceDwnEndpoints();
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
/**
|
|
487
|
-
* Helper method to resolve encryption keys from a recipient's DID.
|
|
488
|
-
* This can be used to get encryption keys before creating an encrypted RecordsWrite.
|
|
489
|
-
*
|
|
490
|
-
* @param recipientDid - The DID of the recipient
|
|
491
|
-
* @param options - Optional configuration
|
|
492
|
-
* @param options.useRelayEndpoint - If true, uses the relay's /api/did/:did/encryption-keys endpoint (default: false)
|
|
493
|
-
* @param options.relayUrl - The relay URL to use (default: tries to detect from service endpoints)
|
|
494
|
-
* @returns Array of encryption keys with keyId, publicKeyJwk, and keyType
|
|
495
|
-
*/
|
|
496
|
-
async resolveRecipientEncryptionKeys(
|
|
497
|
-
recipientDid: string,
|
|
498
|
-
options?: { useRelayEndpoint?: boolean; relayUrl?: string }
|
|
499
|
-
): Promise<Array<{ keyId: string; publicKeyJwk: any; keyType: string }>> {
|
|
500
|
-
const { useRelayEndpoint = false, relayUrl } = options || {};
|
|
501
|
-
|
|
502
|
-
// Option 1: Use relay endpoint if specified
|
|
503
|
-
if (useRelayEndpoint) {
|
|
504
|
-
try {
|
|
505
|
-
const url = relayUrl || (await getServiceDwnEndpoints())[0] || 'http://localhost:8085';
|
|
506
|
-
const response = await fetch(`${url}/api/did/${recipientDid}/encryption-keys`);
|
|
507
|
-
const result = await response.json();
|
|
508
|
-
|
|
509
|
-
if (result.ok && result.encryptionKeys) {
|
|
510
|
-
return result.encryptionKeys;
|
|
511
|
-
}
|
|
512
|
-
} catch (error) {
|
|
513
|
-
console.warn('Failed to resolve encryption keys via relay endpoint:', error);
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// Option 2: Use SDK's built-in DID resolver
|
|
518
|
-
try {
|
|
519
|
-
// Check if agent has didResolver (IDManagedAgent)
|
|
520
|
-
const managedAgent = this.agent as any;
|
|
521
|
-
if (!managedAgent.didResolver) {
|
|
522
|
-
throw new Error('DID resolver not available. Use useRelayEndpoint: true or ensure agent is properly initialized.');
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
const { didDocument } = await managedAgent.didResolver.resolve(recipientDid);
|
|
526
|
-
|
|
527
|
-
if (!didDocument) {
|
|
528
|
-
throw new Error(`DID document not found for ${recipientDid}`);
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
const encryptionKeys: Array<{ keyId: string; publicKeyJwk: any; keyType: string }> = [];
|
|
532
|
-
|
|
533
|
-
// Look for verification methods with publicKeyJwk
|
|
534
|
-
if (didDocument.verificationMethod) {
|
|
535
|
-
for (const vm of didDocument.verificationMethod) {
|
|
536
|
-
if (vm.publicKeyJwk && vm.id) {
|
|
537
|
-
const keyId = vm.id.includes('#') ? vm.id.split('#')[1] : vm.id;
|
|
538
|
-
if (keyId) {
|
|
539
|
-
encryptionKeys.push({
|
|
540
|
-
keyId,
|
|
541
|
-
publicKeyJwk : vm.publicKeyJwk,
|
|
542
|
-
keyType : vm.type || 'Unknown',
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// Also check keyAgreement section
|
|
550
|
-
if (didDocument.keyAgreement) {
|
|
551
|
-
for (const ka of didDocument.keyAgreement) {
|
|
552
|
-
if (typeof ka === 'string') {
|
|
553
|
-
const keyId = ka.includes('#') ? ka.split('#')[1] : ka;
|
|
554
|
-
const vm = didDocument.verificationMethod?.find(
|
|
555
|
-
(v) => v.id === ka || v.id.endsWith(`#${keyId}`)
|
|
556
|
-
);
|
|
557
|
-
if (vm?.publicKeyJwk && keyId) {
|
|
558
|
-
encryptionKeys.push({
|
|
559
|
-
keyId,
|
|
560
|
-
publicKeyJwk : vm.publicKeyJwk,
|
|
561
|
-
keyType : vm.type || 'Unknown',
|
|
562
|
-
});
|
|
563
|
-
}
|
|
564
|
-
} else if (ka.publicKeyJwk) {
|
|
565
|
-
const keyId = ka.id?.includes('#')
|
|
566
|
-
? ka.id.split('#')[1]
|
|
567
|
-
: ka.id || 'unknown';
|
|
568
|
-
if (keyId) {
|
|
569
|
-
encryptionKeys.push({
|
|
570
|
-
keyId,
|
|
571
|
-
publicKeyJwk : ka.publicKeyJwk,
|
|
572
|
-
keyType : ka.type || 'Unknown',
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
return encryptionKeys;
|
|
580
|
-
} catch (error: any) {
|
|
581
|
-
throw new Error(`Failed to resolve encryption keys for ${recipientDid}: ${error.message}`);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
}
|