Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Resolver to support MultiApi modules #466

Merged
merged 17 commits into from
Oct 31, 2024
8 changes: 5 additions & 3 deletions examples/bbs-dock.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { initializeWasm } from '@docknetwork/credential-sdk/crypto';
import { DIDResolver } from '@docknetwork/credential-sdk/resolver';
import { Resolver } from '@docknetwork/credential-sdk/resolver';
import Bls12381G2KeyPairDock2022 from '@docknetwork/credential-sdk/vc/crypto/Bls12381G2KeyPairDock2022';
import {
issueCredential,
Expand All @@ -15,8 +15,10 @@ const keypairOpts = {
'przwNdX6Bn5TzwmX56fYKQr6vk5U2DsfJJHZJQzr1Sxd9oJUg1rEEoUP7Bz33WNpykvkkqoTByMwnceCx9yvTW8CG1V5XpSwHPSN222cwMe9xr4mViyLWkKtoraybEPeLHT',
};

class ExampleDIDResolver extends DIDResolver {
static METHOD = 'example';
class ExampleDIDResolver extends Resolver {
prefix = 'did';

method = 'example';

constructor() {
super(void 0);
Expand Down
20 changes: 12 additions & 8 deletions examples/resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import {
DidKey,
DIDDocument,
} from '@docknetwork/credential-sdk/types';
import { parseDIDUrl } from '@docknetwork/credential-sdk/utils';
import { NoDIDError } from '@docknetwork/credential-sdk/modules/abstract/did';
import {
DIDResolver,
DIDKeyResolver,
UniversalResolver,
WILDCARD,
DockDIDResolver,
DIDResolver,
ResolverRouter,
Resolver,
} from '@docknetwork/credential-sdk/resolver';
import { DockDIDModule } from '@docknetwork/dock-blockchain-modules';

Expand All @@ -39,16 +41,18 @@ const dock = new DockAPI();
const didModule = new DockDIDModule(dock);

// Custom ethereum resolver class
class EtherResolver extends DIDResolver {
static METHOD = 'ethr';
class EtherResolver extends Resolver {
prefix = 'did';

method = 'ethr';

constructor(config) {
super();
this.ethres = ethr.getResolver(config).ethr;
}

async resolve(did) {
const parsed = this.parseDid(did);
const parsed = parseDIDUrl(did);
try {
return this.ethres(did, parsed);
} catch (e) {
Expand Down Expand Up @@ -86,12 +90,12 @@ async function main() {

const resolvers = [
new DIDKeyResolver(), // did:key resolver
new DockDIDResolver(didModule), // Prebuilt resolver
new DIDResolver(didModule), // Prebuilt resolver
new EtherResolver(ethereumProviderConfig), // Custom resolver
];

class AnyDIDResolver extends DIDResolver {
static METHOD = WILDCARD;
class AnyDIDResolver extends ResolverRouter {
method = WILDCARD;
}

const resolver = new AnyDIDResolver([
Expand Down
8 changes: 4 additions & 4 deletions examples/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import {

import {
UniversalResolver,
DockResolver,
WildcardMultiResolver,
CoreResolver,
WildcardResolverRouter,
} from '@docknetwork/credential-sdk/resolver';

const dock = new DockAPI();
Expand Down Expand Up @@ -103,8 +103,8 @@ async function main() {
console.log('Result from chain:', result);

const universalResolverUrl = 'https://uniresolver.io';
const resolver = new WildcardMultiResolver([
new DockResolver(modules),
const resolver = new WildcardResolverRouter([
new CoreResolver(modules),
new UniversalResolver(universalResolverUrl),
]);

Expand Down
11 changes: 10 additions & 1 deletion packages/cheqd-blockchain-api/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
} from '@docknetwork/credential-sdk/utils';
import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing';
import {
DIDModule, ResourceModule, createCheqdSDK, CheqdNetwork,
DIDModule,
ResourceModule,
createCheqdSDK,
CheqdNetwork,
} from '@cheqd/sdk';
import {
MsgCreateDidDocPayload,
Expand Down Expand Up @@ -167,6 +170,10 @@ export class CheqdAPI extends ApiProvider {
return res;
}

methods() {
return ['cheqd'];
}

supportsIdentifier(id) {
this.ensureInitialized();

Expand All @@ -182,6 +189,8 @@ export class CheqdAPI extends ApiProvider {
return this.supportsIdentifier(id[0]);
} else if (id instanceof TypedEnum) {
return this.supportsIdentifier(this.value);
} else if (id.Qualifier?.contains('cheqd:')) {
return true;
}

return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ class CheqdApiProvider extends ApiProvider {
return this.cheqd.fees;
}

methods() {
return this.cheqd.methods();
}

isInitialized() {
return this.cheqd.isInitialized();
}
Expand Down
6 changes: 5 additions & 1 deletion packages/cheqd-blockchain-modules/src/common/inject-cheqd.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { withExtendedStaticProperties } from '@docknetwork/credential-sdk/utils/inheritance';
import CheqdAPIProvider from './cheqd-api-provider';

export default function injectDock(klass) {
export default function injectCheqd(klass) {
const name = `withCheqd(${klass.name})`;

const obj = {
Expand All @@ -22,6 +22,10 @@ export default function injectDock(klass) {
supportsIdentifier(id) {
return this.apiProvider.supportsIdentifier(id);
}

methods() {
return this.apiProvider.methods();
}
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import { withExtendedPrototypeProperties } from '../../../utils';

class ApiProvider {
/**
* Returns array of the methods supported by the given API.
* @returns {Array<string>}
*/
methods() {
throw new Error('Unimplemented');
}

/**
* Returns `true` is the API was initialized.
* @returns {boolean}
*/
isInitialized() {
Expand Down Expand Up @@ -39,6 +48,6 @@ class ApiProvider {
* Base class that must be extended by all API providers.
*/
export default withExtendedPrototypeProperties(
['isInitialized', 'stateChangeBytes', 'signAndSend'],
['methods', 'isInitialized', 'stateChangeBytes', 'signAndSend'],
ApiProvider,
);
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/**
* Base module class that must be extended by all modules.
*/
export default class AbstractBaseModule {
import { withExtendedPrototypeProperties } from '../../../utils';

class AbstractBaseModule {
/**
* Signs and sends provided extrinsic.
*
Expand All @@ -19,3 +18,8 @@ export default class AbstractBaseModule {
return await this.apiProvider.signAndSend(extrinsic, params);
}
}

/**
* Base module class that must be extended by all modules.
*/
export default withExtendedPrototypeProperties(['methods'], AbstractBaseModule);
5 changes: 4 additions & 1 deletion packages/credential-sdk/src/modules/abstract/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ export const AbstractCoreModules = withExtendedStaticProperties(
AttestModule: { key: 'attest', optional: false },
BlobModule: { key: 'blob', optional: false },
DIDModule: { key: 'did', optional: false },
OffchainSignaturesModule: { key: 'offchainSignatures', optional: false },
OffchainSignaturesModule: {
key: 'offchainSignatures',
optional: false,
},
BBSModule: { key: 'bbs', optional: false },
BBSPlusModule: { key: 'bbsPlus', optional: false },
PSModule: { key: 'ps', optional: false },
Expand Down
4 changes: 4 additions & 0 deletions packages/credential-sdk/src/modules/multi-api/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export function injectModuleRouter(klass) {
dispatchById(id, fn) {
return fn(this.moduleById(id));
}

methods() {
return this.modules.flatMap((module) => module.methods());
}
},
};

Expand Down
25 changes: 25 additions & 0 deletions packages/credential-sdk/src/modules/tests/blob-module.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { DidKeypair, Ed25519Keypair } from '../../keypairs';
import { NoBlobError } from '../abstract/blob/errors';
import { DIDDocument } from '../../types';
import { itIf } from './common';
import { BlobResolver } from '../../resolver/blob';
import { stringToU8a } from '../../utils';

// eslint-disable-next-line jest/no-export
export default function generateBlobModuleTests(
Expand Down Expand Up @@ -56,5 +58,28 @@ export default function generateBlobModuleTests(
new NoBlobError(id),
);
});

test('`BlobResolver`', async () => {
const resolver = new BlobResolver(blobModule);
const did = DID.random();

const keyPair = Ed25519Keypair.random();
const didKeypair = new DidKeypair([did, 1], keyPair);

const document = DIDDocument.create(did, [didKeypair.didKey()]);

await didModule.createDocument(document, didKeypair);

const blob1 = {
id: BlobId.random(did),
blob: 'abcdef',
};

await blobModule.new(blob1, didKeypair);
expect(await resolver.resolve(String(blob1.id))).toEqual([
String(did),
stringToU8a(blob1.blob),
]);
});
});
}
15 changes: 15 additions & 0 deletions packages/credential-sdk/src/modules/tests/did-module.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DidKeypair, Ed25519Keypair } from '../../keypairs';
import { DIDResolver } from '../../resolver';
import {
DIDDocument,
BBSPublicKeyValue,
Expand Down Expand Up @@ -229,5 +230,19 @@ export default function generateDIDModuleTests(
new NoDIDError(did),
);
});

test('`DIDResolver`', async () => {
const resolver = new DIDResolver(module);
const did = DID.random();

const keyPair = Ed25519Keypair.random();
const didKeypair = new DidKeypair([did, 1], keyPair);

const document = DIDDocument.create(did, [didKeypair.didKey()]);

await module.createDocument(document, didKeypair);

expect(await resolver.resolve(String(did))).toEqual(document.toJSON());
});
});
}
39 changes: 33 additions & 6 deletions packages/credential-sdk/src/resolver/blob/blob-resolver.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,36 @@
import { MultiResolver } from '../generic';
import { ensureInstanceOf } from '../../utils';
import { AbstractBlobModule } from '../../modules/abstract/blob';
import { Resolver } from '../generic';

class DockBlobResolver extends Resolver {
prefix = 'blob';

get method() {
return this.blobModule.methods();
}

/**
* @param {AbstractBlobModule}
* @constructor
*/
constructor(blobModule) {
super();

/**
* @type {AbstractBlobModule}
*/
this.blobModule = ensureInstanceOf(blobModule, AbstractBlobModule);
}

async resolve(blobUri) {
const [author, blob] = await this.blobModule.get(blobUri);

return [String(author), blob.toObjectOrBytes()];
}
}

/**
* Resolves `Blob` with the identifier `blob:*`.
* @abstract
* Resolves `Blob`s with identifier `blob:dock:*`.
* @type {DockBlobResolver}
*/
export default class BlobResolver extends MultiResolver {
static PREFIX = 'blob';
}
export default DockBlobResolver;
32 changes: 0 additions & 32 deletions packages/credential-sdk/src/resolver/blob/dock-blob-resolver.js

This file was deleted.

1 change: 0 additions & 1 deletion packages/credential-sdk/src/resolver/blob/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export { default as BlobResolver } from './blob-resolver';
export { default as DockBlobResolver } from './dock-blob-resolver';
21 changes: 21 additions & 0 deletions packages/credential-sdk/src/resolver/core-resolver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { DIDResolver } from './did';
import { StatusList2021Resolver } from './status-list2021';
import { ResolverRouter } from './generic';
import { BlobResolver } from './blob';
import { ensureInstanceOf } from '../utils';
import { AbstractCoreModules } from '../modules';

/**
* Resolves dock-hosted entities such us `did:dock:*` and `status-list2021:dock:*`, `rev-reg:dock:*`, `blob:dock:*`.
*/
export default class CoreResolver extends ResolverRouter {
constructor(modules) {
ensureInstanceOf(modules, AbstractCoreModules);

super([
new DIDResolver(modules.did),
new StatusList2021Resolver(modules.statusListCredential),
new BlobResolver(modules.blob),
]);
}
}
Loading
Loading