UNPKG

@elysium-onchain-id/identity-sdk

Version:
699 lines 35.8 kB
"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.Identity = exports.NonExistingClaimError = exports.InvalidClaimError = exports.InvalidKeyError = exports.KeyPurposeNotRegisteredError = exports.KeyPurposeAlreadyRegisteredError = void 0; const ethers_1 = require("ethers"); const providers_1 = require("@ethersproject/providers"); const utils_1 = require("ethers/lib/utils"); const OnchainID = __importStar(require("@onchain-id/solidity")); const Key_interface_1 = require("./Key.interface"); const ENS_1 = require("../core/utils/ENS"); const Claim_1 = require("../claim/Claim"); const Utils_1 = require("../core/utils/Utils"); const Errors_1 = require("../core/errors/Errors"); class KeyPurposeAlreadyRegisteredError extends Error { constructor({ message = 'Key already has purpose on identity contract.' } = {}) { super(message); this.name = 'KeyPurposeAlreadyRegisteredError'; Object.setPrototypeOf(this, KeyPurposeAlreadyRegisteredError.prototype); } } exports.KeyPurposeAlreadyRegisteredError = KeyPurposeAlreadyRegisteredError; class KeyPurposeNotRegisteredError extends Error { constructor({ message = 'Key does not have the purpose on identity contract.' } = {}) { super(message); this.name = 'KeyPurposeNotRegisteredError'; Object.setPrototypeOf(this, KeyPurposeNotRegisteredError.prototype); } } exports.KeyPurposeNotRegisteredError = KeyPurposeNotRegisteredError; class InvalidKeyError extends Error { constructor({ message = 'Definition of the Key is not valid.' } = {}) { super(message); this.name = 'InvalidKeyError'; Object.setPrototypeOf(this, InvalidKeyError.prototype); } } exports.InvalidKeyError = InvalidKeyError; class InvalidClaimError extends Error { constructor({ message = 'Definition of the Claim is not valid.' } = {}) { super(message); this.name = 'InvalidClaimError'; Object.setPrototypeOf(this, InvalidClaimError.prototype); } } exports.InvalidClaimError = InvalidClaimError; class NonExistingClaimError extends Error { constructor({ message = 'There is no such claim.' } = {}) { super(message); this.name = 'NonExistingClaimError'; Object.setPrototypeOf(this, NonExistingClaimError.prototype); } } exports.NonExistingClaimError = NonExistingClaimError; class Identity { /** * Instantiate a new Identity with the provided address or ENS string that will be resolved. * @param addressOrENS Must be a valid Ethereum address, checksumed, all lower-case or all uppercase. * @param options * @params options.provider If provided, the identity will use this provider for all blockchain operation (unless override) instead of the SDK default provider. */ static at(addressOrENS, options) { return __awaiter(this, void 0, void 0, function* () { let address; if (!addressOrENS.includes('.')) { address = (0, ENS_1.normalizeAddress)(addressOrENS); } else { if (providers_1.Provider.isProvider(options === null || options === void 0 ? void 0 : options.provider)) { address = yield (0, ENS_1.resolveENS)(addressOrENS, options === null || options === void 0 ? void 0 : options.provider); } else if (ethers_1.Signer.isSigner(options === null || options === void 0 ? void 0 : options.signer) && providers_1.Provider.isProvider(options === null || options === void 0 ? void 0 : options.signer.provider)) { address = yield (0, ENS_1.resolveENS)(addressOrENS, options === null || options === void 0 ? void 0 : options.signer.provider); } else { throw new Errors_1.InvalidProviderError('Resolving ENS requires a Provider.'); } } return new Identity(address, (options === null || options === void 0 ? void 0 : options.signer) || (options === null || options === void 0 ? void 0 : options.provider)); }); } /** * Compute the address an ONCHAINID deployed using a Factory/Gateway would have. * @param factory The address of the factory contract (this is not the address of the Gateway contract) * @param unprefixedSalt The salt specified when requesting the deployment, usually the address of the identity owner. * @param implementationAuthority The address of the implementation authority contract used by the Factory. */ static computeDeploymentAddress({ factory, unprefixedSalt, implementationAuthority }) { return (0, utils_1.getCreate2Address)(factory, (0, utils_1.keccak256)((0, utils_1.toUtf8Bytes)('OID' + unprefixedSalt)), (0, utils_1.keccak256)((0, utils_1.concat)([ OnchainID.contracts.IdentityProxy.bytecode, utils_1.defaultAbiCoder.encode(['address', 'address'], [implementationAuthority, factory]), ]))); } /** * Deploy a new Identity, and return the Identity object. * The signer will pay for the deployment, and will be added in the MANAGEMENT keys. * If not given, the Signer will use the default provider from the SDK if it is defined and is a Signer. * Note that the identity will be returned with the provided Signer, thus management operation can be chained. * @param config - Configuration of the identity to deploy. * @param config.managementKey - Ethereum address to set as the initial management key. * @param config.implementationAuthority - Ethereum address of the implementation authority to use. * @param options * @example Usually called with `identity.deployed()`: * ```typescript * const identity = await Identity.deployNew(); * await identity.deployed(); * ``` */ static deployNew(config, options) { var _a; return __awaiter(this, void 0, void 0, function* () { if (!ethers_1.Signer.isSigner(options.signer)) { throw new Errors_1.InvalidProviderError('Contract deployment requires a Signer.'); } if (!(0, utils_1.isHexString)(config.managementKey)) { throw new InvalidKeyError(); } const contract = yield new ethers_1.ContractFactory(OnchainID.contracts.IdentityProxy.abi, OnchainID.contracts.IdentityProxy.bytecode, options === null || options === void 0 ? void 0 : options.signer).deploy(config.implementationAuthority, config.managementKey, (_a = options === null || options === void 0 ? void 0 : options.overrides) !== null && _a !== void 0 ? _a : {}); const identity = new Identity(contract.address, options === null || options === void 0 ? void 0 : options.signer); identity.deploymentContract = contract; return identity; }); } /** * Deploy a new Identity for a given wallet and a specific salt, and return the Identity object, using an ONCHAINID * Gateway. To deploy an identity using this method, the gatewa requires a signature from an approved signer that * contains the salt and the address of the identity owner (see specifications). * The signer will pay for the deployment. * If not given, the Signer will use the default provider from the SDK if it is defined and is a Signer. * Note that the identity will be returned with the provided Signer, thus management operation can be chained. * @param config - Configuration of the identity to deploy. * @param config.gateway - address of the gateway to use * @param config.identityOwner - address of the identity owner * @param config.salt - address of the factory to deploy a proxy identity. * @param config.signature - signature of salt + identityOwner + expiry (see specifications) * @param config.signatureExpiry - the block timestamp where the signature will expire (in seconds and as a BigNumber) * @param options * @param options.signer - the signer to use to sign and send the transaction * @example Usually called with `identity.deployed()`: * ```typescript * const identity = await Identity.deployUsingGatewayWithSalt({ * gateway: '0x...', * identityOwner: '0x..', * salt: 'some-salt', * signature: '0x...', * signatureExpiry: BigNumber.from('1689583125'), * }); * await identity.deployed(); * ``` */ static deployUsingGatewayWithSalt(config, options) { return __awaiter(this, void 0, void 0, function* () { if (!ethers_1.Signer.isSigner(options.signer)) { throw new Errors_1.InvalidProviderError('Contract deployment requires a Signer.'); } if (!(0, utils_1.isAddress)(config.gateway) || !(0, utils_1.isAddress)(config.identityOwner) || !config.salt || !(0, utils_1.isHexString)(config.signature)) { throw new Error('Invalid parameters : gateway and identity owner must be addresses, salt and signature must be hex strings, signatureExpiry must be BigNumber'); } const gatewayContract = new ethers_1.Contract(config.gateway, OnchainID.contracts.Gateway.abi, options.signer); return gatewayContract.deployIdentityWithSalt(config.identityOwner, config.salt, config.signatureExpiry, config.signature); }); } /** * Deploy a new Identity for a given wallet and a specific salt, and return the Identity object, using an ONCHAINID * Gateway. To deploy an identity using this method, the gateway requires a signature from an approved signer that * contains the salt and the address of the identity owner and the list of management keys (see specifications). * The signer will pay for the deployment. * If not given, the Signer will use the default provider from the SDK if it is defined and is a Signer. * Note that the identity will be returned with the provided Signer, thus management operation can be chained. * @param config - Configuration of the identity to deploy. * @param config.gateway - address of the gateway to use * @param config.identityOwner - address of the identity owner * @param config.salt - address of the factory to deploy a proxy identity. * @param config.managementKeys - list of management keys to add to the identity * @param config.signature - signature of salt + identityOwner + expiry (see specifications) * @param config.signatureExpiry - the block timestamp where the signature will expire (in seconds and as a BigNumber) * @param options * @param options.signer - the signer to use to sign and send the transaction * @example Usually called with `identity.deployed()`: * ```typescript * const identity = await Identity.deployUsingGatewayWithSalt({ * gateway: '0x...', * identityOwner: '0x..', * salt: 'some-salt', * managementKeys: [IdentitySDK.utils.encodeAndHash(['address'], ['0x...'])], * signature: '0x...', * signatureExpiry: BigNumber.from('1689583125'), * }); * await identity.deployed(); * ``` */ static deployUsingGatewayWithSaltAndManagementKeys(config, options) { if (!ethers_1.Signer.isSigner(options.signer)) { throw new Errors_1.InvalidProviderError('Contract deployment requires a Signer.'); } if (!(0, utils_1.isAddress)(config.gateway) || !(0, utils_1.isAddress)(config.identityOwner) || !config.salt || !(0, utils_1.isHexString)(config.signature) || !config.managementKeys || config.managementKeys.length === 0) { throw new Error('Invalid parameters : gateway and identity owner must be addresses, salt and signature must be hex strings, signatureExpiry must be BigNumber, managementKeys must be an array of hashed managements keys.'); } const gatewayContract = new ethers_1.Contract(config.gateway, OnchainID.contracts.Gateway.abi, options.signer); return gatewayContract.deployIdentityWithSaltAndManagementKeys(config.identityOwner, config.salt, config.managementKeys, config.signatureExpiry, config.signature); } /** * Deploy a new Identity, and return the Identity object, using an ONCHAINID Gateway. This method only deploys * an identity for the wallet that signed the transaction. * The signer will pay for the deployment. * If not given, the Signer will use the default provider from the SDK if it is defined and is a Signer. * Note that the identity will be returned with the provided Signer, thus management operation can be chained. * @param config - Configuration of the identity to deploy. * @param config.gateway - address of the gateway to use * @param config.identityOwner - address of the identity owner, must be the address of the signer * @param options * @param options.signer - the signer to use to sign and send the transaction * @example Usually called with `identity.deployed()`: * ```typescript * const identity = await Identity.deployUsingGatewayWithSalt({ * gateway: '0x...', * identityOwner: '0x..', * }); * await identity.deployed(); * ``` */ static deployUsingGatewayForWallet(config, options) { return __awaiter(this, void 0, void 0, function* () { if (!ethers_1.Signer.isSigner(options.signer)) { throw new Errors_1.InvalidProviderError('Contract deployment requires a Signer.'); } const gatewayContract = new ethers_1.Contract(config.gateway, OnchainID.contracts.Gateway.abi, options.signer); return gatewayContract.deployIdentityForWallet(config.identityOwner); }); } /** * Instantiate an Identity. * @param address A valid Ethereum address (not an ENS, use `Identity#at(ens)`.). * @param provider Override the default provider of SDK, and use for all operation of this Identity. */ constructor(address, provider) { this.address = (0, ENS_1.normalizeAddress)(address); this.claimHolderInstance = undefined; this.keyHolderInstance = undefined; this.provider = provider; } /** * Add a claim to an Identity. * The signature must have been signed with a keypair having the public key in the CLAIM keys of Identity. * @param topic * @param scheme * @param issuer * @param signature * @param data * @param uri * @param [options] */ addClaim(topic, scheme, issuer, signature, data, uri, options) { var _a; return __awaiter(this, void 0, void 0, function* () { const _signer = (options === null || options === void 0 ? void 0 : options.signer) || this.provider; if (!ethers_1.Signer.isSigner(_signer)) { throw new Errors_1.InvalidProviderError('Contract operations require a Signer.'); } if (!(0, utils_1.isHexString)(signature)) { throw new InvalidClaimError({ message: 'signature must be a valid hex string.' }); } const signatureBytes = (0, utils_1.arrayify)(signature); if (data.length > 0 && !(0, utils_1.isHexString)(data)) { throw new InvalidClaimError({ message: 'data must be a valid hex string.' }); } const dataBytes = (0, utils_1.arrayify)(data.length > 0 ? data : '0x'); let instance = this.claimHolderInstance; if (!instance || (options === null || options === void 0 ? void 0 : options.signer)) { instance = yield this.instantiateClaimHolder(_signer); } if (!(yield this.keyHasPurpose((0, Utils_1.encodeAndHash)(['address'], [yield _signer.getAddress()]), Key_interface_1.KeyPurpose.CLAIM, options))) { throw new Errors_1.OperationForbiddenError({ message: 'CLAIM key required on the identity to add a claim.' }); } return instance.addClaim(topic, scheme, issuer, signatureBytes, dataBytes, uri, (_a = options === null || options === void 0 ? void 0 : options.overrides) !== null && _a !== void 0 ? _a : {}); }); } /** * Add a Key to an Identity. * The Signer must have a MANAGEMENT key in the Identity. * @param key Must be a valid byte32 hex string (pass the keccak256 hash of the key string encoded (abi.encode)). * @param purpose Must be an integer. It is recommended to use the standard KeyPurpose enum. * @param type Must be a an integer. It is recommended to use the standard KeyType enum. * @param [options] */ addKey(key, purpose, type, options) { var _a; return __awaiter(this, void 0, void 0, function* () { const _signer = (options === null || options === void 0 ? void 0 : options.signer) || this.provider; if (!ethers_1.Signer.isSigner(_signer)) { throw new Errors_1.InvalidProviderError('Contract operations require a Signer.'); } let instance = this.keyHolderInstance; if (!instance || (options === null || options === void 0 ? void 0 : options.signer)) { instance = yield this.instantiateKeyHolder(_signer); } if (!(yield this.keyHasPurpose((0, Utils_1.encodeAndHash)(['address'], [yield _signer.getAddress()]), Key_interface_1.KeyPurpose.MANAGEMENT, options))) { throw new Errors_1.OperationForbiddenError({ message: 'MANAGEMENT key required on the identity to add a key.' }); } if (!(0, utils_1.isHexString)(key)) { throw new InvalidKeyError(); } if (yield this.keyHasPurpose(key, purpose, options)) { throw new KeyPurposeAlreadyRegisteredError(); } return instance.addKey(key, purpose, type, (_a = options === null || options === void 0 ? void 0 : options.overrides) !== null && _a !== void 0 ? _a : {}); }); } /** * Returns the Identity if the Identity was deployed, or awaits for the Identity to be deployed before returning it. * * @example Usually called after a `Identity.deployNew()`: * ```typescript * const identity = await Identity.deployNew(); * await identity.deployed(); * ``` */ deployed() { return __awaiter(this, void 0, void 0, function* () { if (this.deploymentContract) { yield this.deploymentContract.deployed(); return this; } return this; }); } /** * Get ClaimData details for an Identity. * @param claimId * @param [options] */ getClaim(claimId, options) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { const _provider = (_b = (_a = options === null || options === void 0 ? void 0 : options.provider) !== null && _a !== void 0 ? _a : options === null || options === void 0 ? void 0 : options.signer) !== null && _b !== void 0 ? _b : this.provider; let instance = this.claimHolderInstance; if (!instance) { instance = yield this.instantiateClaimHolder(_provider); } return instance.getClaim(claimId).then((claim) => { if (claim[2] === ethers_1.constants.AddressZero) { return null; } return new Claim_1.Claim({ address: this.address, id: claimId, topic: claim[0].toNumber(), scheme: claim[1].toNumber(), issuer: claim[2], signature: claim[3], data: claim[4], uri: claim[5], }); }); }); } /** * Get claims details for an Identity. * @deprecated * @param claimId * @param [options] */ getClaims(claimId, options) { return __awaiter(this, void 0, void 0, function* () { throw new Error('Claim retrieval must be performed by exploring ClaimAdded and ClaimRemoved events.'); }); } /** * Get Claims details by topic for an Identity. * @param topic * @param [options] */ getClaimsByTopic(topic, options) { return __awaiter(this, void 0, void 0, function* () { const promises = yield this.getClaimIdsByTopic(topic, options) .then((claimIds) => claimIds.map((claimId) => __awaiter(this, void 0, void 0, function* () { return this.getClaim(claimId, options); }))); return Promise.all(promises); }); } /** * Get ClaimData IDs by topic for an Identity. * @param topic * @param [options] */ getClaimIdsByTopic(topic, options) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { const _provider = (_b = (_a = options === null || options === void 0 ? void 0 : options.provider) !== null && _a !== void 0 ? _a : options === null || options === void 0 ? void 0 : options.signer) !== null && _b !== void 0 ? _b : this.provider; let instance = this.claimHolderInstance; if (!instance) { instance = yield this.instantiateClaimHolder(_provider); } return instance.getClaimIdsByTopic(topic); }); } /** * Returns the deployment transaction of the Identity if it was previously created with Identity.deployNew(). * * @example Can be called only after a `Identity.deployNew()`: * ```typescript * const identity = await Identity.deployNew(); * identity.getDeployTransaction(); * ``` */ getDeployTransaction() { if (this.deploymentContract) { return this.deploymentContract.deployTransaction; } return null; } /** * Get the details of a key in an Identity. * @param key * @param [options] */ getKey(key, options) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { const _provider = (_b = (_a = options === null || options === void 0 ? void 0 : options.provider) !== null && _a !== void 0 ? _a : options === null || options === void 0 ? void 0 : options.signer) !== null && _b !== void 0 ? _b : this.provider; let instance = this.keyHolderInstance; if (!instance) { instance = yield this.instantiateKeyHolder(_provider); } return instance.getKey(key).then((key) => { if (key[2] === '0x0000000000000000000000000000000000000000000000000000000000000000') { return null; } return { purposes: key[0].map(purpose => purpose.toNumber()), type: key[1].toNumber(), key: key[2], }; }); }); } /** * Get the purpose of a key in an identity. * @param key * @param [options] */ getKeyPurposes(key, options) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { const _provider = (_b = (_a = options === null || options === void 0 ? void 0 : options.provider) !== null && _a !== void 0 ? _a : options === null || options === void 0 ? void 0 : options.signer) !== null && _b !== void 0 ? _b : this.provider; let instance = this.keyHolderInstance; if (!instance) { instance = yield this.instantiateKeyHolder(_provider); } return instance.getKeyPurposes(key).then((purposes) => { return purposes.map((purpose) => purpose.toNumber()); }); }); } /** * Get the details of the keys contained in an Identity by purpose. * @param purpose * @param [options] */ getKeysByPurpose(purpose, options) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { const _provider = (_b = (_a = options === null || options === void 0 ? void 0 : options.provider) !== null && _a !== void 0 ? _a : options === null || options === void 0 ? void 0 : options.signer) !== null && _b !== void 0 ? _b : this.provider; let instance = this.keyHolderInstance; if (!instance) { instance = yield this.instantiateKeyHolder(_provider); } const promises = yield instance.getKeysByPurpose(purpose) .then((keys) => { return keys.map((key) => __awaiter(this, void 0, void 0, function* () { return this.getKey(key, options); })); }); return Promise.all(promises); }); } /** * Instantiate the Identity IdentityInterface Contract with the Identity's address. * @param [providerOrSigner] */ instantiateClaimHolder(providerOrSigner) { return __awaiter(this, void 0, void 0, function* () { const _provider = providerOrSigner !== null && providerOrSigner !== void 0 ? providerOrSigner : this.provider; if (this.claimHolderInstance && (this.claimHolderInstance.provider === _provider || this.claimHolderInstance.signer === _provider)) { return this.claimHolderInstance; } this.claimHolderInstance = yield this.instantiate(OnchainID.interfaces.IERC735.abi, _provider); return this.claimHolderInstance; }); } /** * Instantiate the Identity KeyHolder Contract with the Identity's address. * @param [providerOrSigner] */ instantiateKeyHolder(providerOrSigner) { return __awaiter(this, void 0, void 0, function* () { const _provider = providerOrSigner !== null && providerOrSigner !== void 0 ? providerOrSigner : this.provider; if (this.keyHolderInstance && (this.keyHolderInstance.provider === _provider || this.keyHolderInstance.signer === _provider)) { return this.keyHolderInstance; } this.keyHolderInstance = yield this.instantiate(OnchainID.interfaces.IERC734.abi, _provider); return this.keyHolderInstance; }); } /** * Instantiate an Identity with the given abi using the object's address. * @param abi * @param [providerOrSigner] */ instantiate(abi, providerOrSigner) { return __awaiter(this, void 0, void 0, function* () { if (!this.address) { throw new Error('Identity has no address defined. Use .instantiateAtAddress() or set .address first.'); } const _provider = providerOrSigner !== null && providerOrSigner !== void 0 ? providerOrSigner : this.provider; return this.instantiateAtAddress(this.address, abi, _provider); }); } /** * Instantiate an Identity with the given abi at a given address. * @param address * @param abi * @param [providerOrSigner] */ instantiateAtAddress(address, abi, providerOrSigner) { return __awaiter(this, void 0, void 0, function* () { const _providerOrSigner = providerOrSigner !== null && providerOrSigner !== void 0 ? providerOrSigner : this.provider; if (!providers_1.Provider.isProvider(_providerOrSigner) && !ethers_1.Signer.isSigner(_providerOrSigner)) { throw new Errors_1.InvalidProviderError('A provider or a signer is required to instanciate a contract.'); } return new ethers_1.Contract(address, abi, _providerOrSigner); }); } /** * Check if a key has at least the given purpose. * @param key * @param purpose * @param [options] */ keyHasPurpose(key, purpose, options) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { const _provider = (_b = (_a = options === null || options === void 0 ? void 0 : options.provider) !== null && _a !== void 0 ? _a : options === null || options === void 0 ? void 0 : options.signer) !== null && _b !== void 0 ? _b : this.provider; let instance = this.keyHolderInstance; if (!instance) { instance = yield this.instantiateKeyHolder(_provider); } return instance.keyHasPurpose(key, purpose); }); } /** * Remove a claim, provided the signer has the right to do so. * @param claimId * @param [options] */ removeClaim(claimId, options) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { const _signer = (_a = options === null || options === void 0 ? void 0 : options.signer) !== null && _a !== void 0 ? _a : this.provider; if (!ethers_1.Signer.isSigner(_signer)) { throw new Errors_1.InvalidProviderError('Contract operations require a Signer.'); } if (!(yield this.keyHasPurpose((0, Utils_1.encodeAndHash)(['address'], [yield _signer.getAddress()]), Key_interface_1.KeyPurpose.CLAIM, options))) { throw new Errors_1.OperationForbiddenError({ message: 'CLAIM key required on the identity to remove a claim.' }); } const claim = yield this.getClaim(claimId, options); if (!claim || claim.topic === 0) { throw new NonExistingClaimError({ message: 'The specified claim ID was not found on the Identity.' }); } let instance = this.claimHolderInstance; if (!instance || (options === null || options === void 0 ? void 0 : options.signer)) { instance = yield this.instantiateClaimHolder(_signer); } return instance.removeClaim(claimId, (_b = options === null || options === void 0 ? void 0 : options.overrides) !== null && _b !== void 0 ? _b : {}); }); } /** * Remove a Key from an Identity. * The Signer must have a MANAGEMENT key in the Identity. * @param key Key must be a valid byte32 hex string. * @param purpose KeyPurpose must be a valid byte32 hex string. * @param [options] */ removeKey(key, purpose, options) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { const _signer = (_a = options === null || options === void 0 ? void 0 : options.signer) !== null && _a !== void 0 ? _a : this.provider; if (!ethers_1.Signer.isSigner(_signer)) { throw new Errors_1.InvalidProviderError('Contract operations require a Signer.'); } if (!(0, utils_1.isHexString)(key)) { throw new InvalidKeyError(); } let instance = this.keyHolderInstance; if (!instance) { instance = yield this.instantiateKeyHolder(_signer); } if (!(yield this.keyHasPurpose((0, Utils_1.encodeAndHash)(['address'], [yield _signer.getAddress()]), Key_interface_1.KeyPurpose.MANAGEMENT, options))) { throw new Errors_1.OperationForbiddenError({ message: 'MANAGEMENT key required on the identity to remove a key.' }); } if (!(yield this.keyHasPurpose(key, purpose, options))) { throw new KeyPurposeNotRegisteredError(); } return instance.removeKey(key, purpose, (_b = options === null || options === void 0 ? void 0 : options.overrides) !== null && _b !== void 0 ? _b : {}); }); } /** * Use another provider or signer to interact with the Identity. * This will reset all contract instances of the identity that will need to be instantiated once again with the new provider. * @param providerOrSigner */ useProvider(providerOrSigner) { this.provider = providerOrSigner; // Reset contract instances. this.claimHolderInstance = undefined; this.keyHolderInstance = undefined; } /** * Verify if the message was signed with a key that is authorized to perform action for this Identity. * @param message * @param signature * @param [options] */ validateSignature(message, signature, options) { return __awaiter(this, void 0, void 0, function* () { let signingKey; try { signingKey = (0, utils_1.verifyMessage)(message, signature); } catch (err) { return false; } return yield this.keyHasPurpose((0, Utils_1.encodeAndHash)(['address'], [signingKey]), Key_interface_1.KeyPurpose.ACTION, options); }); } /** * Verify a specific claim given with full data or by ID. * @param claim Claim object or ID. * @param [options] */ verifyClaim(claim, options) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { if (!this.address) { return { valid: false, reason: 'Identity is not deployed.', }; } const _provider = (_b = (_a = options === null || options === void 0 ? void 0 : options.provider) !== null && _a !== void 0 ? _a : options === null || options === void 0 ? void 0 : options.signer) !== null && _b !== void 0 ? _b : this.provider; if (!providers_1.Provider.isProvider(_provider)) { throw new Error('Provider is required to verify claim validity.'); } let claimData; if (typeof claim === 'string') { claimData = yield this.getClaim(claim, options); } else { claimData = claim; } const _claim = new Claim_1.Claim(claimData); const valid = yield _claim.verifyValidity(_provider); return { valid, }; }); } } exports.Identity = Identity; //# sourceMappingURL=Identity.js.map