@blockchain-lab-um/masca-connector
Version:
Library for using Masca on the frontend
151 lines (148 loc) • 4.72 kB
JavaScript
import { isError } from '@blockchain-lab-um/utils';
import { getAccountId, EthereumWebAuth } from '@didtools/pkh-ethereum';
import { DIDSession } from 'did-session';
import { getEthTypesFromInputDoc } from 'eip-712-types-generation';
// src/utils.ts
async function validateAndSetCeramicSession() {
const api = this.getMascaApi();
const enabledCredentialStoresResult = await api.getCredentialStore();
if (isError(enabledCredentialStoresResult)) {
throw new Error("Failed to get enabled VC stores.");
}
if (enabledCredentialStoresResult.data.ceramic === false) {
return;
}
const session = await api.validateStoredCeramicSession();
if (!isError(session)) {
return;
}
const provider = this.providerStore.getCurrentProvider()?.provider;
if (!provider) {
throw new Error("No provider found");
}
const addresses = await provider.request({
method: "eth_requestAccounts"
});
const accountId = await getAccountId(provider, addresses[0]);
const authMethod = await EthereumWebAuth.getAuthMethod(provider, accountId);
let newSession;
try {
newSession = await DIDSession.authorize(authMethod, {
expiresInSecs: 60 * 60 * 24 * 7,
resources: ["ceramic://*"]
});
} catch (e) {
throw new Error("User failed to sign session.");
}
const serializedSession = newSession.serialize();
const result = await api.setCeramicSession(serializedSession);
if (isError(result)) {
throw new Error("Failed to set session in Masca.");
}
}
async function signVerifiablePresentation(presentation) {
const provider = this.providerStore.getCurrentProvider()?.provider;
if (!provider)
throw new Error("No provider found");
const addresses = await provider.request({
method: "eth_requestAccounts"
});
if (!presentation.holder.includes(addresses[0]) && !presentation.holder.includes(
await this.viemClient.getEns({ address: addresses[0] })
)) {
throw new Error("Wrong holder");
}
const chainId = Number.parseInt(
await provider.request({ method: "eth_chainId" }),
16
);
presentation.proof = {
verificationMethod: `${presentation.holder}#controller`,
created: presentation.issuanceDate,
proofPurpose: "assertionMethod",
type: "EthereumEip712Signature2021"
};
const message = presentation;
const domain = {
chainId,
name: "VerifiablePresentation",
version: "1"
};
const primaryType = "VerifiablePresentation";
const types = getEthTypesFromInputDoc(presentation, primaryType);
const data = JSON.stringify({ domain, types, message, primaryType });
const signature = await provider.request({
method: "eth_signTypedData_v4",
params: [addresses[0], data]
});
presentation.proof.proofValue = signature;
presentation.proof.eip712 = {
domain,
types,
primaryType
};
return presentation;
}
async function signVerifiableCredential(credential, params) {
const provider = this.providerStore.getCurrentProvider()?.provider;
if (!provider)
throw new Error("No provider found");
const addresses = await provider.request({
method: "eth_requestAccounts"
});
let issuer = "";
if (typeof credential.issuer === "string") {
issuer = credential.issuer;
} else {
issuer = credential.issuer.id;
}
if (!issuer.includes(addresses[0]) && !issuer.includes(
await this.viemClient.getEns({ address: addresses[0] })
)) {
throw new Error("Invalid Issuer");
}
const chainId = Number.parseInt(
await provider.request({ method: "eth_chainId" }),
16
);
credential.proof = {
verificationMethod: `${issuer}#controller`,
created: credential.issuanceDate,
proofPurpose: "assertionMethod",
type: "EthereumEip712Signature2021"
};
const message = credential;
const domain = {
chainId,
name: "VerifiableCredential",
version: "1"
};
const primaryType = "VerifiableCredential";
const allTypes = getEthTypesFromInputDoc(credential, primaryType);
const types = { ...allTypes };
const data = JSON.stringify({ domain, types, message, primaryType });
const signature = await provider.request({
method: "eth_signTypedData_v4",
params: [addresses[0], data]
});
credential.proof.proofValue = signature;
credential.proof.eip712 = {
domain,
types: allTypes,
primaryType
};
if (params.options?.save) {
const api = this.getMascaApi();
const result = await api.saveCredential(
credential,
{
store: params.options.store
}
);
if (isError(result)) {
throw new Error("Failed to save VC in Masca.");
}
}
return credential;
}
export { signVerifiableCredential, signVerifiablePresentation, validateAndSetCeramicSession };