@elysium-onchain-id/identity-sdk
Version:
Interact with BlockChain Identities.
699 lines • 35.8 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.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