@elysium-onchain-id/identity-sdk
Version:
Interact with BlockChain Identities.
191 lines • 8.87 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Claim = void 0;
const utils_1 = require("ethers/lib/utils");
const OnchainID = __importStar(require("@onchain-id/solidity"));
const SignerModule_1 = require("../core/SignerModule");
const ethers_1 = require("ethers");
const Utils_1 = require("../core/utils/Utils");
const Errors_1 = require("../core/errors/Errors");
class Claim {
/**
* Generate the hash of a claim using the provided data, use this method when using a JSON scheme with public and private data.
* This hash should be put in the `data` field of the claim.
* @param topic
* @param emissionDate
* @param publicData
* @param privateData
*/
static generateHash(topic, emissionDate, publicData, privateData) {
if (publicData && privateData && emissionDate && topic) {
return (0, utils_1.sha256)((0, utils_1.toUtf8Bytes)(JSON.stringify({ topic, emissionDate, privateData, publicData })));
}
else {
throw new Error("Can't generate the Claim Hash because some data is missing.");
}
}
/**
* Generate the blockchain hash of the claim. This is the hash that has to be sign by the claim issuer.
* @param address
* @param topic
* @param data
*/
static generateBlockchainHash(address, topic, data) {
return (0, Utils_1.encodeAndHash)(['address', 'uint256', 'bytes'], [address, topic, data]);
}
static generateClaimID(issuer, topic) {
return (0, Utils_1.encodeAndHash)(['address', 'uint256'], [issuer, topic]);
}
/**
* Generate the blockchain hash of a claim and signs it with the provided signer or the default signer of the SDK.
* @param topic
* @param address
* @param data
* @param [signer]
* @returns Claim signature.
*/
static sign(topic, address, data, signer) {
return __awaiter(this, void 0, void 0, function* () {
if (!SignerModule_1.SignerModule.isSignerModule(signer)) {
throw new Errors_1.InvalidProviderError('A signer is required to generate a claim signature.');
}
if (!(0, Utils_1.isHexString)(data)) {
throw new Error('Claim data to sign must be a valid hex string.');
}
const claimHash = Claim.generateBlockchainHash(address, topic, data);
return signer.signMessage((0, utils_1.arrayify)(claimHash));
});
}
/**
* Verify the signature of a claim.
* The standard signature of a claim is the keccak256 hash of (identityAddress, topic, data) prefixed and signed.
* The data argument is exactly the content of the data claim field stored in blockchain (caution to hex padding).
* Data is expected to be an hexString.
* Using the IdentitySDK, call `IdentitySDK.utils.toHex('data')`.
* Using web3utils, call `web3utils.asciiToHex('data')`.
* Using ethersjs, call `Ethers.utils.hexlify(Ethers.utils.toUtf8Bytes('data'))`
* @param signingKey
* @param topic
* @param address Address of identity contract.
* @param data
* @param signature
*/
static verifySignature(signingKey, topic, address, data, signature) {
return __awaiter(this, void 0, void 0, function* () {
if (!(0, Utils_1.isHexString)(data)) {
throw new Error('Claim data to sign must be a valid hex string.');
}
const claimHash = Claim.generateBlockchainHash(address, topic, data);
try {
const signerAddress = yield (0, utils_1.verifyMessage)((0, utils_1.arrayify)(claimHash), signature);
return signerAddress === signingKey;
}
catch (err) {
return false;
}
});
}
/**
* Create a new Claim Object from a ClaimData (got from BlockChain Identity Contract).
* Use #.createFromURI() to fetch from an URI.
* @param claim
*/
constructor(claim) {
if (claim) {
Object.assign(this, claim);
}
}
/**
* Generate the hash of the claim data if it was populated with private data.
* If all data are not provided as arguments, data fromm the Claim object will be used.
* Note that to verify a claim complete data, you will need to have access to its private data.
* Use the .populate() method to fetch all the public and private data if available.
* @param topic
* @param emissionDate
* @param publicData
* @param privateData
*/
generateHash(topic, emissionDate, publicData, privateData) {
if (publicData && privateData && emissionDate && topic) {
return Claim.generateHash(topic, emissionDate, publicData, privateData);
}
else {
if (!this.publicData || !this.privateData || !this.emissionDate) {
throw new Error("Can't generate the Claim Hash because some data is missing. Call .populate() first to retrieve data from the Claim Issuer.");
}
return this.generateHash(this.topic, this.emissionDate, this.publicData, this.privateData);
}
}
/**
* Sign the claim.
* It will update the signature property of the claim. The signature can only be generated for a claim that as a topic, an address and data.
* @param signer Signer module to use. If null, use default signer of SDK.
*/
sign(signer) {
return __awaiter(this, void 0, void 0, function* () {
if (!this.topic) {
throw new Error('Claim has no topic defined, thus it cannot be signed.');
}
if (!this.address) {
throw new Error('Claim has no address defined, thus it cannot be signed.');
}
if (!this.data) {
throw new Error('Claim has no data defined, thus it cannot be signed.');
}
const signature = yield Claim.sign(this.topic, this.address, this.data, signer);
this.signature = signature;
return signature;
});
}
/**
* Verify the validity of a claim against the Claim Issuer Contract.
* @param provider Provider instance to fetch blockchain data.
* @return true if the claim is declared valid by the Claim Issuer, false otherwise.
*/
verifyValidity(provider) {
return __awaiter(this, void 0, void 0, function* () {
if (!this.topic || !this.address || !this.signature) {
throw new Error(`Claim is not complete and thus cannot be verified.`);
}
if (!this.issuer) {
throw new Error('A claim that has no issuer address cannot be verified.');
}
const claimIssuerInstance = new ethers_1.Contract(this.issuer, OnchainID.interfaces.IClaimIssuer.abi, provider);
return claimIssuerInstance.isClaimValid(this.address, this.topic, this.signature, this.data);
});
}
}
exports.Claim = Claim;
//# sourceMappingURL=Claim.js.map