ethr-did-resolver
Advanced tools
Comparing version 6.1.0 to 6.2.0
import { Signer } from '@ethersproject/abstract-signer'; | ||
import { CallOverrides, Contract } from '@ethersproject/contracts'; | ||
import { BlockTag, Provider, TransactionReceipt } from '@ethersproject/providers'; | ||
import { address } from './helpers'; | ||
import { address, MetaSignature } from './helpers'; | ||
/** | ||
@@ -13,2 +13,3 @@ * A class that can be used to interact with the ERC1056 contract on behalf of a local controller key-pair | ||
did: string; | ||
private legacyNonce; | ||
/** | ||
@@ -24,12 +25,25 @@ * Creates an EthrDidController instance. | ||
* @param registry - optional - The ERC1056 registry address. Defaults to '0xdca7ef03e98e0dc2b855be647c39abe984fcf21b'. Only used with 'provider' or 'rpcUrl' | ||
* @param legacyNonce - optional - If the legacy nonce tracking method should be accounted for. If lesser version of did-ethr-registry contract v1.0.0 is used then this should be true. | ||
*/ | ||
constructor(identifier: string | address, contract?: Contract, signer?: Signer, chainNameOrId?: string, provider?: Provider, rpcUrl?: string, registry?: string); | ||
constructor(identifier: string | address, contract?: Contract, signer?: Signer, chainNameOrId?: string, provider?: Provider, rpcUrl?: string, registry?: string, legacyNonce?: boolean); | ||
getOwner(address: address, blockTag?: BlockTag): Promise<string>; | ||
attachContract(controller?: address | Promise<address>): Promise<Contract>; | ||
changeOwner(newOwner: address, options?: CallOverrides): Promise<TransactionReceipt>; | ||
createChangeOwnerHash(newOwner: address): Promise<string>; | ||
changeOwnerSigned(newOwner: address, metaSignature: MetaSignature, options?: CallOverrides): Promise<TransactionReceipt>; | ||
addDelegate(delegateType: string, delegateAddress: address, exp: number, options?: CallOverrides): Promise<TransactionReceipt>; | ||
createAddDelegateHash(delegateType: string, delegateAddress: address, exp: number): Promise<string>; | ||
addDelegateSigned(delegateType: string, delegateAddress: address, exp: number, metaSignature: MetaSignature, options?: CallOverrides): Promise<TransactionReceipt>; | ||
revokeDelegate(delegateType: string, delegateAddress: address, options?: CallOverrides): Promise<TransactionReceipt>; | ||
createRevokeDelegateHash(delegateType: string, delegateAddress: address): Promise<string>; | ||
revokeDelegateSigned(delegateType: string, delegateAddress: address, metaSignature: MetaSignature, options?: CallOverrides): Promise<TransactionReceipt>; | ||
setAttribute(attrName: string, attrValue: string, exp: number, options?: CallOverrides): Promise<TransactionReceipt>; | ||
createSetAttributeHash(attrName: string, attrValue: string, exp: number): Promise<string>; | ||
setAttributeSigned(attrName: string, attrValue: string, exp: number, metaSignature: MetaSignature, options?: CallOverrides): Promise<TransactionReceipt>; | ||
revokeAttribute(attrName: string, attrValue: string, options?: CallOverrides): Promise<TransactionReceipt>; | ||
createRevokeAttributeHash(attrName: string, attrValue: string): Promise<string>; | ||
private getPaddedNonceCompatability; | ||
private getPaddedNonce; | ||
revokeAttributeSigned(attrName: string, attrValue: string, metaSignature: MetaSignature, options?: CallOverrides): Promise<TransactionReceipt>; | ||
} | ||
//# sourceMappingURL=controller.d.ts.map |
import { BigNumber } from '@ethersproject/bignumber'; | ||
import { VerificationMethod } from 'did-resolver'; | ||
import { Contract } from '@ethersproject/contracts'; | ||
export declare const identifierMatcher: RegExp; | ||
@@ -7,2 +8,3 @@ export declare const nullAddress = "0x0000000000000000000000000000000000000000"; | ||
export declare const DEFAULT_JSON_RPC = "http://127.0.0.1:8545/"; | ||
export declare const MESSAGE_PREFIX = "0x1900"; | ||
export declare type address = string; | ||
@@ -53,2 +55,7 @@ export declare type uint256 = BigNumber; | ||
} | ||
export interface MetaSignature { | ||
sigV: number; | ||
sigR: bytes32; | ||
sigS: bytes32; | ||
} | ||
export declare const legacyAttrTypes: Record<string, string>; | ||
@@ -64,2 +71,3 @@ export declare const legacyAlgoMap: Record<string, string>; | ||
}; | ||
export declare function signMetaTxData(identity: string, signerAddress: string, privateKeyBytes: Uint8Array, dataBytes: Uint8Array, didReg: Contract): Promise<import("@ethersproject/bytes").Signature>; | ||
export declare enum Errors { | ||
@@ -66,0 +74,0 @@ /** |
@@ -8,2 +8,5 @@ import { Base58 } from '@ethersproject/basex'; | ||
import { computeAddress } from '@ethersproject/transactions'; | ||
import { keccak256 } from '@ethersproject/keccak256'; | ||
import { arrayify, hexlify, concat, hexConcat, zeroPad } from '@ethersproject/bytes'; | ||
import '@ethersproject/signing-key'; | ||
@@ -13,2 +16,3 @@ const identifierMatcher = /^(.*)?(0x[0-9a-fA-F]{40}|0x[0-9a-fA-F]{66})$/; | ||
const DEFAULT_REGISTRY_ADDRESS = '0xdca7ef03e98e0dc2b855be647c39abe984fcf21b'; | ||
const MESSAGE_PREFIX = '0x1900'; | ||
var verificationMethodTypes; | ||
@@ -221,2 +225,478 @@ | ||
const HashZero = "0x0000000000000000000000000000000000000000000000000000000000000000"; | ||
const version$1 = "logger/5.6.0"; | ||
let _permanentCensorErrors = false; | ||
let _censorErrors = false; | ||
const LogLevels = { debug: 1, "default": 2, info: 2, warning: 3, error: 4, off: 5 }; | ||
let _logLevel = LogLevels["default"]; | ||
let _globalLogger = null; | ||
function _checkNormalize() { | ||
try { | ||
const missing = []; | ||
// Make sure all forms of normalization are supported | ||
["NFD", "NFC", "NFKD", "NFKC"].forEach((form) => { | ||
try { | ||
if ("test".normalize(form) !== "test") { | ||
throw new Error("bad normalize"); | ||
} | ||
; | ||
} | ||
catch (error) { | ||
missing.push(form); | ||
} | ||
}); | ||
if (missing.length) { | ||
throw new Error("missing " + missing.join(", ")); | ||
} | ||
if (String.fromCharCode(0xe9).normalize("NFD") !== String.fromCharCode(0x65, 0x0301)) { | ||
throw new Error("broken implementation"); | ||
} | ||
} | ||
catch (error) { | ||
return error.message; | ||
} | ||
return null; | ||
} | ||
const _normalizeError = _checkNormalize(); | ||
var LogLevel; | ||
(function (LogLevel) { | ||
LogLevel["DEBUG"] = "DEBUG"; | ||
LogLevel["INFO"] = "INFO"; | ||
LogLevel["WARNING"] = "WARNING"; | ||
LogLevel["ERROR"] = "ERROR"; | ||
LogLevel["OFF"] = "OFF"; | ||
})(LogLevel || (LogLevel = {})); | ||
var ErrorCode; | ||
(function (ErrorCode) { | ||
/////////////////// | ||
// Generic Errors | ||
// Unknown Error | ||
ErrorCode["UNKNOWN_ERROR"] = "UNKNOWN_ERROR"; | ||
// Not Implemented | ||
ErrorCode["NOT_IMPLEMENTED"] = "NOT_IMPLEMENTED"; | ||
// Unsupported Operation | ||
// - operation | ||
ErrorCode["UNSUPPORTED_OPERATION"] = "UNSUPPORTED_OPERATION"; | ||
// Network Error (i.e. Ethereum Network, such as an invalid chain ID) | ||
// - event ("noNetwork" is not re-thrown in provider.ready; otherwise thrown) | ||
ErrorCode["NETWORK_ERROR"] = "NETWORK_ERROR"; | ||
// Some sort of bad response from the server | ||
ErrorCode["SERVER_ERROR"] = "SERVER_ERROR"; | ||
// Timeout | ||
ErrorCode["TIMEOUT"] = "TIMEOUT"; | ||
/////////////////// | ||
// Operational Errors | ||
// Buffer Overrun | ||
ErrorCode["BUFFER_OVERRUN"] = "BUFFER_OVERRUN"; | ||
// Numeric Fault | ||
// - operation: the operation being executed | ||
// - fault: the reason this faulted | ||
ErrorCode["NUMERIC_FAULT"] = "NUMERIC_FAULT"; | ||
/////////////////// | ||
// Argument Errors | ||
// Missing new operator to an object | ||
// - name: The name of the class | ||
ErrorCode["MISSING_NEW"] = "MISSING_NEW"; | ||
// Invalid argument (e.g. value is incompatible with type) to a function: | ||
// - argument: The argument name that was invalid | ||
// - value: The value of the argument | ||
ErrorCode["INVALID_ARGUMENT"] = "INVALID_ARGUMENT"; | ||
// Missing argument to a function: | ||
// - count: The number of arguments received | ||
// - expectedCount: The number of arguments expected | ||
ErrorCode["MISSING_ARGUMENT"] = "MISSING_ARGUMENT"; | ||
// Too many arguments | ||
// - count: The number of arguments received | ||
// - expectedCount: The number of arguments expected | ||
ErrorCode["UNEXPECTED_ARGUMENT"] = "UNEXPECTED_ARGUMENT"; | ||
/////////////////// | ||
// Blockchain Errors | ||
// Call exception | ||
// - transaction: the transaction | ||
// - address?: the contract address | ||
// - args?: The arguments passed into the function | ||
// - method?: The Solidity method signature | ||
// - errorSignature?: The EIP848 error signature | ||
// - errorArgs?: The EIP848 error parameters | ||
// - reason: The reason (only for EIP848 "Error(string)") | ||
ErrorCode["CALL_EXCEPTION"] = "CALL_EXCEPTION"; | ||
// Insufficient funds (< value + gasLimit * gasPrice) | ||
// - transaction: the transaction attempted | ||
ErrorCode["INSUFFICIENT_FUNDS"] = "INSUFFICIENT_FUNDS"; | ||
// Nonce has already been used | ||
// - transaction: the transaction attempted | ||
ErrorCode["NONCE_EXPIRED"] = "NONCE_EXPIRED"; | ||
// The replacement fee for the transaction is too low | ||
// - transaction: the transaction attempted | ||
ErrorCode["REPLACEMENT_UNDERPRICED"] = "REPLACEMENT_UNDERPRICED"; | ||
// The gas limit could not be estimated | ||
// - transaction: the transaction passed to estimateGas | ||
ErrorCode["UNPREDICTABLE_GAS_LIMIT"] = "UNPREDICTABLE_GAS_LIMIT"; | ||
// The transaction was replaced by one with a higher gas price | ||
// - reason: "cancelled", "replaced" or "repriced" | ||
// - cancelled: true if reason == "cancelled" or reason == "replaced") | ||
// - hash: original transaction hash | ||
// - replacement: the full TransactionsResponse for the replacement | ||
// - receipt: the receipt of the replacement | ||
ErrorCode["TRANSACTION_REPLACED"] = "TRANSACTION_REPLACED"; | ||
})(ErrorCode || (ErrorCode = {})); | ||
const HEX = "0123456789abcdef"; | ||
class Logger { | ||
constructor(version) { | ||
Object.defineProperty(this, "version", { | ||
enumerable: true, | ||
value: version, | ||
writable: false | ||
}); | ||
} | ||
_log(logLevel, args) { | ||
const level = logLevel.toLowerCase(); | ||
if (LogLevels[level] == null) { | ||
this.throwArgumentError("invalid log level name", "logLevel", logLevel); | ||
} | ||
if (_logLevel > LogLevels[level]) { | ||
return; | ||
} | ||
console.log.apply(console, args); | ||
} | ||
debug(...args) { | ||
this._log(Logger.levels.DEBUG, args); | ||
} | ||
info(...args) { | ||
this._log(Logger.levels.INFO, args); | ||
} | ||
warn(...args) { | ||
this._log(Logger.levels.WARNING, args); | ||
} | ||
makeError(message, code, params) { | ||
// Errors are being censored | ||
if (_censorErrors) { | ||
return this.makeError("censored error", code, {}); | ||
} | ||
if (!code) { | ||
code = Logger.errors.UNKNOWN_ERROR; | ||
} | ||
if (!params) { | ||
params = {}; | ||
} | ||
const messageDetails = []; | ||
Object.keys(params).forEach((key) => { | ||
const value = params[key]; | ||
try { | ||
if (value instanceof Uint8Array) { | ||
let hex = ""; | ||
for (let i = 0; i < value.length; i++) { | ||
hex += HEX[value[i] >> 4]; | ||
hex += HEX[value[i] & 0x0f]; | ||
} | ||
messageDetails.push(key + "=Uint8Array(0x" + hex + ")"); | ||
} | ||
else { | ||
messageDetails.push(key + "=" + JSON.stringify(value)); | ||
} | ||
} | ||
catch (error) { | ||
messageDetails.push(key + "=" + JSON.stringify(params[key].toString())); | ||
} | ||
}); | ||
messageDetails.push(`code=${code}`); | ||
messageDetails.push(`version=${this.version}`); | ||
const reason = message; | ||
let url = ""; | ||
switch (code) { | ||
case ErrorCode.NUMERIC_FAULT: { | ||
url = "NUMERIC_FAULT"; | ||
const fault = message; | ||
switch (fault) { | ||
case "overflow": | ||
case "underflow": | ||
case "division-by-zero": | ||
url += "-" + fault; | ||
break; | ||
case "negative-power": | ||
case "negative-width": | ||
url += "-unsupported"; | ||
break; | ||
case "unbound-bitwise-result": | ||
url += "-unbound-result"; | ||
break; | ||
} | ||
break; | ||
} | ||
case ErrorCode.CALL_EXCEPTION: | ||
case ErrorCode.INSUFFICIENT_FUNDS: | ||
case ErrorCode.MISSING_NEW: | ||
case ErrorCode.NONCE_EXPIRED: | ||
case ErrorCode.REPLACEMENT_UNDERPRICED: | ||
case ErrorCode.TRANSACTION_REPLACED: | ||
case ErrorCode.UNPREDICTABLE_GAS_LIMIT: | ||
url = code; | ||
break; | ||
} | ||
if (url) { | ||
message += " [ See: https:/\/links.ethers.org/v5-errors-" + url + " ]"; | ||
} | ||
if (messageDetails.length) { | ||
message += " (" + messageDetails.join(", ") + ")"; | ||
} | ||
// @TODO: Any?? | ||
const error = new Error(message); | ||
error.reason = reason; | ||
error.code = code; | ||
Object.keys(params).forEach(function (key) { | ||
error[key] = params[key]; | ||
}); | ||
return error; | ||
} | ||
throwError(message, code, params) { | ||
throw this.makeError(message, code, params); | ||
} | ||
throwArgumentError(message, name, value) { | ||
return this.throwError(message, Logger.errors.INVALID_ARGUMENT, { | ||
argument: name, | ||
value: value | ||
}); | ||
} | ||
assert(condition, message, code, params) { | ||
if (!!condition) { | ||
return; | ||
} | ||
this.throwError(message, code, params); | ||
} | ||
assertArgument(condition, message, name, value) { | ||
if (!!condition) { | ||
return; | ||
} | ||
this.throwArgumentError(message, name, value); | ||
} | ||
checkNormalize(message) { | ||
if (_normalizeError) { | ||
this.throwError("platform missing String.prototype.normalize", Logger.errors.UNSUPPORTED_OPERATION, { | ||
operation: "String.prototype.normalize", form: _normalizeError | ||
}); | ||
} | ||
} | ||
checkSafeUint53(value, message) { | ||
if (typeof (value) !== "number") { | ||
return; | ||
} | ||
if (message == null) { | ||
message = "value not safe"; | ||
} | ||
if (value < 0 || value >= 0x1fffffffffffff) { | ||
this.throwError(message, Logger.errors.NUMERIC_FAULT, { | ||
operation: "checkSafeInteger", | ||
fault: "out-of-safe-range", | ||
value: value | ||
}); | ||
} | ||
if (value % 1) { | ||
this.throwError(message, Logger.errors.NUMERIC_FAULT, { | ||
operation: "checkSafeInteger", | ||
fault: "non-integer", | ||
value: value | ||
}); | ||
} | ||
} | ||
checkArgumentCount(count, expectedCount, message) { | ||
if (message) { | ||
message = ": " + message; | ||
} | ||
else { | ||
message = ""; | ||
} | ||
if (count < expectedCount) { | ||
this.throwError("missing argument" + message, Logger.errors.MISSING_ARGUMENT, { | ||
count: count, | ||
expectedCount: expectedCount | ||
}); | ||
} | ||
if (count > expectedCount) { | ||
this.throwError("too many arguments" + message, Logger.errors.UNEXPECTED_ARGUMENT, { | ||
count: count, | ||
expectedCount: expectedCount | ||
}); | ||
} | ||
} | ||
checkNew(target, kind) { | ||
if (target === Object || target == null) { | ||
this.throwError("missing new", Logger.errors.MISSING_NEW, { name: kind.name }); | ||
} | ||
} | ||
checkAbstract(target, kind) { | ||
if (target === kind) { | ||
this.throwError("cannot instantiate abstract class " + JSON.stringify(kind.name) + " directly; use a sub-class", Logger.errors.UNSUPPORTED_OPERATION, { name: target.name, operation: "new" }); | ||
} | ||
else if (target === Object || target == null) { | ||
this.throwError("missing new", Logger.errors.MISSING_NEW, { name: kind.name }); | ||
} | ||
} | ||
static globalLogger() { | ||
if (!_globalLogger) { | ||
_globalLogger = new Logger(version$1); | ||
} | ||
return _globalLogger; | ||
} | ||
static setCensorship(censorship, permanent) { | ||
if (!censorship && permanent) { | ||
this.globalLogger().throwError("cannot permanently disable censorship", Logger.errors.UNSUPPORTED_OPERATION, { | ||
operation: "setCensorship" | ||
}); | ||
} | ||
if (_permanentCensorErrors) { | ||
if (!censorship) { | ||
return; | ||
} | ||
this.globalLogger().throwError("error censorship permanent", Logger.errors.UNSUPPORTED_OPERATION, { | ||
operation: "setCensorship" | ||
}); | ||
} | ||
_censorErrors = !!censorship; | ||
_permanentCensorErrors = !!permanent; | ||
} | ||
static setLogLevel(logLevel) { | ||
const level = LogLevels[logLevel.toLowerCase()]; | ||
if (level == null) { | ||
Logger.globalLogger().warn("invalid log level - " + logLevel); | ||
return; | ||
} | ||
_logLevel = level; | ||
} | ||
static from(version) { | ||
return new Logger(version); | ||
} | ||
} | ||
Logger.errors = ErrorCode; | ||
Logger.levels = LogLevel; | ||
const version = "strings/5.6.1"; | ||
const logger = new Logger(version); | ||
/////////////////////////////// | ||
var UnicodeNormalizationForm; | ||
(function (UnicodeNormalizationForm) { | ||
UnicodeNormalizationForm["current"] = ""; | ||
UnicodeNormalizationForm["NFC"] = "NFC"; | ||
UnicodeNormalizationForm["NFD"] = "NFD"; | ||
UnicodeNormalizationForm["NFKC"] = "NFKC"; | ||
UnicodeNormalizationForm["NFKD"] = "NFKD"; | ||
})(UnicodeNormalizationForm || (UnicodeNormalizationForm = {})); | ||
var Utf8ErrorReason; | ||
(function (Utf8ErrorReason) { | ||
// A continuation byte was present where there was nothing to continue | ||
// - offset = the index the codepoint began in | ||
Utf8ErrorReason["UNEXPECTED_CONTINUE"] = "unexpected continuation byte"; | ||
// An invalid (non-continuation) byte to start a UTF-8 codepoint was found | ||
// - offset = the index the codepoint began in | ||
Utf8ErrorReason["BAD_PREFIX"] = "bad codepoint prefix"; | ||
// The string is too short to process the expected codepoint | ||
// - offset = the index the codepoint began in | ||
Utf8ErrorReason["OVERRUN"] = "string overrun"; | ||
// A missing continuation byte was expected but not found | ||
// - offset = the index the continuation byte was expected at | ||
Utf8ErrorReason["MISSING_CONTINUE"] = "missing continuation byte"; | ||
// The computed code point is outside the range for UTF-8 | ||
// - offset = start of this codepoint | ||
// - badCodepoint = the computed codepoint; outside the UTF-8 range | ||
Utf8ErrorReason["OUT_OF_RANGE"] = "out of UTF-8 range"; | ||
// UTF-8 strings may not contain UTF-16 surrogate pairs | ||
// - offset = start of this codepoint | ||
// - badCodepoint = the computed codepoint; inside the UTF-16 surrogate range | ||
Utf8ErrorReason["UTF16_SURROGATE"] = "UTF-16 surrogate"; | ||
// The string is an overlong representation | ||
// - offset = start of this codepoint | ||
// - badCodepoint = the computed codepoint; already bounds checked | ||
Utf8ErrorReason["OVERLONG"] = "overlong representation"; | ||
})(Utf8ErrorReason || (Utf8ErrorReason = {})); | ||
function errorFunc(reason, offset, bytes, output, badCodepoint) { | ||
return logger.throwArgumentError(`invalid codepoint at offset ${offset}; ${reason}`, "bytes", bytes); | ||
} | ||
function ignoreFunc(reason, offset, bytes, output, badCodepoint) { | ||
// If there is an invalid prefix (including stray continuation), skip any additional continuation bytes | ||
if (reason === Utf8ErrorReason.BAD_PREFIX || reason === Utf8ErrorReason.UNEXPECTED_CONTINUE) { | ||
let i = 0; | ||
for (let o = offset + 1; o < bytes.length; o++) { | ||
if (bytes[o] >> 6 !== 0x02) { | ||
break; | ||
} | ||
i++; | ||
} | ||
return i; | ||
} | ||
// This byte runs us past the end of the string, so just jump to the end | ||
// (but the first byte was read already read and therefore skipped) | ||
if (reason === Utf8ErrorReason.OVERRUN) { | ||
return bytes.length - offset - 1; | ||
} | ||
// Nothing to skip | ||
return 0; | ||
} | ||
function replaceFunc(reason, offset, bytes, output, badCodepoint) { | ||
// Overlong representations are otherwise "valid" code points; just non-deistingtished | ||
if (reason === Utf8ErrorReason.OVERLONG) { | ||
output.push(badCodepoint); | ||
return 0; | ||
} | ||
// Put the replacement character into the output | ||
output.push(0xfffd); | ||
// Otherwise, process as if ignoring errors | ||
return ignoreFunc(reason, offset, bytes); | ||
} | ||
// Common error handing strategies | ||
Object.freeze({ | ||
error: errorFunc, | ||
ignore: ignoreFunc, | ||
replace: replaceFunc | ||
}); | ||
// http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array | ||
function toUtf8Bytes(str, form = UnicodeNormalizationForm.current) { | ||
if (form != UnicodeNormalizationForm.current) { | ||
logger.checkNormalize(); | ||
str = str.normalize(form); | ||
} | ||
let result = []; | ||
for (let i = 0; i < str.length; i++) { | ||
const c = str.charCodeAt(i); | ||
if (c < 0x80) { | ||
result.push(c); | ||
} | ||
else if (c < 0x800) { | ||
result.push((c >> 6) | 0xc0); | ||
result.push((c & 0x3f) | 0x80); | ||
} | ||
else if ((c & 0xfc00) == 0xd800) { | ||
i++; | ||
const c2 = str.charCodeAt(i); | ||
if (i >= str.length || (c2 & 0xfc00) !== 0xdc00) { | ||
throw new Error("invalid utf-8 string"); | ||
} | ||
// Surrogate Pair | ||
const pair = 0x10000 + ((c & 0x03ff) << 10) + (c2 & 0x03ff); | ||
result.push((pair >> 18) | 0xf0); | ||
result.push(((pair >> 12) & 0x3f) | 0x80); | ||
result.push(((pair >> 6) & 0x3f) | 0x80); | ||
result.push((pair & 0x3f) | 0x80); | ||
} | ||
else { | ||
result.push((c >> 12) | 0xe0); | ||
result.push(((c >> 6) & 0x3f) | 0x80); | ||
result.push((c & 0x3f) | 0x80); | ||
} | ||
} | ||
return arrayify(result); | ||
} | ||
function formatBytes32String(text) { | ||
// Get the bytes | ||
const bytes = toUtf8Bytes(text); | ||
// Check we have room for null-termination | ||
if (bytes.length > 31) { | ||
throw new Error("bytes32 string must be less than 32 bytes"); | ||
} | ||
// Zero-pad (implicitly null-terminates) | ||
return hexlify(concat([bytes, HashZero]).slice(0, 32)); | ||
} | ||
/** | ||
@@ -237,4 +717,5 @@ * A class that can be used to interact with the ERC1056 contract on behalf of a local controller key-pair | ||
* @param registry - optional - The ERC1056 registry address. Defaults to '0xdca7ef03e98e0dc2b855be647c39abe984fcf21b'. Only used with 'provider' or 'rpcUrl' | ||
* @param legacyNonce - optional - If the legacy nonce tracking method should be accounted for. If lesser version of did-ethr-registry contract v1.0.0 is used then this should be true. | ||
*/ | ||
constructor(identifier, contract, signer, chainNameOrId = 'mainnet', provider, rpcUrl, registry = DEFAULT_REGISTRY_ADDRESS) { | ||
constructor(identifier, contract, signer, chainNameOrId = 'mainnet', provider, rpcUrl, registry = DEFAULT_REGISTRY_ADDRESS, legacyNonce = true) { | ||
this.contract = void 0; | ||
@@ -244,3 +725,5 @@ this.signer = void 0; | ||
this.did = void 0; | ||
// initialize identifier | ||
this.legacyNonce = void 0; | ||
this.legacyNonce = legacyNonce; // initialize identifier | ||
const { | ||
@@ -326,6 +809,19 @@ address, | ||
addDelegate(delegateType, delegateAddress, exp, options = {}) { | ||
createChangeOwnerHash(newOwner) { | ||
try { | ||
const _this4 = this; | ||
return Promise.resolve(_this4.getPaddedNonceCompatability()).then(function (paddedNonce) { | ||
const dataToHash = hexConcat([MESSAGE_PREFIX, _this4.contract.address, paddedNonce, _this4.address, concat([toUtf8Bytes('changeOwner'), newOwner])]); | ||
return keccak256(dataToHash); | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
changeOwnerSigned(newOwner, metaSignature, options = {}) { | ||
try { | ||
const _this5 = this; | ||
const overrides = { | ||
@@ -336,6 +832,26 @@ gasLimit: 123456, | ||
}; | ||
return Promise.resolve(_this4.attachContract(overrides.from)).then(function (contract) { | ||
return Promise.resolve(_this5.attachContract(overrides.from)).then(function (contract) { | ||
delete overrides.from; | ||
return Promise.resolve(contract.functions.changeOwnerSigned(_this5.address, metaSignature.sigV, metaSignature.sigR, metaSignature.sigS, newOwner, overrides)).then(function (ownerChange) { | ||
return Promise.resolve(ownerChange.wait()); | ||
}); | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
addDelegate(delegateType, delegateAddress, exp, options = {}) { | ||
try { | ||
const _this6 = this; | ||
const overrides = { | ||
gasLimit: 123456, | ||
gasPrice: 1000000000, | ||
...options | ||
}; | ||
return Promise.resolve(_this6.attachContract(overrides.from)).then(function (contract) { | ||
delete overrides.from; | ||
const delegateTypeBytes = stringToBytes32(delegateType); | ||
return Promise.resolve(contract.functions.addDelegate(_this4.address, delegateTypeBytes, delegateAddress, exp, overrides)).then(function (addDelegateTx) { | ||
return Promise.resolve(contract.functions.addDelegate(_this6.address, delegateTypeBytes, delegateAddress, exp, overrides)).then(function (addDelegateTx) { | ||
addDelegateTx; | ||
@@ -350,5 +866,40 @@ return Promise.resolve(addDelegateTx.wait()); | ||
createAddDelegateHash(delegateType, delegateAddress, exp) { | ||
try { | ||
const _this7 = this; | ||
return Promise.resolve(_this7.getPaddedNonceCompatability()).then(function (paddedNonce) { | ||
const dataToHash = hexConcat([MESSAGE_PREFIX, _this7.contract.address, paddedNonce, _this7.address, concat([toUtf8Bytes('addDelegate'), formatBytes32String(delegateType), delegateAddress, zeroPad(hexlify(exp), 32)])]); | ||
return keccak256(dataToHash); | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
addDelegateSigned(delegateType, delegateAddress, exp, metaSignature, options = {}) { | ||
try { | ||
const _this8 = this; | ||
const overrides = { | ||
gasLimit: 123456, | ||
gasPrice: 1000000000, | ||
...options | ||
}; | ||
return Promise.resolve(_this8.attachContract(overrides.from)).then(function (contract) { | ||
delete overrides.from; | ||
const delegateTypeBytes = stringToBytes32(delegateType); | ||
return Promise.resolve(contract.functions.addDelegateSigned(_this8.address, metaSignature.sigV, metaSignature.sigR, metaSignature.sigS, delegateTypeBytes, delegateAddress, exp, overrides)).then(function (addDelegateTx) { | ||
addDelegateTx; | ||
return Promise.resolve(addDelegateTx.wait()); | ||
}); | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
revokeDelegate(delegateType, delegateAddress, options = {}) { | ||
try { | ||
const _this5 = this; | ||
const _this9 = this; | ||
@@ -361,5 +912,5 @@ const overrides = { | ||
delegateType = delegateType.startsWith('0x') ? delegateType : stringToBytes32(delegateType); | ||
return Promise.resolve(_this5.attachContract(overrides.from)).then(function (contract) { | ||
return Promise.resolve(_this9.attachContract(overrides.from)).then(function (contract) { | ||
delete overrides.from; | ||
return Promise.resolve(contract.functions.revokeDelegate(_this5.address, delegateType, delegateAddress, overrides)).then(function (addDelegateTx) { | ||
return Promise.resolve(contract.functions.revokeDelegate(_this9.address, delegateType, delegateAddress, overrides)).then(function (addDelegateTx) { | ||
return Promise.resolve(addDelegateTx.wait()); | ||
@@ -373,5 +924,39 @@ }); | ||
createRevokeDelegateHash(delegateType, delegateAddress) { | ||
try { | ||
const _this10 = this; | ||
return Promise.resolve(_this10.getPaddedNonceCompatability()).then(function (paddedNonce) { | ||
const dataToHash = hexConcat([MESSAGE_PREFIX, _this10.contract.address, paddedNonce, _this10.address, concat([toUtf8Bytes('revokeDelegate'), formatBytes32String(delegateType), delegateAddress])]); | ||
return keccak256(dataToHash); | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
revokeDelegateSigned(delegateType, delegateAddress, metaSignature, options = {}) { | ||
try { | ||
const _this11 = this; | ||
const overrides = { | ||
gasLimit: 123456, | ||
gasPrice: 1000000000, | ||
...options | ||
}; | ||
delegateType = delegateType.startsWith('0x') ? delegateType : stringToBytes32(delegateType); | ||
return Promise.resolve(_this11.attachContract(overrides.from)).then(function (contract) { | ||
delete overrides.from; | ||
return Promise.resolve(contract.functions.revokeDelegateSigned(_this11.address, metaSignature.sigV, metaSignature.sigR, metaSignature.sigS, delegateType, delegateAddress, overrides)).then(function (addDelegateTx) { | ||
return Promise.resolve(addDelegateTx.wait()); | ||
}); | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
setAttribute(attrName, attrValue, exp, options = {}) { | ||
try { | ||
const _this6 = this; | ||
const _this12 = this; | ||
@@ -386,5 +971,5 @@ const overrides = { | ||
attrValue = attrValue.startsWith('0x') ? attrValue : '0x' + Buffer.from(attrValue, 'utf-8').toString('hex'); | ||
return Promise.resolve(_this6.attachContract(overrides.from)).then(function (contract) { | ||
return Promise.resolve(_this12.attachContract(overrides.from)).then(function (contract) { | ||
delete overrides.from; | ||
return Promise.resolve(contract.functions.setAttribute(_this6.address, attrName, attrValue, exp, overrides)).then(function (setAttrTx) { | ||
return Promise.resolve(contract.functions.setAttribute(_this12.address, attrName, attrValue, exp, overrides)).then(function (setAttrTx) { | ||
return Promise.resolve(setAttrTx.wait()); | ||
@@ -398,5 +983,41 @@ }); | ||
createSetAttributeHash(attrName, attrValue, exp) { | ||
try { | ||
const _this13 = this; | ||
return Promise.resolve(_this13.getPaddedNonce()).then(function (paddedNonce) { | ||
const dataToHash = hexConcat([MESSAGE_PREFIX, _this13.contract.address, paddedNonce, _this13.address, concat([toUtf8Bytes('setAttribute'), formatBytes32String(attrName), toUtf8Bytes(attrValue), zeroPad(hexlify(exp), 32)])]); | ||
return keccak256(dataToHash); | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
setAttributeSigned(attrName, attrValue, exp, metaSignature, options = {}) { | ||
try { | ||
const _this14 = this; | ||
const overrides = { | ||
gasLimit: 123456, | ||
gasPrice: 1000000000, | ||
controller: undefined, | ||
...options | ||
}; | ||
attrName = attrName.startsWith('0x') ? attrName : stringToBytes32(attrName); | ||
attrValue = attrValue.startsWith('0x') ? attrValue : '0x' + Buffer.from(attrValue, 'utf-8').toString('hex'); | ||
return Promise.resolve(_this14.attachContract(overrides.from)).then(function (contract) { | ||
delete overrides.from; | ||
return Promise.resolve(contract.functions.setAttributeSigned(_this14.address, metaSignature.sigV, metaSignature.sigR, metaSignature.sigS, attrName, attrValue, exp, overrides)).then(function (setAttrTx) { | ||
return Promise.resolve(setAttrTx.wait()); | ||
}); | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
revokeAttribute(attrName, attrValue, options = {}) { | ||
try { | ||
const _this7 = this; | ||
const _this15 = this; | ||
@@ -411,5 +1032,5 @@ // console.log(`revoking attribute ${attrName}(${attrValue}) for ${identity}`) | ||
attrValue = attrValue.startsWith('0x') ? attrValue : '0x' + Buffer.from(attrValue, 'utf-8').toString('hex'); | ||
return Promise.resolve(_this7.attachContract(overrides.from)).then(function (contract) { | ||
return Promise.resolve(_this15.attachContract(overrides.from)).then(function (contract) { | ||
delete overrides.from; | ||
return Promise.resolve(contract.functions.revokeAttribute(_this7.address, attrName, attrValue, overrides)).then(function (revokeAttributeTX) { | ||
return Promise.resolve(contract.functions.revokeAttribute(_this15.address, attrName, attrValue, overrides)).then(function (revokeAttributeTX) { | ||
return Promise.resolve(revokeAttributeTX.wait()); | ||
@@ -423,2 +1044,80 @@ }); | ||
createRevokeAttributeHash(attrName, attrValue) { | ||
try { | ||
const _this16 = this; | ||
return Promise.resolve(_this16.getPaddedNonce()).then(function (paddedNonce) { | ||
const dataToHash = hexConcat([MESSAGE_PREFIX, _this16.contract.address, paddedNonce, _this16.address, concat([toUtf8Bytes('revokeAttribute'), formatBytes32String(attrName), toUtf8Bytes(attrValue)])]); | ||
return keccak256(dataToHash); | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
/* | ||
The current version of the ethr-did-registry contract tracks the nonce as a property | ||
of the original owner, and not as a property of the signer (current owner). | ||
That's why we need to differentiate between deployments here, or otherwise our signature will be | ||
computed wrong resulting in a failed TX | ||
*/ | ||
getPaddedNonceCompatability() { | ||
try { | ||
const _this17 = this; | ||
let nonce; | ||
if (_this17.legacyNonce) { | ||
return Promise.resolve(_this17.getOwner(_this17.address)).then(function (currentOwner) { | ||
return Promise.resolve(_this17.contract.nonce(currentOwner)).then(function (_this17$contract$nonc) { | ||
nonce = _this17$contract$nonc; | ||
return zeroPad(arrayify(nonce), 32); | ||
}); | ||
}); | ||
} else { | ||
return Promise.resolve(_this17.getPaddedNonce()); | ||
} | ||
return Promise.resolve(); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
getPaddedNonce() { | ||
try { | ||
const _this18 = this; | ||
return Promise.resolve(_this18.contract.nonce(_this18.address)).then(function (nonce) { | ||
return zeroPad(arrayify(nonce), 32); | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
revokeAttributeSigned(attrName, attrValue, metaSignature, options = {}) { | ||
try { | ||
const _this19 = this; | ||
// console.log(`revoking attribute ${attrName}(${attrValue}) for ${identity}`) | ||
const overrides = { | ||
gasLimit: 123456, | ||
gasPrice: 1000000000, | ||
...options | ||
}; | ||
attrName = attrName.startsWith('0x') ? attrName : stringToBytes32(attrName); | ||
attrValue = attrValue.startsWith('0x') ? attrValue : '0x' + Buffer.from(attrValue, 'utf-8').toString('hex'); | ||
return Promise.resolve(_this19.attachContract(overrides.from)).then(function (contract) { | ||
delete overrides.from; | ||
return Promise.resolve(contract.functions.revokeAttributeSigned(_this19.address, metaSignature.sigV, metaSignature.sigR, metaSignature.sigS, attrName, attrValue, overrides)).then(function (revokeAttributeTX) { | ||
return Promise.resolve(revokeAttributeTX.wait()); | ||
}); | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
} | ||
@@ -425,0 +1124,0 @@ |
{ | ||
"name": "ethr-did-resolver", | ||
"version": "6.1.0", | ||
"version": "6.2.0", | ||
"description": "Resolve DID documents for ethereum addresses and public keys", | ||
@@ -72,21 +72,22 @@ "type": "module", | ||
"devDependencies": { | ||
"@babel/core": "7.18.9", | ||
"@babel/preset-env": "7.18.9", | ||
"@babel/core": "7.18.13", | ||
"@babel/preset-env": "7.18.10", | ||
"@babel/preset-typescript": "7.18.6", | ||
"@ethersproject/strings": "^5.6.1", | ||
"@semantic-release/changelog": "6.0.1", | ||
"@semantic-release/git": "10.0.1", | ||
"@types/jest": "28.1.6", | ||
"@typescript-eslint/eslint-plugin": "5.30.7", | ||
"@typescript-eslint/parser": "5.30.7", | ||
"@types/jest": "28.1.8", | ||
"@typescript-eslint/eslint-plugin": "5.35.1", | ||
"@typescript-eslint/parser": "5.35.1", | ||
"babel-jest": "28.1.3", | ||
"eslint": "8.20.0", | ||
"eslint": "8.23.0", | ||
"eslint-config-prettier": "8.5.0", | ||
"eslint-plugin-jest": "26.6.0", | ||
"eslint-plugin-jest": "26.9.0", | ||
"eslint-plugin-prettier": "4.2.1", | ||
"ganache": "7.3.2", | ||
"ganache": "7.4.1", | ||
"jest": "28.1.3", | ||
"microbundle": "0.15.0", | ||
"microbundle": "0.15.1", | ||
"prettier": "2.7.1", | ||
"semantic-release": "19.0.3", | ||
"typescript": "4.7.4" | ||
"semantic-release": "19.0.5", | ||
"typescript": "4.8.2" | ||
}, | ||
@@ -99,4 +100,7 @@ "dependencies": { | ||
"@ethersproject/bignumber": "^5.6.2", | ||
"@ethersproject/bytes": "^5.6.1", | ||
"@ethersproject/contracts": "^5.6.2", | ||
"@ethersproject/keccak256": "^5.6.1", | ||
"@ethersproject/providers": "^5.6.8", | ||
"@ethersproject/signing-key": "^5.6.2", | ||
"@ethersproject/transactions": "^5.6.2", | ||
@@ -103,0 +107,0 @@ "did-resolver": "^4.0.0", |
@@ -5,3 +5,13 @@ import { Signer } from '@ethersproject/abstract-signer' | ||
import { getContractForNetwork } from './configuration' | ||
import { address, DEFAULT_REGISTRY_ADDRESS, interpretIdentifier, stringToBytes32 } from './helpers' | ||
import { | ||
address, | ||
DEFAULT_REGISTRY_ADDRESS, | ||
interpretIdentifier, | ||
MESSAGE_PREFIX, | ||
MetaSignature, | ||
stringToBytes32, | ||
} from './helpers' | ||
import { arrayify, concat, hexConcat, hexlify, zeroPad } from '@ethersproject/bytes' | ||
import { keccak256 } from '@ethersproject/keccak256' | ||
import { formatBytes32String, toUtf8Bytes } from '@ethersproject/strings' | ||
@@ -16,2 +26,3 @@ /** | ||
public did: string | ||
private legacyNonce: boolean | ||
@@ -28,2 +39,3 @@ /** | ||
* @param registry - optional - The ERC1056 registry address. Defaults to '0xdca7ef03e98e0dc2b855be647c39abe984fcf21b'. Only used with 'provider' or 'rpcUrl' | ||
* @param legacyNonce - optional - If the legacy nonce tracking method should be accounted for. If lesser version of did-ethr-registry contract v1.0.0 is used then this should be true. | ||
*/ | ||
@@ -37,4 +49,6 @@ constructor( | ||
rpcUrl?: string, | ||
registry: string = DEFAULT_REGISTRY_ADDRESS | ||
registry: string = DEFAULT_REGISTRY_ADDRESS, | ||
legacyNonce = true | ||
) { | ||
this.legacyNonce = legacyNonce | ||
// initialize identifier | ||
@@ -89,2 +103,40 @@ const { address, publicKey, network } = interpretIdentifier(identifier) | ||
async createChangeOwnerHash(newOwner: address) { | ||
const paddedNonce = await this.getPaddedNonceCompatability() | ||
const dataToHash = hexConcat([ | ||
MESSAGE_PREFIX, | ||
this.contract.address, | ||
paddedNonce, | ||
this.address, | ||
concat([toUtf8Bytes('changeOwner'), newOwner]), | ||
]) | ||
return keccak256(dataToHash) | ||
} | ||
async changeOwnerSigned( | ||
newOwner: address, | ||
metaSignature: MetaSignature, | ||
options: CallOverrides = {} | ||
): Promise<TransactionReceipt> { | ||
const overrides = { | ||
gasLimit: 123456, | ||
gasPrice: 1000000000, | ||
...options, | ||
} | ||
const contract = await this.attachContract(overrides.from) | ||
delete overrides.from | ||
const ownerChange = await contract.functions.changeOwnerSigned( | ||
this.address, | ||
metaSignature.sigV, | ||
metaSignature.sigR, | ||
metaSignature.sigS, | ||
newOwner, | ||
overrides | ||
) | ||
return await ownerChange.wait() | ||
} | ||
async addDelegate( | ||
@@ -116,2 +168,50 @@ delegateType: string, | ||
async createAddDelegateHash(delegateType: string, delegateAddress: address, exp: number) { | ||
const paddedNonce = await this.getPaddedNonceCompatability() | ||
const dataToHash = hexConcat([ | ||
MESSAGE_PREFIX, | ||
this.contract.address, | ||
paddedNonce, | ||
this.address, | ||
concat([ | ||
toUtf8Bytes('addDelegate'), | ||
formatBytes32String(delegateType), | ||
delegateAddress, | ||
zeroPad(hexlify(exp), 32), | ||
]), | ||
]) | ||
return keccak256(dataToHash) | ||
} | ||
async addDelegateSigned( | ||
delegateType: string, | ||
delegateAddress: address, | ||
exp: number, | ||
metaSignature: MetaSignature, | ||
options: CallOverrides = {} | ||
): Promise<TransactionReceipt> { | ||
const overrides = { | ||
gasLimit: 123456, | ||
gasPrice: 1000000000, | ||
...options, | ||
} | ||
const contract = await this.attachContract(overrides.from) | ||
delete overrides.from | ||
const delegateTypeBytes = stringToBytes32(delegateType) | ||
const addDelegateTx = await contract.functions.addDelegateSigned( | ||
this.address, | ||
metaSignature.sigV, | ||
metaSignature.sigR, | ||
metaSignature.sigS, | ||
delegateTypeBytes, | ||
delegateAddress, | ||
exp, | ||
overrides | ||
) | ||
addDelegateTx | ||
return await addDelegateTx.wait() | ||
} | ||
async revokeDelegate( | ||
@@ -139,2 +239,41 @@ delegateType: string, | ||
async createRevokeDelegateHash(delegateType: string, delegateAddress: address) { | ||
const paddedNonce = await this.getPaddedNonceCompatability() | ||
const dataToHash = hexConcat([ | ||
MESSAGE_PREFIX, | ||
this.contract.address, | ||
paddedNonce, | ||
this.address, | ||
concat([toUtf8Bytes('revokeDelegate'), formatBytes32String(delegateType), delegateAddress]), | ||
]) | ||
return keccak256(dataToHash) | ||
} | ||
async revokeDelegateSigned( | ||
delegateType: string, | ||
delegateAddress: address, | ||
metaSignature: MetaSignature, | ||
options: CallOverrides = {} | ||
): Promise<TransactionReceipt> { | ||
const overrides = { | ||
gasLimit: 123456, | ||
gasPrice: 1000000000, | ||
...options, | ||
} | ||
delegateType = delegateType.startsWith('0x') ? delegateType : stringToBytes32(delegateType) | ||
const contract = await this.attachContract(overrides.from) | ||
delete overrides.from | ||
const addDelegateTx = await contract.functions.revokeDelegateSigned( | ||
this.address, | ||
metaSignature.sigV, | ||
metaSignature.sigR, | ||
metaSignature.sigS, | ||
delegateType, | ||
delegateAddress, | ||
overrides | ||
) | ||
return await addDelegateTx.wait() | ||
} | ||
async setAttribute( | ||
@@ -160,2 +299,50 @@ attrName: string, | ||
async createSetAttributeHash(attrName: string, attrValue: string, exp: number) { | ||
const paddedNonce = await this.getPaddedNonce() | ||
const dataToHash = hexConcat([ | ||
MESSAGE_PREFIX, | ||
this.contract.address, | ||
paddedNonce, | ||
this.address, | ||
concat([ | ||
toUtf8Bytes('setAttribute'), | ||
formatBytes32String(attrName), | ||
toUtf8Bytes(attrValue), | ||
zeroPad(hexlify(exp), 32), | ||
]), | ||
]) | ||
return keccak256(dataToHash) | ||
} | ||
async setAttributeSigned( | ||
attrName: string, | ||
attrValue: string, | ||
exp: number, | ||
metaSignature: MetaSignature, | ||
options: CallOverrides = {} | ||
): Promise<TransactionReceipt> { | ||
const overrides = { | ||
gasLimit: 123456, | ||
gasPrice: 1000000000, | ||
controller: undefined, | ||
...options, | ||
} | ||
attrName = attrName.startsWith('0x') ? attrName : stringToBytes32(attrName) | ||
attrValue = attrValue.startsWith('0x') ? attrValue : '0x' + Buffer.from(attrValue, 'utf-8').toString('hex') | ||
const contract = await this.attachContract(overrides.from) | ||
delete overrides.from | ||
const setAttrTx = await contract.functions.setAttributeSigned( | ||
this.address, | ||
metaSignature.sigV, | ||
metaSignature.sigR, | ||
metaSignature.sigS, | ||
attrName, | ||
attrValue, | ||
exp, | ||
overrides | ||
) | ||
return await setAttrTx.wait() | ||
} | ||
async revokeAttribute(attrName: string, attrValue: string, options: CallOverrides = {}): Promise<TransactionReceipt> { | ||
@@ -175,2 +362,65 @@ // console.log(`revoking attribute ${attrName}(${attrValue}) for ${identity}`) | ||
} | ||
async createRevokeAttributeHash(attrName: string, attrValue: string) { | ||
const paddedNonce = await this.getPaddedNonce() | ||
const dataToHash = hexConcat([ | ||
MESSAGE_PREFIX, | ||
this.contract.address, | ||
paddedNonce, | ||
this.address, | ||
concat([toUtf8Bytes('revokeAttribute'), formatBytes32String(attrName), toUtf8Bytes(attrValue)]), | ||
]) | ||
return keccak256(dataToHash) | ||
} | ||
/* | ||
The current version of the ethr-did-registry contract tracks the nonce as a property | ||
of the original owner, and not as a property of the signer (current owner). | ||
That's why we need to differentiate between deployments here, or otherwise our signature will be | ||
computed wrong resulting in a failed TX | ||
*/ | ||
private async getPaddedNonceCompatability() { | ||
let nonce | ||
if (this.legacyNonce) { | ||
const currentOwner = await this.getOwner(this.address) | ||
nonce = await this.contract.nonce(currentOwner) | ||
return zeroPad(arrayify(nonce), 32) | ||
} else { | ||
return this.getPaddedNonce() | ||
} | ||
} | ||
private async getPaddedNonce() { | ||
const nonce = await this.contract.nonce(this.address) | ||
return zeroPad(arrayify(nonce), 32) | ||
} | ||
async revokeAttributeSigned( | ||
attrName: string, | ||
attrValue: string, | ||
metaSignature: MetaSignature, | ||
options: CallOverrides = {} | ||
): Promise<TransactionReceipt> { | ||
// console.log(`revoking attribute ${attrName}(${attrValue}) for ${identity}`) | ||
const overrides = { | ||
gasLimit: 123456, | ||
gasPrice: 1000000000, | ||
...options, | ||
} | ||
attrName = attrName.startsWith('0x') ? attrName : stringToBytes32(attrName) | ||
attrValue = attrValue.startsWith('0x') ? attrValue : '0x' + Buffer.from(attrValue, 'utf-8').toString('hex') | ||
const contract = await this.attachContract(overrides.from) | ||
delete overrides.from | ||
const revokeAttributeTX = await contract.functions.revokeAttributeSigned( | ||
this.address, | ||
metaSignature.sigV, | ||
metaSignature.sigR, | ||
metaSignature.sigS, | ||
attrName, | ||
attrValue, | ||
overrides | ||
) | ||
return await revokeAttributeTX.wait() | ||
} | ||
} |
@@ -5,2 +5,6 @@ import { getAddress } from '@ethersproject/address' | ||
import { VerificationMethod } from 'did-resolver' | ||
import { Contract } from '@ethersproject/contracts' | ||
import { keccak256 } from '@ethersproject/keccak256' | ||
import { arrayify, hexConcat, zeroPad } from '@ethersproject/bytes' | ||
import { SigningKey } from '@ethersproject/signing-key' | ||
@@ -11,2 +15,3 @@ export const identifierMatcher = /^(.*)?(0x[0-9a-fA-F]{40}|0x[0-9a-fA-F]{66})$/ | ||
export const DEFAULT_JSON_RPC = 'http://127.0.0.1:8545/' | ||
export const MESSAGE_PREFIX = '0x1900' | ||
@@ -67,2 +72,9 @@ export type address = string | ||
// Interface for transporting v, r, s signature parameters used in meta transactions | ||
export interface MetaSignature { | ||
sigV: number | ||
sigR: bytes32 | ||
sigS: bytes32 | ||
} | ||
export const legacyAttrTypes: Record<string, string> = { | ||
@@ -119,2 +131,16 @@ sigAuth: 'SignatureAuthentication2018', | ||
export async function signMetaTxData( | ||
identity: string, | ||
signerAddress: string, | ||
privateKeyBytes: Uint8Array, | ||
dataBytes: Uint8Array, | ||
didReg: Contract | ||
) { | ||
const nonce = await didReg.nonce(signerAddress) | ||
const paddedNonce = zeroPad(arrayify(nonce), 32) | ||
const dataToSign = hexConcat(['0x1900', didReg.address, paddedNonce, identity, dataBytes]) | ||
const hash = keccak256(dataToSign) | ||
return new SigningKey(privateKeyBytes).signDigest(hash) | ||
} | ||
export enum Errors { | ||
@@ -121,0 +147,0 @@ /** |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1592612
28627
13
20
1