diff --git a/examples/wallet-connect.html b/examples/wallet-connect.html
index eb3e813ab..35d0e8369 100644
--- a/examples/wallet-connect.html
+++ b/examples/wallet-connect.html
@@ -128,35 +128,16 @@
Success
},
};
- const scopes = [
- {
- interface: "Records",
- method: "Write",
- protocol: "http://profile-protocol.xyz",
- },
- {
- interface: "Records",
- method: "Query",
- protocol: "http://profile-protocol.xyz",
- },
- {
- interface: "Records",
- method: "Read",
- protocol: "http://profile-protocol.xyz",
- },
- ];
+ const permissionRequests = Web5.requestPermissions([{
+ definition: profileProtocol,
+ }]);
try {
const { delegateDid } = await Web5.connect({
walletConnectOptions: {
walletUri: "web5://connect",
connectServerUrl: "http://localhost:3000/connect",
- permissionRequests: [
- {
- protocolDefinition: profileProtocol,
- permissionScopes: scopes,
- },
- ],
+ permissionRequests: permissionRequests,
onWalletUriReady: generateQRCode,
validatePin: async () => {
goToPinScreen();
diff --git a/packages/agent/src/connect.ts b/packages/agent/src/connect.ts
index a3d671185..abe89333b 100644
--- a/packages/agent/src/connect.ts
+++ b/packages/agent/src/connect.ts
@@ -1,13 +1,15 @@
-import { CryptoUtils } from '@web5/crypto';
-import { DwnPermissionScope, DwnProtocolDefinition, DwnRecordsPermissionScope } from './index.js';
+
+import type { PushedAuthResponse } from './oidc.js';
+import type { DwnPermissionScope, DwnProtocolDefinition, Web5ConnectAuthResponse } from './index.js';
+
import {
- Web5ConnectAuthResponse,
Oidc,
- type PushedAuthResponse,
} from './oidc.js';
import { pollWithTtl } from './utils.js';
-import { DidJwk } from '@web5/dids';
+
import { Convert } from '@web5/common';
+import { CryptoUtils } from '@web5/crypto';
+import { DidJwk } from '@web5/dids';
import { DwnInterfaceName, DwnMethodName } from '@tbd54566975/dwn-sdk-js';
/**
@@ -183,9 +185,9 @@ export type ConnectPermissionRequest = {
permissionScopes: DwnPermissionScope[];
};
-export type PermissionRequest = 'write' | 'read' | 'delete' | 'query' | 'subscribe';
+export type Permission = 'write' | 'read' | 'delete' | 'query' | 'subscribe';
-function requestPermissionsForProtocol(definition: DwnProtocolDefinition, permissions: PermissionRequest[]): ConnectPermissionRequest {
+function requestPermissionsForProtocol(definition: DwnProtocolDefinition, permissions: Permission[]): ConnectPermissionRequest {
const requests: DwnPermissionScope[] = [];
// In order to enable sync, we must request permissions for `MessagesQuery`, `MessagesRead` and `MessagesSubscribe`
diff --git a/packages/agent/src/oidc.ts b/packages/agent/src/oidc.ts
index 2952d55b3..169c40ff1 100644
--- a/packages/agent/src/oidc.ts
+++ b/packages/agent/src/oidc.ts
@@ -12,13 +12,13 @@ import { concatenateUrl } from './utils.js';
import { xchacha20poly1305 } from '@noble/ciphers/chacha';
import type { ConnectPermissionRequest } from './connect.js';
import { DidDocument, DidJwk, PortableDid, type BearerDid } from '@web5/dids';
-import { AgentDwnApi } from './dwn-api.js';
import type {
PermissionScope,
RecordsWriteMessage,
} from '@tbd54566975/dwn-sdk-js';
import { DwnInterface, DwnProtocolDefinition } from './types/dwn.js';
import { AgentPermissionsApi } from './permissions-api.js';
+import type { Web5Agent } from './types/agent.js';
/**
* Sent to an OIDC server to authorize a client. Allows clients
@@ -614,11 +614,11 @@ function encryptAuthResponse({
async function createPermissionGrants(
selectedDid: string,
delegateBearerDid: BearerDid,
- dwn: AgentDwnApi,
+ agent: Web5Agent,
scopes: PermissionScope[],
) {
- const permissionsApi = new AgentPermissionsApi(dwn);
+ const permissionsApi = new AgentPermissionsApi({ agent });
// TODO: cleanup all grants if one fails by deleting them from the DWN: https://github.com/TBD54566975/web5-js/issues/849
const permissionGrants = await Promise.all(
@@ -638,19 +638,17 @@ async function createPermissionGrants(
const { encodedData, ...rawMessage } = grant.message;
const data = Convert.base64Url(encodedData).toUint8Array();
- const params = {
+ const { reply } = await agent.sendDwnRequest({
author : selectedDid,
target : selectedDid,
messageType : DwnInterface.RecordsWrite,
dataStream : new Blob([data]),
rawMessage,
- };
-
- const sent = await dwn.sendRequest(params);
+ });
- if (sent.reply.status.code !== 202) {
+ if (reply.status.code !== 202) {
throw new Error(
- `Could not send the message. Error details: ${sent.reply.status.detail}`
+ `Could not send the message. Error details: ${reply.status.detail}`
);
}
@@ -668,10 +666,10 @@ async function createPermissionGrants(
*/
async function prepareProtocols(
selectedDid: string,
- agentDwnApi: AgentDwnApi,
+ agent: Web5Agent,
protocolDefinition: DwnProtocolDefinition
) {
- const queryMessage = await agentDwnApi.processRequest({
+ const queryMessage = await agent.processDwnRequest({
author : selectedDid,
messageType : DwnInterface.ProtocolsQuery,
target : selectedDid,
@@ -679,7 +677,7 @@ async function prepareProtocols(
});
if (queryMessage.reply.status.code === 404) {
- const configureMessage = await agentDwnApi.processRequest({
+ const configureMessage = await agent.processDwnRequest({
author : selectedDid,
messageType : DwnInterface.ProtocolsConfigure,
target : selectedDid,
@@ -707,7 +705,7 @@ async function submitAuthResponse(
selectedDid: string,
authRequest: Web5ConnectAuthRequest,
randomPin: string,
- agentDwnApi: AgentDwnApi,
+ agent: Web5Agent,
) {
const delegateBearerDid = await DidJwk.create();
const delegatePortableDid = await delegateBearerDid.export();
@@ -716,8 +714,8 @@ async function submitAuthResponse(
// TODO: validate to make sure the scopes and definition are assigned to the same protocol
const { protocolDefinition, permissionScopes } = permissionRequest;
- await prepareProtocols(selectedDid, agentDwnApi, protocolDefinition);
- const permissionGrants = await Oidc.createPermissionGrants(selectedDid, delegateBearerDid, agentDwnApi, permissionScopes);
+ await prepareProtocols(selectedDid, agent, protocolDefinition);
+ const permissionGrants = await Oidc.createPermissionGrants(selectedDid, delegateBearerDid, agent, permissionScopes);
return permissionGrants;
});
diff --git a/packages/agent/tests/connect.spec.ts b/packages/agent/tests/connect.spec.ts
index ee0aa5f15..6bb5d36a0 100644
--- a/packages/agent/tests/connect.spec.ts
+++ b/packages/agent/tests/connect.spec.ts
@@ -288,7 +288,7 @@ describe('web5 connect', function () {
const results = await Oidc.createPermissionGrants(
providerIdentity.did.uri,
delegateBearerDid,
- testHarness.agent.dwn,
+ testHarness.agent,
permissionScopes
);
const scopesRequestedPlusTwoDefaultScopes = permissionScopes.length;
@@ -390,7 +390,7 @@ describe('web5 connect', function () {
selectedDid,
authRequest,
randomPin,
- testHarness.agent.dwn
+ testHarness.agent
);
expect(fetchSpy.calledOnce).to.be.true;
});
diff --git a/packages/api/src/web5.ts b/packages/api/src/web5.ts
index 112579de1..0f45bcbb7 100644
--- a/packages/api/src/web5.ts
+++ b/packages/api/src/web5.ts
@@ -6,11 +6,14 @@
import type {
BearerIdentity,
+ ConnectPermissionRequest,
DelegateGrant,
DwnDataEncodedRecordsWriteMessage,
DwnMessagesPermissionScope,
+ DwnProtocolDefinition,
DwnRecordsPermissionScope,
HdIdentityVault,
+ Permission,
WalletConnectOptions,
Web5Agent,
} from '@web5/agent';
@@ -480,4 +483,14 @@ export class Web5 {
// we expect that any connected protocols will include MessagesQuery and MessagesRead grants that will allow it to sync
return [...connectedProtocols];
}
+
+ /**
+ * Creates a connect permissions request for specific protocols.
+ * If no permissions are explicitly provided, the default is all permissions ('read', 'write', 'delete', 'query', 'subscribe').
+ */
+ static requestPermissions(requests: { definition: DwnProtocolDefinition, permissions?: Permission[] }[]): ConnectPermissionRequest[] {
+ return requests.map(({ definition, permissions }) => WalletConnect.requestPermissionsForProtocol(definition, permissions ?? [
+ 'read', 'write', 'delete', 'query', 'subscribe'
+ ]));
+ }
}