Skip to content

Commit

Permalink
Upgrade dwn-sdk-js to latest v0.4.0 (#736)
Browse files Browse the repository at this point in the history
- migrate `Events` interface to `Messages` interface methods
- `MessagesGet` now returns a single Message along with the data, avoiding a subsequent `RecordsRead` during sync.
- Improved test coverage for sync.
  • Loading branch information
LiranCohen authored Jul 3, 2024
1 parent 169bd1c commit 89f239d
Show file tree
Hide file tree
Showing 14 changed files with 753 additions and 316 deletions.
5 changes: 5 additions & 0 deletions .changeset/grumpy-carpets-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@web5/api": minor
---

Update Agent to latest version along with dwn-sdk-js to v 0.4.0
8 changes: 8 additions & 0 deletions .changeset/lemon-islands-provide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@web5/agent": minor
"@web5/user-agent": minor
"@web5/proxy-agent": minor
"@web5/identity-agent": minor
---

Migrate `Events` interface to `Messages` interface for sync
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@changesets/cli": "^2.27.5",
"@npmcli/package-json": "5.0.0",
"@typescript-eslint/eslint-plugin": "7.9.0",
"@web5/dwn-server": "0.3.1",
"@web5/dwn-server": "0.4.0",
"audit-ci": "^7.0.1",
"eslint-plugin-mocha": "10.4.3",
"npkill": "0.11.3"
Expand All @@ -42,4 +42,4 @@
"ws@<8.17.1": ">=8.17.1"
}
}
}
}
4 changes: 2 additions & 2 deletions packages/agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"dependencies": {
"@noble/ciphers": "0.4.1",
"@scure/bip39": "1.2.2",
"@tbd54566975/dwn-sdk-js": "0.3.10",
"@tbd54566975/dwn-sdk-js": "0.4.0",
"@web5/common": "1.0.0",
"@web5/crypto": "1.0.0",
"@web5/dids": "1.1.0",
Expand Down Expand Up @@ -110,4 +110,4 @@
"sinon": "16.1.3",
"typescript": "5.1.6"
}
}
}
51 changes: 12 additions & 39 deletions packages/agent/src/dwn-api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Readable } from '@web5/common';
import type { DwnConfig, GenericMessage, UnionMessageReply } from '@tbd54566975/dwn-sdk-js';

import { Convert, NodeStream } from '@web5/common';
import { NodeStream } from '@web5/common';
import { utils as cryptoUtils } from '@web5/crypto';
import { DidDht, DidJwk, DidResolverCacheLevel, UniversalResolver } from '@web5/dids';
import { Cid, DataStoreLevel, Dwn, DwnMethodName, EventLogLevel, Message, MessageStoreLevel, ResumableTaskStoreLevel } from '@tbd54566975/dwn-sdk-js';
Expand Down Expand Up @@ -357,54 +357,27 @@ export class AgentDwnApi {
}): Promise<DwnMessageWithBlob<T>> {
const signer = await this.getSigner(author);

// Construct a MessagesGet message to fetch the message.
const messagesGet = await dwnMessageConstructors[DwnInterface.MessagesGet].create({
messageCids: [messageCid],
// Construct a MessagesRead message to fetch the message.
const messagesRead = await dwnMessageConstructors[DwnInterface.MessagesRead].create({
messageCid: messageCid,
signer
});

const result = await this._dwn.processMessage(author, messagesGet.message);
const result = await this._dwn.processMessage(author, messagesRead.message);

if (!(result.entries && result.entries.length === 1)) {
throw new Error('AgentDwnApi: Expected 1 message entry in the MessagesGet response but received none or more than one.');
if (result.status.code !== 200) {
throw new Error(`AgentDwnApi: Failed to read message, response status: ${result.status.code} - ${result.status.detail}`);
}

const [ messageEntry ] = result.entries;

const messageEntry = result.entry!;
const message = messageEntry.message as DwnMessage[T];
if (!message) {
throw new Error(`AgentDwnApi: Message not found with CID: ${messageCid}`);
}

let dwnMessageWithBlob: DwnMessageWithBlob<T> = { message };
// isRecordsWrite(message) && (dwnMessage.data = await this.getDataForRecordsWrite({ author, message, messageEntry, messageType, signer }));

// If the message is a RecordsWrite, either data will be present,
// OR we have to fetch it using a RecordsRead.
if (isRecordsWrite(messageEntry)) {
if (messageEntry.encodedData) {
const dataBytes = Convert.base64Url(messageEntry.encodedData).toUint8Array();
// TODO: test adding the messageEntry.message.descriptor.dataFormat to the Blob constructor.
dwnMessageWithBlob.data = new Blob([dataBytes]);

} else {
const recordsRead = await dwnMessageConstructors[DwnInterface.RecordsRead].create({
filter: {
recordId: messageEntry.message.recordId
},
signer
});
// If the message is a RecordsWrite, data will be present in the form of a stream

const reply = await this._dwn.processMessage(author, recordsRead.message);

if (reply.status.code >= 400) {
const { status: { code, detail } } = reply;
throw new Error(`AgentDwnApi: (${code}) Failed to read data associated with record ${messageEntry.message.recordId}. ${detail}}`);
} else if (reply.record) {
const dataBytes = await NodeStream.consumeToBytes({ readable: reply.record.data });
dwnMessageWithBlob.data = new Blob([dataBytes]);
}
}
if (isRecordsWrite(messageEntry) && messageEntry.data) {
const dataBytes = await NodeStream.consumeToBytes({ readable: messageEntry.data });
dwnMessageWithBlob.data = new Blob([ dataBytes ], { type: messageEntry.message.descriptor.dataFormat });
}

return dwnMessageWithBlob;
Expand Down
2 changes: 1 addition & 1 deletion packages/agent/src/prototyping/clients/dwn-rpc-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export type DwnRpcRequest = {
/** The DID of the target to which the message is addressed. */
targetDid: string;

/** Optional subscription handler for DWN events. */
/** Optional subscription handler for DWN message events. */
subscriptionHandler?: DwnSubscriptionHandler;
}

Expand Down
6 changes: 4 additions & 2 deletions packages/agent/src/prototyping/clients/http-dwn-rpc-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ export class HttpDwnRpcClient implements DwnRpc {
}

const { reply } = dwnRpcResponse.result;
if (dataStream) {
reply['record']['data'] = dataStream;
if (dataStream && reply.record) {
reply.record.data = dataStream;
} else if (dataStream && reply.entry) {
reply.entry.data = dataStream;
}

return reply as DwnRpcResponse;
Expand Down
Loading

0 comments on commit 89f239d

Please sign in to comment.