Socket
Socket
Sign inDemoInstall

@ethersproject/hash

Package Overview
Dependencies
9
Maintainers
1
Versions
46
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 5.6.0 to 6.0.0-beta.1

lib/logger.d.ts

2

lib/_version.d.ts

@@ -1,2 +0,2 @@

export declare const version = "hash/5.6.0";
export declare const version = "@ethersproject/hash@6.0.0-beta.1";
//# sourceMappingURL=_version.d.ts.map

@@ -1,5 +0,2 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.version = void 0;
exports.version = "hash/5.6.0";
export const version = "@ethersproject/hash@6.0.0-beta.1";
//# sourceMappingURL=_version.js.map

@@ -1,2 +0,2 @@

export declare function id(text: string): string;
export declare function id(value: string): string;
//# sourceMappingURL=id.d.ts.map

@@ -1,10 +0,6 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.id = void 0;
var keccak256_1 = require("@ethersproject/keccak256");
var strings_1 = require("@ethersproject/strings");
function id(text) {
return (0, keccak256_1.keccak256)((0, strings_1.toUtf8Bytes)(text));
import { keccak256 } from "@ethersproject/crypto";
import { toUtf8Bytes } from "@ethersproject/strings";
export function id(value) {
return keccak256(toUtf8Bytes(value));
}
exports.id = id;
//# sourceMappingURL=id.js.map

@@ -1,6 +0,6 @@

import { id } from "./id";
import { dnsEncode, isValidName, namehash } from "./namehash";
import { hashMessage, messagePrefix } from "./message";
import { TypedDataEncoder as _TypedDataEncoder } from "./typed-data";
export { id, dnsEncode, namehash, isValidName, messagePrefix, hashMessage, _TypedDataEncoder, };
export { id } from "./id.js";
export { isValidName, namehash, dnsEncode } from "./namehash.js";
export { messagePrefix, hashMessage } from "./message.js";
export { TypedDataEncoder } from "./typed-data.js";
export type { TypedDataDomain, TypedDataField } from "./typed-data.js";
//# sourceMappingURL=index.d.ts.map

@@ -1,15 +0,5 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports._TypedDataEncoder = exports.hashMessage = exports.messagePrefix = exports.isValidName = exports.namehash = exports.dnsEncode = exports.id = void 0;
var id_1 = require("./id");
Object.defineProperty(exports, "id", { enumerable: true, get: function () { return id_1.id; } });
var namehash_1 = require("./namehash");
Object.defineProperty(exports, "dnsEncode", { enumerable: true, get: function () { return namehash_1.dnsEncode; } });
Object.defineProperty(exports, "isValidName", { enumerable: true, get: function () { return namehash_1.isValidName; } });
Object.defineProperty(exports, "namehash", { enumerable: true, get: function () { return namehash_1.namehash; } });
var message_1 = require("./message");
Object.defineProperty(exports, "hashMessage", { enumerable: true, get: function () { return message_1.hashMessage; } });
Object.defineProperty(exports, "messagePrefix", { enumerable: true, get: function () { return message_1.messagePrefix; } });
var typed_data_1 = require("./typed-data");
Object.defineProperty(exports, "_TypedDataEncoder", { enumerable: true, get: function () { return typed_data_1.TypedDataEncoder; } });
export { id } from "./id.js";
export { isValidName, namehash, dnsEncode } from "./namehash.js";
export { messagePrefix, hashMessage } from "./message.js";
export { TypedDataEncoder } from "./typed-data.js";
//# sourceMappingURL=index.js.map

@@ -1,4 +0,3 @@

import { Bytes } from "@ethersproject/bytes";
export declare const messagePrefix = "\u0019Ethereum Signed Message:\n";
export declare function hashMessage(message: Bytes | string): string;
export declare function hashMessage(message: Uint8Array | string): string;
//# sourceMappingURL=message.d.ts.map

@@ -1,19 +0,15 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hashMessage = exports.messagePrefix = void 0;
var bytes_1 = require("@ethersproject/bytes");
var keccak256_1 = require("@ethersproject/keccak256");
var strings_1 = require("@ethersproject/strings");
exports.messagePrefix = "\x19Ethereum Signed Message:\n";
function hashMessage(message) {
import { concat } from "@ethersproject/bytes";
import { keccak256 } from "@ethersproject/crypto";
import { toUtf8Bytes } from "@ethersproject/strings";
export const messagePrefix = "\x19Ethereum Signed Message:\n";
export function hashMessage(message) {
if (typeof (message) === "string") {
message = (0, strings_1.toUtf8Bytes)(message);
message = toUtf8Bytes(message);
}
return (0, keccak256_1.keccak256)((0, bytes_1.concat)([
(0, strings_1.toUtf8Bytes)(exports.messagePrefix),
(0, strings_1.toUtf8Bytes)(String(message.length)),
return keccak256(concat([
toUtf8Bytes(messagePrefix),
toUtf8Bytes(String(message.length)),
message
]));
}
exports.hashMessage = hashMessage;
//# sourceMappingURL=message.js.map

@@ -1,18 +0,13 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.dnsEncode = exports.namehash = exports.isValidName = void 0;
var bytes_1 = require("@ethersproject/bytes");
var strings_1 = require("@ethersproject/strings");
var keccak256_1 = require("@ethersproject/keccak256");
var logger_1 = require("@ethersproject/logger");
var _version_1 = require("./_version");
var logger = new logger_1.Logger(_version_1.version);
var Zeros = new Uint8Array(32);
import { concat, hexlify } from "@ethersproject/bytes";
import { keccak256 } from "@ethersproject/crypto";
import { nameprep, toUtf8Bytes } from "@ethersproject/strings";
import { logger } from "./logger.js";
const Zeros = new Uint8Array(32);
Zeros.fill(0);
var Partition = new RegExp("^((.*)\\.)?([^.]+)$");
function isValidName(name) {
const Partition = new RegExp("^((.*)\\.)?([^.]+)$");
export function isValidName(name) {
try {
var comps = name.split(".");
for (var i = 0; i < comps.length; i++) {
if ((0, strings_1.nameprep)(comps[i]).length === 0) {
const comps = name.split(".");
for (let i = 0; i < comps.length; i++) {
if (nameprep(comps[i]).length === 0) {
throw new Error("empty");

@@ -26,32 +21,38 @@ }

}
exports.isValidName = isValidName;
function namehash(name) {
/* istanbul ignore if */
export function namehash(name) {
if (typeof (name) !== "string") {
logger.throwArgumentError("invalid ENS name; not a string", "name", name);
}
var current = name;
var result = Zeros;
let current = name;
let result = Zeros;
while (current.length) {
var partition = current.match(Partition);
const partition = current.match(Partition);
if (partition == null || partition[2] === "") {
logger.throwArgumentError("invalid ENS address; missing component", "name", name);
return logger.throwArgumentError("invalid ENS name; missing component", "name", name);
}
var label = (0, strings_1.toUtf8Bytes)((0, strings_1.nameprep)(partition[3]));
result = (0, keccak256_1.keccak256)((0, bytes_1.concat)([result, (0, keccak256_1.keccak256)(label)]));
const label = toUtf8Bytes(nameprep(partition[3]));
result = keccak256(concat([result, keccak256(label)]));
current = partition[2] || "";
}
return (0, bytes_1.hexlify)(result);
return hexlify(result);
}
exports.namehash = namehash;
function dnsEncode(name) {
return (0, bytes_1.hexlify)((0, bytes_1.concat)(name.split(".").map(function (comp) {
export function dnsEncode(name) {
if (typeof (name) !== "string") {
logger.throwArgumentError("invalid DNS name; not a string", "name", name);
}
if (name === "") {
return "0x00";
}
// @TODO: should we enforce the 255 octet limit?
return concat(name.split(".").map((comp) => {
if (comp === "") {
logger.throwArgumentError("invalid DNS name; missing component", "name", name);
}
// We jam in an _ prefix to fill in with the length later
// Note: Nameprep throws if the component is over 63 bytes
var bytes = (0, strings_1.toUtf8Bytes)("_" + (0, strings_1.nameprep)(comp));
const bytes = toUtf8Bytes("_" + nameprep(comp));
bytes[0] = bytes.length - 1;
return bytes;
}))) + "00";
})) + "00";
}
exports.dnsEncode = dnsEncode;
//# sourceMappingURL=namehash.js.map

@@ -1,10 +0,19 @@

import { TypedDataDomain, TypedDataField } from "@ethersproject/abstract-signer";
import type { BigNumberish, BytesLike } from "@ethersproject/logger";
export interface TypedDataDomain {
name?: string;
version?: string;
chainId?: BigNumberish;
verifyingContract?: string;
salt?: BytesLike;
}
export interface TypedDataField {
name: string;
type: string;
}
export declare class TypedDataEncoder {
#private;
readonly primaryType: string;
readonly types: Record<string, Array<TypedDataField>>;
readonly _encoderCache: Record<string, (value: any) => string>;
readonly _types: Record<string, string>;
get types(): Record<string, Array<TypedDataField>>;
constructor(types: Record<string, Array<TypedDataField>>);
getEncoder(type: string): (value: any) => string;
_getEncoder(type: string): (value: any) => string;
encodeType(name: string): string;

@@ -11,0 +20,0 @@ encodeData(type: string, value: any): string;

@@ -1,66 +0,40 @@

"use strict";
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());
});
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypedDataEncoder = void 0;
var address_1 = require("@ethersproject/address");
var bignumber_1 = require("@ethersproject/bignumber");
var bytes_1 = require("@ethersproject/bytes");
var keccak256_1 = require("@ethersproject/keccak256");
var properties_1 = require("@ethersproject/properties");
var logger_1 = require("@ethersproject/logger");
var _version_1 = require("./_version");
var logger = new logger_1.Logger(_version_1.version);
var id_1 = require("./id");
var padding = new Uint8Array(32);
var _TypedDataEncoder_instances, _TypedDataEncoder_types, _TypedDataEncoder_fullTypes, _TypedDataEncoder_encoderCache, _TypedDataEncoder_getEncoder;
//import { TypedDataDomain, TypedDataField } from "@ethersproject/providerabstract-signer";
import { getAddress } from "@ethersproject/address";
import { arrayify, concat, hexlify, zeroPadLeft, isHexString } from "@ethersproject/bytes";
import { keccak256 } from "@ethersproject/crypto";
import { defineProperties } from "@ethersproject/properties";
import { mask, toHex, toTwos } from "@ethersproject/math";
import { id } from "./id.js";
import { logger } from "./logger.js";
const padding = new Uint8Array(32);
padding.fill(0);
var NegativeOne = bignumber_1.BigNumber.from(-1);
var Zero = bignumber_1.BigNumber.from(0);
var One = bignumber_1.BigNumber.from(1);
var MaxUint256 = bignumber_1.BigNumber.from("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
const BN__1 = BigInt(-1);
const BN_0 = BigInt(0);
const BN_1 = BigInt(1);
const BN_MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
;
;
function hexPadRight(value) {
var bytes = (0, bytes_1.arrayify)(value);
var padOffset = bytes.length % 32;
const bytes = arrayify(value);
const padOffset = bytes.length % 32;
if (padOffset) {
return (0, bytes_1.hexConcat)([bytes, padding.slice(padOffset)]);
return concat([bytes, padding.slice(padOffset)]);
}
return (0, bytes_1.hexlify)(bytes);
return hexlify(bytes);
}
var hexTrue = (0, bytes_1.hexZeroPad)(One.toHexString(), 32);
var hexFalse = (0, bytes_1.hexZeroPad)(Zero.toHexString(), 32);
var domainFieldTypes = {
const hexTrue = toHex(BN_1, 32);
const hexFalse = toHex(BN_0, 32);
const domainFieldTypes = {
name: "string",

@@ -72,3 +46,3 @@ version: "string",

};
var domainFieldNames = [
const domainFieldNames = [
"name", "version", "chainId", "verifyingContract", "salt"

@@ -79,3 +53,3 @@ ];

if (typeof (value) !== "string") {
logger.throwArgumentError("invalid domain value for " + JSON.stringify(key), "domain." + key, value);
logger.throwArgumentError(`invalid domain value for ${JSON.stringify(key)}`, `domain.${key}`, value);
}

@@ -85,29 +59,21 @@ return value;

}
var domainChecks = {
const domainChecks = {
name: checkString("name"),
version: checkString("version"),
chainId: function (value) {
try {
return bignumber_1.BigNumber.from(value).toString();
}
catch (error) { }
return logger.throwArgumentError("invalid domain value for \"chainId\"", "domain.chainId", value);
return logger.getBigInt(value, "domain.chainId");
},
verifyingContract: function (value) {
try {
return (0, address_1.getAddress)(value).toLowerCase();
return getAddress(value).toLowerCase();
}
catch (error) { }
return logger.throwArgumentError("invalid domain value \"verifyingContract\"", "domain.verifyingContract", value);
return logger.throwArgumentError(`invalid domain value "verifyingContract"`, "domain.verifyingContract", value);
},
salt: function (value) {
try {
var bytes = (0, bytes_1.arrayify)(value);
if (bytes.length !== 32) {
throw new Error("bad length");
}
return (0, bytes_1.hexlify)(bytes);
const bytes = logger.getBytes(value, "domain.salt");
if (bytes.length !== 32) {
logger.throwArgumentError(`invalid domain value "salt"`, "domain.salt", value);
}
catch (error) { }
return logger.throwArgumentError("invalid domain value \"salt\"", "domain.salt", value);
return hexlify(bytes);
}

@@ -118,17 +84,17 @@ };

{
var match = type.match(/^(u?)int(\d*)$/);
const match = type.match(/^(u?)int(\d*)$/);
if (match) {
var signed = (match[1] === "");
var width = parseInt(match[2] || "256");
const signed = (match[1] === "");
const width = parseInt(match[2] || "256");
if (width % 8 !== 0 || width > 256 || (match[2] && match[2] !== String(width))) {
logger.throwArgumentError("invalid numeric width", "type", type);
}
var boundsUpper_1 = MaxUint256.mask(signed ? (width - 1) : width);
var boundsLower_1 = signed ? boundsUpper_1.add(One).mul(NegativeOne) : Zero;
return function (value) {
var v = bignumber_1.BigNumber.from(value);
if (v.lt(boundsLower_1) || v.gt(boundsUpper_1)) {
logger.throwArgumentError("value out-of-bounds for " + type, "value", value);
const boundsUpper = mask(BN_MAX_UINT256, signed ? (width - 1) : width);
const boundsLower = signed ? ((boundsUpper + BN_1) * BN__1) : BN_0;
return function (_value) {
const value = logger.getBigInt(_value, "value");
if (value < boundsLower || value > boundsUpper) {
logger.throwArgumentError(`value out-of-bounds for ${type}`, "value", value);
}
return (0, bytes_1.hexZeroPad)(v.toTwos(256).toHexString(), 32);
return toHex(toTwos(value, 256), 32);
};

@@ -139,12 +105,12 @@ }

{
var match = type.match(/^bytes(\d+)$/);
const match = type.match(/^bytes(\d+)$/);
if (match) {
var width_1 = parseInt(match[1]);
if (width_1 === 0 || width_1 > 32 || match[1] !== String(width_1)) {
const width = parseInt(match[1]);
if (width === 0 || width > 32 || match[1] !== String(width)) {
logger.throwArgumentError("invalid bytes width", "type", type);
}
return function (value) {
var bytes = (0, bytes_1.arrayify)(value);
if (bytes.length !== width_1) {
logger.throwArgumentError("invalid length for " + type, "value", value);
const bytes = arrayify(value);
if (bytes.length !== width) {
logger.throwArgumentError(`invalid length for ${type}`, "value", value);
}

@@ -157,3 +123,3 @@ return hexPadRight(value);

case "address": return function (value) {
return (0, bytes_1.hexZeroPad)((0, address_1.getAddress)(value), 32);
return zeroPadLeft(getAddress(value), 32);
};

@@ -164,6 +130,6 @@ case "bool": return function (value) {

case "bytes": return function (value) {
return (0, keccak256_1.keccak256)(value);
return keccak256(value);
};
case "string": return function (value) {
return (0, id_1.id)(value);
return id(value);
};

@@ -174,54 +140,52 @@ }

function encodeType(name, fields) {
return name + "(" + fields.map(function (_a) {
var name = _a.name, type = _a.type;
return (type + " " + name);
}).join(",") + ")";
return `${name}(${fields.map(({ name, type }) => (type + " " + name)).join(",")})`;
}
var TypedDataEncoder = /** @class */ (function () {
function TypedDataEncoder(types) {
(0, properties_1.defineReadOnly)(this, "types", Object.freeze((0, properties_1.deepCopy)(types)));
(0, properties_1.defineReadOnly)(this, "_encoderCache", {});
(0, properties_1.defineReadOnly)(this, "_types", {});
export class TypedDataEncoder {
constructor(types) {
_TypedDataEncoder_instances.add(this);
_TypedDataEncoder_types.set(this, void 0);
_TypedDataEncoder_fullTypes.set(this, void 0);
_TypedDataEncoder_encoderCache.set(this, void 0);
__classPrivateFieldSet(this, _TypedDataEncoder_types, JSON.stringify(types), "f");
__classPrivateFieldSet(this, _TypedDataEncoder_fullTypes, new Map(), "f");
__classPrivateFieldSet(this, _TypedDataEncoder_encoderCache, new Map(), "f");
// Link struct types to their direct child structs
var links = {};
const links = new Map();
// Link structs to structs which contain them as a child
var parents = {};
const parents = new Map();
// Link all subtypes within a given struct
var subtypes = {};
Object.keys(types).forEach(function (type) {
links[type] = {};
parents[type] = [];
subtypes[type] = {};
const subtypes = new Map();
Object.keys(types).forEach((type) => {
links.set(type, new Set());
parents.set(type, []);
subtypes.set(type, new Set());
});
var _loop_1 = function (name_1) {
var uniqueNames = {};
types[name_1].forEach(function (field) {
for (const name in types) {
const uniqueNames = new Set();
for (const field of types[name]) {
// Check each field has a unique name
if (uniqueNames[field.name]) {
logger.throwArgumentError("duplicate variable name " + JSON.stringify(field.name) + " in " + JSON.stringify(name_1), "types", types);
if (uniqueNames.has(field.name)) {
logger.throwArgumentError(`duplicate variable name ${JSON.stringify(field.name)} in ${JSON.stringify(name)}`, "types", types);
}
uniqueNames[field.name] = true;
uniqueNames.add(field.name);
// Get the base type (drop any array specifiers)
var baseType = field.type.match(/^([^\x5b]*)(\x5b|$)/)[1];
if (baseType === name_1) {
logger.throwArgumentError("circular type reference to " + JSON.stringify(baseType), "types", types);
const baseType = (field.type.match(/^([^\x5b]*)(\x5b|$)/))[1] || null;
if (baseType === name) {
logger.throwArgumentError(`circular type reference to ${JSON.stringify(baseType)}`, "types", types);
}
// Is this a base encoding type?
var encoder = getBaseEncoder(baseType);
const encoder = getBaseEncoder(baseType);
if (encoder) {
return;
continue;
}
if (!parents[baseType]) {
logger.throwArgumentError("unknown type " + JSON.stringify(baseType), "types", types);
if (!parents.has(baseType)) {
logger.throwArgumentError(`unknown type ${JSON.stringify(baseType)}`, "types", types);
}
// Add linkage
parents[baseType].push(name_1);
links[name_1][baseType] = true;
});
};
for (var name_1 in types) {
_loop_1(name_1);
parents.get(baseType).push(name);
links.get(name).add(baseType);
}
}
// Deduce the primary type
var primaryTypes = Object.keys(parents).filter(function (n) { return (parents[n].length === 0); });
const primaryTypes = Array.from(parents.keys()).filter((n) => (parents.get(n).length === 0));
if (primaryTypes.length === 0) {

@@ -231,14 +195,14 @@ logger.throwArgumentError("missing primary type", "types", types);

else if (primaryTypes.length > 1) {
logger.throwArgumentError("ambiguous primary types or unused types: " + primaryTypes.map(function (t) { return (JSON.stringify(t)); }).join(", "), "types", types);
logger.throwArgumentError(`ambiguous primary types or unused types: ${primaryTypes.map((t) => (JSON.stringify(t))).join(", ")}`, "types", types);
}
(0, properties_1.defineReadOnly)(this, "primaryType", primaryTypes[0]);
defineProperties(this, { primaryType: primaryTypes[0] });
// Check for circular type references
function checkCircular(type, found) {
if (found[type]) {
logger.throwArgumentError("circular type reference to " + JSON.stringify(type), "types", types);
if (found.has(type)) {
logger.throwArgumentError(`circular type reference to ${JSON.stringify(type)}`, "types", types);
}
found[type] = true;
Object.keys(links[type]).forEach(function (child) {
if (!parents[child]) {
return;
found.add(type);
for (const child of links.get(type)) {
if (!parents.has(child)) {
continue;
}

@@ -248,92 +212,50 @@ // Recursively check children

// Mark all ancestors as having this decendant
Object.keys(found).forEach(function (subtype) {
subtypes[subtype][child] = true;
});
});
delete found[type];
for (const subtype of found) {
subtypes.get(subtype).add(child);
}
}
found.delete(type);
}
checkCircular(this.primaryType, {});
checkCircular(this.primaryType, new Set());
// Compute each fully describe type
for (var name_2 in subtypes) {
var st = Object.keys(subtypes[name_2]);
for (const [name, set] of subtypes) {
const st = Array.from(set);
st.sort();
this._types[name_2] = encodeType(name_2, types[name_2]) + st.map(function (t) { return encodeType(t, types[t]); }).join("");
__classPrivateFieldGet(this, _TypedDataEncoder_fullTypes, "f").set(name, encodeType(name, types[name]) + st.map((t) => encodeType(t, types[t])).join(""));
}
}
TypedDataEncoder.prototype.getEncoder = function (type) {
var encoder = this._encoderCache[type];
get types() {
return JSON.parse(__classPrivateFieldGet(this, _TypedDataEncoder_types, "f"));
}
getEncoder(type) {
let encoder = __classPrivateFieldGet(this, _TypedDataEncoder_encoderCache, "f").get(type);
if (!encoder) {
encoder = this._encoderCache[type] = this._getEncoder(type);
encoder = __classPrivateFieldGet(this, _TypedDataEncoder_instances, "m", _TypedDataEncoder_getEncoder).call(this, type);
__classPrivateFieldGet(this, _TypedDataEncoder_encoderCache, "f").set(type, encoder);
}
return encoder;
};
TypedDataEncoder.prototype._getEncoder = function (type) {
var _this = this;
// Basic encoder type (address, bool, uint256, etc)
{
var encoder = getBaseEncoder(type);
if (encoder) {
return encoder;
}
}
// Array
var match = type.match(/^(.*)(\x5b(\d*)\x5d)$/);
if (match) {
var subtype_1 = match[1];
var subEncoder_1 = this.getEncoder(subtype_1);
var length_1 = parseInt(match[3]);
return function (value) {
if (length_1 >= 0 && value.length !== length_1) {
logger.throwArgumentError("array length mismatch; expected length ${ arrayLength }", "value", value);
}
var result = value.map(subEncoder_1);
if (_this._types[subtype_1]) {
result = result.map(keccak256_1.keccak256);
}
return (0, keccak256_1.keccak256)((0, bytes_1.hexConcat)(result));
};
}
// Struct
var fields = this.types[type];
if (fields) {
var encodedType_1 = (0, id_1.id)(this._types[type]);
return function (value) {
var values = fields.map(function (_a) {
var name = _a.name, type = _a.type;
var result = _this.getEncoder(type)(value[name]);
if (_this._types[type]) {
return (0, keccak256_1.keccak256)(result);
}
return result;
});
values.unshift(encodedType_1);
return (0, bytes_1.hexConcat)(values);
};
}
return logger.throwArgumentError("unknown type: " + type, "type", type);
};
TypedDataEncoder.prototype.encodeType = function (name) {
var result = this._types[name];
}
encodeType(name) {
const result = __classPrivateFieldGet(this, _TypedDataEncoder_fullTypes, "f").get(name);
if (!result) {
logger.throwArgumentError("unknown type: " + JSON.stringify(name), "name", name);
return logger.throwArgumentError(`unknown type: ${JSON.stringify(name)}`, "name", name);
}
return result;
};
TypedDataEncoder.prototype.encodeData = function (type, value) {
}
encodeData(type, value) {
return this.getEncoder(type)(value);
};
TypedDataEncoder.prototype.hashStruct = function (name, value) {
return (0, keccak256_1.keccak256)(this.encodeData(name, value));
};
TypedDataEncoder.prototype.encode = function (value) {
}
hashStruct(name, value) {
return keccak256(this.encodeData(name, value));
}
encode(value) {
return this.encodeData(this.primaryType, value);
};
TypedDataEncoder.prototype.hash = function (value) {
}
hash(value) {
return this.hashStruct(this.primaryType, value);
};
TypedDataEncoder.prototype._visit = function (type, value, callback) {
var _this = this;
}
_visit(type, value, callback) {
// Basic encoder type (address, bool, uint256, etc)
{
var encoder = getBaseEncoder(type);
const encoder = getBaseEncoder(type);
if (encoder) {

@@ -344,50 +266,49 @@ return callback(type, value);

// Array
var match = type.match(/^(.*)(\x5b(\d*)\x5d)$/);
const match = type.match(/^(.*)(\x5b(\d*)\x5d)$/);
if (match) {
var subtype_2 = match[1];
var length_2 = parseInt(match[3]);
if (length_2 >= 0 && value.length !== length_2) {
const subtype = match[1];
const length = parseInt(match[3]);
if (length >= 0 && value.length !== length) {
logger.throwArgumentError("array length mismatch; expected length ${ arrayLength }", "value", value);
}
return value.map(function (v) { return _this._visit(subtype_2, v, callback); });
return value.map((v) => this._visit(subtype, v, callback));
}
// Struct
var fields = this.types[type];
const fields = this.types[type];
if (fields) {
return fields.reduce(function (accum, _a) {
var name = _a.name, type = _a.type;
accum[name] = _this._visit(type, value[name], callback);
return fields.reduce((accum, { name, type }) => {
accum[name] = this._visit(type, value[name], callback);
return accum;
}, {});
}
return logger.throwArgumentError("unknown type: " + type, "type", type);
};
TypedDataEncoder.prototype.visit = function (value, callback) {
return logger.throwArgumentError(`unknown type: ${type}`, "type", type);
}
visit(value, callback) {
return this._visit(this.primaryType, value, callback);
};
TypedDataEncoder.from = function (types) {
}
static from(types) {
return new TypedDataEncoder(types);
};
TypedDataEncoder.getPrimaryType = function (types) {
}
static getPrimaryType(types) {
return TypedDataEncoder.from(types).primaryType;
};
TypedDataEncoder.hashStruct = function (name, types, value) {
}
static hashStruct(name, types, value) {
return TypedDataEncoder.from(types).hashStruct(name, value);
};
TypedDataEncoder.hashDomain = function (domain) {
var domainFields = [];
for (var name_3 in domain) {
var type = domainFieldTypes[name_3];
}
static hashDomain(domain) {
const domainFields = [];
for (const name in domain) {
const type = domainFieldTypes[name];
if (!type) {
logger.throwArgumentError("invalid typed-data domain key: " + JSON.stringify(name_3), "domain", domain);
logger.throwArgumentError(`invalid typed-data domain key: ${JSON.stringify(name)}`, "domain", domain);
}
domainFields.push({ name: name_3, type: type });
domainFields.push({ name, type });
}
domainFields.sort(function (a, b) {
domainFields.sort((a, b) => {
return domainFieldNames.indexOf(a.name) - domainFieldNames.indexOf(b.name);
});
return TypedDataEncoder.hashStruct("EIP712Domain", { EIP712Domain: domainFields }, domain);
};
TypedDataEncoder.encode = function (domain, types, value) {
return (0, bytes_1.hexConcat)([
}
static encode(domain, types, value) {
return concat([
"0x1901",

@@ -397,70 +318,50 @@ TypedDataEncoder.hashDomain(domain),

]);
};
TypedDataEncoder.hash = function (domain, types, value) {
return (0, keccak256_1.keccak256)(TypedDataEncoder.encode(domain, types, value));
};
}
static hash(domain, types, value) {
return keccak256(TypedDataEncoder.encode(domain, types, value));
}
// Replaces all address types with ENS names with their looked up address
TypedDataEncoder.resolveNames = function (domain, types, value, resolveName) {
return __awaiter(this, void 0, void 0, function () {
var ensCache, encoder, _a, _b, _i, name_4, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
// Make a copy to isolate it from the object passed in
domain = (0, properties_1.shallowCopy)(domain);
ensCache = {};
// Do we need to look up the domain's verifyingContract?
if (domain.verifyingContract && !(0, bytes_1.isHexString)(domain.verifyingContract, 20)) {
ensCache[domain.verifyingContract] = "0x";
}
encoder = TypedDataEncoder.from(types);
// Get a list of all the addresses
encoder.visit(value, function (type, value) {
if (type === "address" && !(0, bytes_1.isHexString)(value, 20)) {
ensCache[value] = "0x";
}
return value;
});
_a = [];
for (_b in ensCache)
_a.push(_b);
_i = 0;
_e.label = 1;
case 1:
if (!(_i < _a.length)) return [3 /*break*/, 4];
name_4 = _a[_i];
_c = ensCache;
_d = name_4;
return [4 /*yield*/, resolveName(name_4)];
case 2:
_c[_d] = _e.sent();
_e.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4:
// Replace the domain verifyingContract if needed
if (domain.verifyingContract && ensCache[domain.verifyingContract]) {
domain.verifyingContract = ensCache[domain.verifyingContract];
}
// Replace all ENS names with their address
value = encoder.visit(value, function (type, value) {
if (type === "address" && ensCache[value]) {
return ensCache[value];
}
return value;
});
return [2 /*return*/, { domain: domain, value: value }];
}
});
static async resolveNames(domain, types, value, resolveName) {
// Make a copy to isolate it from the object passed in
domain = Object.assign({}, domain);
// Look up all ENS names
const ensCache = {};
// Do we need to look up the domain's verifyingContract?
if (domain.verifyingContract && !isHexString(domain.verifyingContract, 20)) {
ensCache[domain.verifyingContract] = "0x";
}
// We are going to use the encoder to visit all the base values
const encoder = TypedDataEncoder.from(types);
// Get a list of all the addresses
encoder.visit(value, (type, value) => {
if (type === "address" && !isHexString(value, 20)) {
ensCache[value] = "0x";
}
return value;
});
};
TypedDataEncoder.getPayload = function (domain, types, value) {
// Lookup each name
for (const name in ensCache) {
ensCache[name] = await resolveName(name);
}
// Replace the domain verifyingContract if needed
if (domain.verifyingContract && ensCache[domain.verifyingContract]) {
domain.verifyingContract = ensCache[domain.verifyingContract];
}
// Replace all ENS names with their address
value = encoder.visit(value, (type, value) => {
if (type === "address" && ensCache[value]) {
return ensCache[value];
}
return value;
});
return { domain, value };
}
static getPayload(domain, types, value) {
// Validate the domain fields
TypedDataEncoder.hashDomain(domain);
// Derive the EIP712Domain Struct reference type
var domainValues = {};
var domainTypes = [];
domainFieldNames.forEach(function (name) {
var value = domain[name];
const domainValues = {};
const domainTypes = [];
domainFieldNames.forEach((name) => {
const value = domain[name];
if (value == null) {

@@ -470,6 +371,6 @@ return;

domainValues[name] = domainChecks[name](value);
domainTypes.push({ name: name, type: domainFieldTypes[name] });
domainTypes.push({ name, type: domainFieldTypes[name] });
});
var encoder = TypedDataEncoder.from(types);
var typesWithDomain = (0, properties_1.shallowCopy)(types);
const encoder = TypedDataEncoder.from(types);
const typesWithDomain = Object.assign({}, types);
if (typesWithDomain.EIP712Domain) {

@@ -487,10 +388,10 @@ logger.throwArgumentError("types must not contain EIP712Domain type", "types.EIP712Domain", types);

primaryType: encoder.primaryType,
message: encoder.visit(value, function (type, value) {
message: encoder.visit(value, (type, value) => {
// bytes
if (type.match(/^bytes(\d*)/)) {
return (0, bytes_1.hexlify)((0, bytes_1.arrayify)(value));
return hexlify(logger.getBytes(value));
}
// uint or int
if (type.match(/^u?int/)) {
return bignumber_1.BigNumber.from(value).toString();
return logger.getBigInt(value).toString();
}

@@ -504,3 +405,3 @@ switch (type) {

if (typeof (value) !== "string") {
logger.throwArgumentError("invalid string", "value", value);
logger.throwArgumentError(`invalid string`, "value", value);
}

@@ -512,6 +413,47 @@ return value;

};
};
return TypedDataEncoder;
}());
exports.TypedDataEncoder = TypedDataEncoder;
}
}
_TypedDataEncoder_types = new WeakMap(), _TypedDataEncoder_fullTypes = new WeakMap(), _TypedDataEncoder_encoderCache = new WeakMap(), _TypedDataEncoder_instances = new WeakSet(), _TypedDataEncoder_getEncoder = function _TypedDataEncoder_getEncoder(type) {
// Basic encoder type (address, bool, uint256, etc)
{
const encoder = getBaseEncoder(type);
if (encoder) {
return encoder;
}
}
// Array
const match = type.match(/^(.*)(\x5b(\d*)\x5d)$/);
if (match) {
const subtype = match[1];
const subEncoder = this.getEncoder(subtype);
const length = parseInt(match[3]);
return (value) => {
if (length >= 0 && value.length !== length) {
logger.throwArgumentError("array length mismatch; expected length ${ arrayLength }", "value", value);
}
let result = value.map(subEncoder);
if (__classPrivateFieldGet(this, _TypedDataEncoder_fullTypes, "f").has(subtype)) {
result = result.map(keccak256);
}
return keccak256(concat(result));
};
}
// Struct
const fields = this.types[type];
if (fields) {
const encodedType = id(__classPrivateFieldGet(this, _TypedDataEncoder_fullTypes, "f").get(type));
return (value) => {
const values = fields.map(({ name, type }) => {
const result = this.getEncoder(type)(value[name]);
if (__classPrivateFieldGet(this, _TypedDataEncoder_fullTypes, "f").has(type)) {
return keccak256(result);
}
return result;
});
values.unshift(encodedType);
return concat(values);
};
}
return logger.throwArgumentError(`unknown type: ${type}`, "type", type);
};
//# sourceMappingURL=typed-data.js.map
MIT License
Copyright (c) 2019 Richard Moore
Copyright (c) 2022 Richard Moore

@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy

{
"author": "Richard Moore <me@ricmoo.com>",
"dependencies": {
"@ethersproject/abstract-signer": "^5.6.0",
"@ethersproject/address": "^5.6.0",
"@ethersproject/bignumber": "^5.6.0",
"@ethersproject/bytes": "^5.6.0",
"@ethersproject/keccak256": "^5.6.0",
"@ethersproject/logger": "^5.6.0",
"@ethersproject/properties": "^5.6.0",
"@ethersproject/strings": "^5.6.0"
"@ethersproject/address": "^6.0.0-beta.1",
"@ethersproject/bytes": "^6.0.0-beta.1",
"@ethersproject/crypto": "^6.0.0-beta.1",
"@ethersproject/logger": "^6.0.0-beta.1",
"@ethersproject/math": "^6.0.0-beta.1",
"@ethersproject/properties": "^6.0.0-beta.1",
"@ethersproject/strings": "^6.0.0-beta.1"
},
"description": "Hash utility functions for Ethereum.",
"description": "Hash utilities for ethers.",
"engines": {
"node": ">=12.17.0"
},
"ethereum": "donations.ethers.eth",
"funding": [
{
"type": "individual",
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
},
{
"type": "individual",
"url": "https://www.buymeacoffee.com/ricmoo"
}
],
"gitHead": "b8cda5dffdcb688e38d7c6a0aec4c7b8b59c1af5",
"gitHead": "77f691b3bc3a6387a5184ec9b1779faab4bcb30d",
"keywords": [

@@ -32,6 +24,6 @@ "Ethereum",

"main": "./lib/index.js",
"module": "./lib.esm/index.js",
"name": "@ethersproject/hash",
"publishConfig": {
"access": "public"
"access": "public",
"tag": "beta"
},

@@ -47,5 +39,6 @@ "repository": {

"sideEffects": false,
"tarballHash": "0x23b00b87b17191eace6450fd824e0f816a3c3dfbdbacd0a904f67b5be5b43984",
"tarballHash": "0xf8ec4639eeaaf31db5783f32bfc52196513ee91f31f26841186f84aa70ff73c8",
"type": "module",
"types": "./lib/index.d.ts",
"version": "5.6.0"
"version": "6.0.0-beta.1"
}

@@ -1,1 +0,1 @@

export const version = "hash/5.6.0";
export const version = "@ethersproject/hash@6.0.0-beta.1";

@@ -1,6 +0,6 @@

import { keccak256 } from "@ethersproject/keccak256";
import { keccak256 } from "@ethersproject/crypto";
import { toUtf8Bytes } from "@ethersproject/strings";
export function id(text: string): string {
return keccak256(toUtf8Bytes(text));
export function id(value: string): string {
return keccak256(toUtf8Bytes(value));
}

@@ -1,20 +0,6 @@

"use strict";
export { id } from "./id.js"
export { isValidName, namehash, dnsEncode } from "./namehash.js";
export { messagePrefix, hashMessage } from "./message.js";
export { TypedDataEncoder } from "./typed-data.js";
import { id } from "./id";
import { dnsEncode, isValidName, namehash } from "./namehash";
import { hashMessage, messagePrefix } from "./message";
import { TypedDataEncoder as _TypedDataEncoder } from "./typed-data";
export {
id,
dnsEncode,
namehash,
isValidName,
messagePrefix,
hashMessage,
_TypedDataEncoder,
}
export type { TypedDataDomain, TypedDataField } from "./typed-data.js";

@@ -1,8 +0,9 @@

import { Bytes, concat } from "@ethersproject/bytes";
import { keccak256 } from "@ethersproject/keccak256";
import { concat } from "@ethersproject/bytes";
import { keccak256 } from "@ethersproject/crypto";
import { toUtf8Bytes } from "@ethersproject/strings";
export const messagePrefix = "\x19Ethereum Signed Message:\n";
export function hashMessage(message: Bytes | string): string {
export function hashMessage(message: Uint8Array | string): string {
if (typeof(message) === "string") { message = toUtf8Bytes(message); }

@@ -15,2 +16,1 @@ return keccak256(concat([

}
import { concat, hexlify } from "@ethersproject/bytes";
import { keccak256 } from "@ethersproject/crypto";
import { nameprep, toUtf8Bytes } from "@ethersproject/strings";
import { keccak256 } from "@ethersproject/keccak256";
import { Logger } from "@ethersproject/logger";
import { version } from "./_version";
const logger = new Logger(version);
import { logger } from "./logger.js";
const Zeros = new Uint8Array(32);

@@ -28,3 +27,2 @@ Zeros.fill(0);

export function namehash(name: string): string {
/* istanbul ignore if */
if (typeof(name) !== "string") {

@@ -39,3 +37,3 @@ logger.throwArgumentError("invalid ENS name; not a string", "name", name);

if (partition == null || partition[2] === "") {
logger.throwArgumentError("invalid ENS address; missing component", "name", name);
return logger.throwArgumentError("invalid ENS name; missing component", "name", name);
}

@@ -52,9 +50,22 @@ const label = toUtf8Bytes(nameprep(partition[3]));

export function dnsEncode(name: string): string {
return hexlify(concat(name.split(".").map((comp) => {
if (typeof(name) !== "string") {
logger.throwArgumentError("invalid DNS name; not a string", "name", name);
}
if (name === "") { return "0x00"; }
// @TODO: should we enforce the 255 octet limit?
return concat(name.split(".").map((comp) => {
if (comp === "") {
logger.throwArgumentError("invalid DNS name; missing component", "name", name);
}
// We jam in an _ prefix to fill in with the length later
// Note: Nameprep throws if the component is over 63 bytes
const bytes = toUtf8Bytes("_" + nameprep(comp));
bytes[0] = bytes.length - 1;
return bytes;
}))) + "00";
})) + "00";
}

@@ -1,22 +0,35 @@

import { TypedDataDomain, TypedDataField } from "@ethersproject/abstract-signer";
//import { TypedDataDomain, TypedDataField } from "@ethersproject/providerabstract-signer";
import { getAddress } from "@ethersproject/address";
import { BigNumber, BigNumberish } from "@ethersproject/bignumber";
import { arrayify, BytesLike, hexConcat, hexlify, hexZeroPad, isHexString } from "@ethersproject/bytes";
import { keccak256 } from "@ethersproject/keccak256";
import { deepCopy, defineReadOnly, shallowCopy } from "@ethersproject/properties";
import { arrayify, concat, hexlify, zeroPadLeft, isHexString } from "@ethersproject/bytes";
import { keccak256 } from "@ethersproject/crypto";
import { defineProperties } from "@ethersproject/properties";
import { mask, toHex, toTwos } from "@ethersproject/math";
import { Logger } from "@ethersproject/logger";
import { version } from "./_version";
const logger = new Logger(version);
import { id } from "./id.js";
import { logger } from "./logger.js";
import { id } from "./id";
import type { BigNumberish, BytesLike } from "@ethersproject/logger";
const padding = new Uint8Array(32);
padding.fill(0);
const NegativeOne: BigNumber = BigNumber.from(-1);
const Zero: BigNumber = BigNumber.from(0);
const One: BigNumber = BigNumber.from(1);
const MaxUint256: BigNumber = BigNumber.from("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
const BN__1 = BigInt(-1);
const BN_0 = BigInt(0);
const BN_1 = BigInt(1);
const BN_MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
export interface TypedDataDomain {
name?: string;
version?: string;
chainId?: BigNumberish;
verifyingContract?: string;
salt?: BytesLike;
};
export interface TypedDataField {
name: string;
type: string;
};
function hexPadRight(value: BytesLike) {

@@ -26,3 +39,3 @@ const bytes = arrayify(value);

if (padOffset) {
return hexConcat([ bytes, padding.slice(padOffset) ]);
return concat([ bytes, padding.slice(padOffset) ]);
}

@@ -32,4 +45,4 @@ return hexlify(bytes);

const hexTrue = hexZeroPad(One.toHexString(), 32);
const hexFalse = hexZeroPad(Zero.toHexString(), 32);
const hexTrue = toHex(BN_1, 32);
const hexFalse = toHex(BN_0, 32);

@@ -61,6 +74,3 @@ const domainFieldTypes: Record<string, string> = {

chainId: function(value: any) {
try {
return BigNumber.from(value).toString()
} catch (error) { }
return logger.throwArgumentError(`invalid domain value for "chainId"`, "domain.chainId", value);
return logger.getBigInt(value, "domain.chainId");
},

@@ -74,12 +84,11 @@ verifyingContract: function(value: any) {

salt: function(value: any) {
try {
const bytes = arrayify(value);
if (bytes.length !== 32) { throw new Error("bad length"); }
return hexlify(bytes);
} catch (error) { }
return logger.throwArgumentError(`invalid domain value "salt"`, "domain.salt", value);
const bytes = logger.getBytes(value, "domain.salt");
if (bytes.length !== 32) {
logger.throwArgumentError(`invalid domain value "salt"`, "domain.salt", value);
}
return hexlify(bytes);
}
}
function getBaseEncoder(type: string): (value: any) => string {
function getBaseEncoder(type: string): null | ((value: any) => string) {
// intXX and uintXX

@@ -96,13 +105,13 @@ {

const boundsUpper = MaxUint256.mask(signed ? (width - 1): width);
const boundsLower = signed ? boundsUpper.add(One).mul(NegativeOne): Zero;
const boundsUpper = mask(BN_MAX_UINT256, signed ? (width - 1): width);
const boundsLower = signed ? ((boundsUpper + BN_1) * BN__1): BN_0;
return function(value: BigNumberish) {
const v = BigNumber.from(value);
return function(_value: BigNumberish) {
const value = logger.getBigInt(_value, "value");
if (v.lt(boundsLower) || v.gt(boundsUpper)) {
if (value < boundsLower || value > boundsUpper) {
logger.throwArgumentError(`value out-of-bounds for ${ type }`, "value", value);
}
return hexZeroPad(v.toTwos(256).toHexString(), 32);
return toHex(toTwos(value, 256), 32);
};

@@ -133,3 +142,3 @@ }

case "address": return function(value: string) {
return hexZeroPad(getAddress(value), 32);
return zeroPadLeft(getAddress(value), 32);
};

@@ -155,43 +164,46 @@ case "bool": return function(value: boolean) {

export class TypedDataEncoder {
readonly primaryType: string;
readonly types: Record<string, Array<TypedDataField>>;
readonly primaryType!: string;
readonly _encoderCache: Record<string, (value: any) => string>;
readonly _types: Record<string, string>;
readonly #types: string;
get types(): Record<string, Array<TypedDataField>> {
return JSON.parse(this.#types);
}
readonly #fullTypes: Map<string, string>
readonly #encoderCache: Map<string, (value: any) => string>;
constructor(types: Record<string, Array<TypedDataField>>) {
defineReadOnly(this, "types", Object.freeze(deepCopy(types)));
this.#types = JSON.stringify(types);
this.#fullTypes = new Map();
this.#encoderCache = new Map();
defineReadOnly(this, "_encoderCache", { });
defineReadOnly(this, "_types", { });
// Link struct types to their direct child structs
const links: Record<string, Record<string, boolean>> = { };
const links: Map<string, Set<string>> = new Map();
// Link structs to structs which contain them as a child
const parents: Record<string, Array<string>> = { };
const parents: Map<string, Array<string>> = new Map();
// Link all subtypes within a given struct
const subtypes: Record<string, Record<string, boolean>> = { };
const subtypes: Map<string, Set<string>> = new Map();
Object.keys(types).forEach((type) => {
links[type] = { };
parents[type] = [ ];
subtypes[type] = { }
links.set(type, new Set());
parents.set(type, [ ]);
subtypes.set(type, new Set());
});
for (const name in types) {
const uniqueNames: Set<string> = new Set();
const uniqueNames: Record<string, boolean> = { };
for (const field of types[name]) {
types[name].forEach((field) => {
// Check each field has a unique name
if (uniqueNames[field.name]) {
if (uniqueNames.has(field.name)) {
logger.throwArgumentError(`duplicate variable name ${ JSON.stringify(field.name) } in ${ JSON.stringify(name) }`, "types", types);
}
uniqueNames[field.name] = true;
uniqueNames.add(field.name);
// Get the base type (drop any array specifiers)
const baseType = field.type.match(/^([^\x5b]*)(\x5b|$)/)[1];
const baseType = (<any>(field.type.match(/^([^\x5b]*)(\x5b|$)/)))[1] || null;
if (baseType === name) {

@@ -203,5 +215,5 @@ logger.throwArgumentError(`circular type reference to ${ JSON.stringify(baseType) }`, "types", types);

const encoder = getBaseEncoder(baseType);
if (encoder) { return ;}
if (encoder) { continue; }
if (!parents[baseType]) {
if (!parents.has(baseType)) {
logger.throwArgumentError(`unknown type ${ JSON.stringify(baseType) }`, "types", types);

@@ -211,9 +223,9 @@ }

// Add linkage
parents[baseType].push(name);
links[name][baseType] = true;
});
(parents.get(baseType) as Array<string>).push(name);
(links.get(name) as Set<string>).add(baseType);
}
}
// Deduce the primary type
const primaryTypes = Object.keys(parents).filter((n) => (parents[n].length === 0));
const primaryTypes = Array.from(parents.keys()).filter((n) => ((parents.get(n) as Array<string>).length === 0));

@@ -226,14 +238,14 @@ if (primaryTypes.length === 0) {

defineReadOnly(this, "primaryType", primaryTypes[0]);
defineProperties<TypedDataEncoder>(this, { primaryType: primaryTypes[0] });
// Check for circular type references
function checkCircular(type: string, found: Record<string, boolean>) {
if (found[type]) {
function checkCircular(type: string, found: Set<string>) {
if (found.has(type)) {
logger.throwArgumentError(`circular type reference to ${ JSON.stringify(type) }`, "types", types);
}
found[type] = true;
found.add(type);
Object.keys(links[type]).forEach((child) => {
if (!parents[child]) { return; }
for (const child of (links.get(type) as Set<string>)) {
if (!parents.has(child)) { continue; }

@@ -244,16 +256,16 @@ // Recursively check children

// Mark all ancestors as having this decendant
Object.keys(found).forEach((subtype) => {
subtypes[subtype][child] = true;
});
});
for (const subtype of found) {
(subtypes.get(subtype) as Set<string>).add(child);
}
}
delete found[type];
found.delete(type);
}
checkCircular(this.primaryType, { });
checkCircular(this.primaryType, new Set());
// Compute each fully describe type
for (const name in subtypes) {
const st = Object.keys(subtypes[name]);
for (const [ name, set ] of subtypes) {
const st = Array.from(set);
st.sort();
this._types[name] = encodeType(name, types[name]) + st.map((t) => encodeType(t, types[t])).join("");
this.#fullTypes.set(name, encodeType(name, types[name]) + st.map((t) => encodeType(t, types[t])).join(""));
}

@@ -263,5 +275,6 @@ }

getEncoder(type: string): (value: any) => string {
let encoder = this._encoderCache[type];
let encoder = this.#encoderCache.get(type);
if (!encoder) {
encoder = this._encoderCache[type] = this._getEncoder(type);
encoder = this.#getEncoder(type);
this.#encoderCache.set(type, encoder);
}

@@ -271,3 +284,3 @@ return encoder;

_getEncoder(type: string): (value: any) => string {
#getEncoder(type: string): (value: any) => string {

@@ -292,7 +305,7 @@ // Basic encoder type (address, bool, uint256, etc)

let result = value.map(subEncoder);
if (this._types[subtype]) {
if (this.#fullTypes.has(subtype)) {
result = result.map(keccak256);
}
return keccak256(hexConcat(result));
return keccak256(concat(result));
};

@@ -304,11 +317,11 @@ }

if (fields) {
const encodedType = id(this._types[type]);
const encodedType = id(this.#fullTypes.get(type) as string);
return (value: Record<string, any>) => {
const values = fields.map(({ name, type }) => {
const result = this.getEncoder(type)(value[name]);
if (this._types[type]) { return keccak256(result); }
if (this.#fullTypes.has(type)) { return keccak256(result); }
return result;
});
values.unshift(encodedType);
return hexConcat(values);
return concat(values);
}

@@ -321,5 +334,5 @@ }

encodeType(name: string): string {
const result = this._types[name];
const result = this.#fullTypes.get(name);
if (!result) {
logger.throwArgumentError(`unknown type: ${ JSON.stringify(name) }`, "name", name);
return logger.throwArgumentError(`unknown type: ${ JSON.stringify(name) }`, "name", name);
}

@@ -409,3 +422,3 @@ return result;

static encode(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
return hexConcat([
return concat([
"0x1901",

@@ -424,3 +437,3 @@ TypedDataEncoder.hashDomain(domain),

// Make a copy to isolate it from the object passed in
domain = shallowCopy(domain);
domain = Object.assign({ }, domain);

@@ -482,3 +495,3 @@ // Look up all ENS names

const typesWithDomain = shallowCopy(types);
const typesWithDomain = Object.assign({ }, types);
if (typesWithDomain.EIP712Domain) {

@@ -501,3 +514,3 @@ logger.throwArgumentError("types must not contain EIP712Domain type", "types.EIP712Domain", types);

if (type.match(/^bytes(\d*)/)) {
return hexlify(arrayify(value));
return hexlify(logger.getBytes(value));
}

@@ -507,3 +520,3 @@

if (type.match(/^u?int/)) {
return BigNumber.from(value).toString();
return logger.getBigInt(value).toString();
}

@@ -510,0 +523,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 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 not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc