credo-near-module
Version:
NEAR Module for Credo SSI Agent
384 lines (361 loc) • 10.2 kB
text/typescript
// import { DidStdFee, VerificationMethods } from "@cheqd/sdk";
import {NearLedgerService } from "../ledger";
import {
AgentContext,
DidCommV1Service,
DidCreateOptions,
DidCreateResult,
DidDeactivateOptions,
DidDocument,
DidDocumentRole,
DidDocumentService,
DidOperationStateActionBase,
DidRecord,
DidRegistrar,
DidRepository,
DidUpdateOptions,
DidUpdateResult,
injectable,
} from "@credo-ts/core";
import { uuid } from "@credo-ts/core/build/utils/uuid";
// import { id } from "ethers";
()
export class NearDIDRegistrar implements DidRegistrar {
public readonly supportedMethods = ["near"];
constructor(private ledgerService: NearLedgerService) {}
async create(
agentContext: AgentContext,
options: EthereumDidCreateOptions
): Promise<DidCreateResult<DidOperationStateActionBase>> {
const didRepository = agentContext.dependencyManager.resolve(DidRepository);
const etheriumLedgerService = agentContext.dependencyManager.resolve(
NearLedgerService
);
let didDocument: DidDocument;
const _didDocument = options.options?.didDocument;
console.log(options);
if (!options.network) {
throw new Error("Network is required");
}
try {
let didStr = "";
if (_didDocument) {
didDocument = _didDocument;
const kanonId = _didDocument.id;
} else {
didDocument = new DidDocument({
id: options.did,
context: "https://www.w3.org/ns/did/v1",
});
}
if (options.did) {
didStr = options.did;
} else {
didStr = `did:near:${options.network}:${uuid()}`;
}
const didDocumentjson = JSON.stringify(didDocument);
console.log(didDocumentjson, didStr);
await etheriumLedgerService.executeDIDOperation(
"create",
didStr,
"testnet",
didDocumentjson
);
console.log(didStr);
didDocument.id = options.did || didStr;
const didRecord = new DidRecord({
did: didStr,
role: DidDocumentRole.Created,
didDocument: didDocument,
tags: {
network: options.network,
role: DidDocumentRole.Created,
method: "kanon",
},
});
console.log(didRecord);
await didRepository.save(agentContext, didRecord);
return {
didDocumentMetadata: {},
didRegistrationMetadata: {},
didState: {
state: "finished",
did: didDocument.id,
didDocument,
secret: options.secret,
},
};
} catch (e: any) {
console.log(e);
return {
didDocumentMetadata: {},
didRegistrationMetadata: {},
didState: {
state: "failed",
reason: e.message,
},
};
}
}
public async createResource(
agentContext: AgentContext,
did: string,
options: KanonCreateResourceOptions
) {
const etheriumLedgerService = agentContext.dependencyManager.resolve(
NearLedgerService
);
const didRepository = agentContext.dependencyManager.resolve(DidRepository);
try {
const didRecord = await didRepository.findCreatedDid(agentContext, did);
console.log(JSON.stringify(options), "options");
// const { didDocument, didDocumentMetadata } =
// await etheriumLedgerService.getDID(did);
// if (!didDocument) {
// throw new Error("DID not found");
// }
const response = await etheriumLedgerService.registerSchema(
did,
JSON.stringify(options)
);
console.log(response, "response");
return {
resource: {
id: options.id,
name: options.name,
version: options.version,
resourceType: options.resourceType,
alsoKnownAs: options.alsoKnownAs,
data: options.data,
},
resourceMetadata: {
},
resourceState: {
state: "finished",
resource: response,
},
};
} catch (e: any) {
console.log(e);
return {
didDocumentMetadata: {},
didRegistrationMetadata: {},
didState: {
state: "failed",
reason: e.message,
},
};
}
}
async createCredentialDefinition(
agentContext: AgentContext,
did: string,
options: any
): Promise<any> {
const etheriumLedgerService = agentContext.dependencyManager.resolve(
NearLedgerService
);
const didRepository = agentContext.dependencyManager.resolve(DidRepository);
try {
const didRecord = await didRepository.findCreatedDid(
agentContext,
options.did
);
console.log(did, options.did, "did");
const response = await etheriumLedgerService.registerCredentialDefinition(
did,
options.did,
JSON.stringify(options)
);
return {
credentialDefinition: response,
credentialDefinitionMetadata: {},
credentialDefinitionState: {
state: "finished",
credentialDefinition: response,
},
};
} catch (e: any) {
console.log(e);
return {
credentialDefinitionMetadata: {},
credentialDefinitionState: {
state: "failed",
reason: e.message,
},
};
}
}
async update(
agentContext: AgentContext,
options: EthereumDidUpdateOptions
): Promise<DidUpdateResult> {
const didRepository = agentContext.dependencyManager.resolve(DidRepository);
const etheriumLedgerService = agentContext.dependencyManager.resolve(
NearLedgerService
);
let didDocument: DidDocument;
const versionId = options.options?.versionId;
try {
if (options.didDocument) {
didDocument = options.didDocument;
const kanonId = options.didDocument.id;
} else {
didDocument = new DidDocument({
id: options.id || options.did,
context: "https://www.w3.org/ns/did/v1",
});
}
const didDocumentjson = JSON.stringify(didDocument);
const response = await etheriumLedgerService.executeDIDOperation(
"update",
didDocument.id,
"testnet",
didDocumentjson
);
if(!response) {
throw new Error("DID not found");
}
const did = response[0].id;
didDocument.id = did;
const didRecord = new DidRecord({
did: didDocument.id,
role: DidDocumentRole.Created,
didDocument: didDocument,
});
await didRepository.save(agentContext, didRecord);
return {
didDocumentMetadata: {},
didRegistrationMetadata: {},
didState: {
state: "finished",
did: didDocument.id,
didDocument,
secret: options.secret,
},
};
} catch (e: any) {
console.log(e);
return {
didDocumentMetadata: {},
didRegistrationMetadata: {},
didState: {
state: "failed",
reason: e.message,
},
};
}
}
async deactivate(
agentContext: AgentContext,
options: EthereumDidDeactivateOptions
): Promise<DidUpdateResult> {
throw new Error("Method not implemented.");
}
}
export interface EthereumDidCreateOptions extends DidCreateOptions {
method: "near";
did: string;
network: string;
id: string;
options: {
versionId?: string;
didDocument: DidDocument;
};
}
export interface EthereumDidUpdateOptions extends DidUpdateOptions {
did: string;
didDocument: DidDocument;
network: string;
id: string;
options: {
versionId?: string;
};
}
export interface EthereumDidDeactivateOptions extends DidDeactivateOptions {
method: "kanon";
did: string;
network: string;
options: {
versionId?: string;
};
}
// interface IVerificationMethod {
// type: `${VerificationMethods}`;
// id: TVerificationKey<string, number>;
// privateKey?: Buffer;
// }
export type TVerificationKeyPrefix = string;
export type TVerificationKey<
K extends TVerificationKeyPrefix,
N extends number
> = `${K}-${N}`;
// did:canon:<network>:<address>:<version>:
export interface KanonCreateResourceOptions
extends Omit<Partial<MsgCreateResourcePayload>, "data"> {
data: string | Uint8Array | object;
}
export interface MsgCreateResourcePayload {
/** data is a byte-representation of the actual Data the user wants to store. */
data: Uint8Array;
/**
* collection_id is an identifier of the DidDocument the resource belongs to.
* Format: <unique-identifier>
*
* Examples:
* - c82f2b02-bdab-4dd7-b833-3e143745d612
* - wGHEXrZvJxR8vw5P3UWH1j
*/
collectionId: string;
/**
* id is a unique id of the resource.
* Format: <uuid>
*/
id: string;
/**
* name is a human-readable name of the resource.
* Format: <string>
*
* Does not change between different versions.
* Example: PassportSchema, EducationTrustRegistry
*/
name: string;
/**
* version is a version of the resource.
* Format: <string>
* Stored as a string. OPTIONAL.
*
* Example: 1.0.0, v2.1.0
*/
version: string;
/**
* resource_type is a type of the resource.
* Format: <string>
*
* This is NOT the same as the resource's media type.
* Example: AnonCredsSchema, StatusList2021
*/
resourceType: string;
/** also_known_as is a list of URIs that can be used to get the resource. */
alsoKnownAs: AlternativeUri[];
}
export interface AlternativeUri {
/**
* uri is the URI of the Resource.
* Examples:
* - did:cheqd:testnet:MjYxNzYKMjYxNzYK/resources/4600ea35-8916-4ac4-b412-55b8f49dd94e
* - https://resolver..cheqd.net/1.0/identifiers/did:cheqd:testnet:MjYxNzYKMjYxNzYK/resources/4600ea35-8916-4ac4-b412-55b8f49dd94e
* - https://example.com/example.json
* - https://gateway.ipfs.io/ipfs/bafybeihetj2ng3d74k7t754atv2s5dk76pcqtvxls6dntef3xa6rax25xe
* - ipfs://bafybeihetj2ng3d74k7t754atv2s5dk76pcqtvxls6dntef3xa6rax25xe
*/
uri: string;
/**
* description is a human-readable description of the URI. Defined client-side.
* Examples:
* - did-uri
* - http-uri
* - ipfs-uri
*/
description: string;
}