UNPKG

16.1 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 return new (P || (P = Promise))(function (resolve, reject) {
5 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 step((generator = generator.apply(thisArg, _arguments || [])).next());
9 });
10};
11var __generator = (this && this.__generator) || function (thisArg, body) {
12 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14 function verb(n) { return function (v) { return step([n, v]); }; }
15 function step(op) {
16 if (f) throw new TypeError("Generator is already executing.");
17 while (_) try {
18 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;
19 if (y = 0, t) op = [op[0] & 2, t.value];
20 switch (op[0]) {
21 case 0: case 1: t = op; break;
22 case 4: _.label++; return { value: op[1], done: false };
23 case 5: _.label++; y = op[1]; op = [0]; continue;
24 case 7: op = _.ops.pop(); _.trys.pop(); continue;
25 default:
26 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30 if (t[2]) _.ops.pop();
31 _.trys.pop(); continue;
32 }
33 op = body.call(thisArg, _);
34 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36 }
37};
38var __read = (this && this.__read) || function (o, n) {
39 var m = typeof Symbol === "function" && o[Symbol.iterator];
40 if (!m) return o;
41 var i = m.call(o), r, ar = [], e;
42 try {
43 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
44 }
45 catch (error) { e = { error: error }; }
46 finally {
47 try {
48 if (r && !r.done && (m = i["return"])) m.call(i);
49 }
50 finally { if (e) throw e.error; }
51 }
52 return ar;
53};
54var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
55 if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
56 if (ar || !(i in from)) {
57 if (!ar) ar = Array.prototype.slice.call(from, 0, i);
58 ar[i] = from[i];
59 }
60 }
61 return to.concat(ar || Array.prototype.slice.call(from));
62};
63var __importDefault = (this && this.__importDefault) || function (mod) {
64 return (mod && mod.__esModule) ? mod : { "default": mod };
65};
66exports.__esModule = true;
67exports.getFiltersForMessage = exports.getSchemaHashForMessage = exports.sortObjectAlphabetically = exports.isEIP712Message = exports.makeTypeEntryStructBuffer = exports.constructTypeDescByteString = exports.destructTypeFromString = exports.EIP712_TYPE_ENCODERS = exports.EIP712_TYPE_PROPERTIES = void 0;
68var axios_1 = __importDefault(require("axios"));
69var sha224_1 = __importDefault(require("crypto-js/sha224"));
70var utils_1 = require("../../utils");
71var eip712_1 = __importDefault(require("@ledgerhq/cryptoassets/data/eip712"));
72var bignumber_js_1 = __importDefault(require("bignumber.js"));
73var NULL_ADDRESS = "0x0000000000000000000000000000000000000000";
74/**
75 * @ignore for the README
76 *
77 * A Map of helpers to get the wanted binary value for
78 * each type of array possible in a type definition
79 */
80var EIP712_ARRAY_TYPE_VALUE;
81(function (EIP712_ARRAY_TYPE_VALUE) {
82 EIP712_ARRAY_TYPE_VALUE[EIP712_ARRAY_TYPE_VALUE["DYNAMIC"] = 0] = "DYNAMIC";
83 EIP712_ARRAY_TYPE_VALUE[EIP712_ARRAY_TYPE_VALUE["FIXED"] = 1] = "FIXED";
84})(EIP712_ARRAY_TYPE_VALUE || (EIP712_ARRAY_TYPE_VALUE = {}));
85/**
86 * @ignore for the README
87 *
88 * A Map of helpers to get the id and size to return for each
89 * type that can be used in EIP712
90 */
91exports.EIP712_TYPE_PROPERTIES = {
92 CUSTOM: {
93 key: function () { return 0; },
94 sizeInBits: function () { return null; }
95 },
96 INT: {
97 key: function () { return 1; },
98 sizeInBits: function (size) { return Number(size) / 8; }
99 },
100 UINT: {
101 key: function () { return 2; },
102 sizeInBits: function (size) { return Number(size) / 8; }
103 },
104 ADDRESS: {
105 key: function () { return 3; },
106 sizeInBits: function () { return null; }
107 },
108 BOOL: {
109 key: function () { return 4; },
110 sizeInBits: function () { return null; }
111 },
112 STRING: {
113 key: function () { return 5; },
114 sizeInBits: function () { return null; }
115 },
116 BYTES: {
117 key: function (size) { return (typeof size !== "undefined" ? 6 : 7); },
118 sizeInBits: function (size) { return (typeof size !== "undefined" ? Number(size) : null); }
119 }
120};
121/**
122 * @ignore for the README
123 *
124 * A Map of encoders to transform a value to formatted buffer
125 */
126exports.EIP712_TYPE_ENCODERS = {
127 INT: function (value, sizeInBits) {
128 if (sizeInBits === void 0) { sizeInBits = 256; }
129 var failSafeValue = value !== null && value !== void 0 ? value : "0";
130 if (typeof failSafeValue === "string" && (failSafeValue === null || failSafeValue === void 0 ? void 0 : failSafeValue.startsWith("0x"))) {
131 return (0, utils_1.hexBuffer)(failSafeValue);
132 }
133 var valueAsBN = new bignumber_js_1["default"](failSafeValue);
134 // If negative we'll use `two's complement` method to
135 // "reversibly convert a positive binary number into a negative binary number with equivalent (but negative) value".
136 // thx wikipedia
137 if (valueAsBN.lt(0)) {
138 var sizeInBytes = sizeInBits / 8;
139 // Creates BN from a buffer serving as a mask filled by maximum value 0xff
140 var maskAsBN = new bignumber_js_1["default"]("0x".concat(Buffer.alloc(sizeInBytes, 0xff).toString("hex")));
141 // two's complement version of value
142 valueAsBN = maskAsBN.plus(valueAsBN).plus(1);
143 }
144 var paddedHexString = valueAsBN.toString(16).length % 2
145 ? "0" + valueAsBN.toString(16)
146 : valueAsBN.toString(16);
147 return Buffer.from(paddedHexString, "hex");
148 },
149 UINT: function (value) {
150 return this.INT(value);
151 },
152 BOOL: function (value) {
153 return this.INT(typeof value === "boolean" ? Number(value).toString() : value);
154 },
155 ADDRESS: function (value) {
156 // Only sending the first 10 bytes (why ?)
157 return (0, utils_1.hexBuffer)(value !== null && value !== void 0 ? value : "").slice(0, 20);
158 },
159 STRING: function (value) {
160 return Buffer.from(value !== null && value !== void 0 ? value : "", "utf-8");
161 },
162 BYTES: function (value, sizeInBits) {
163 var failSafeValue = value !== null && value !== void 0 ? value : "";
164 // Why slice again ?
165 return (0, utils_1.hexBuffer)(failSafeValue).slice(0, sizeInBits !== null && sizeInBits !== void 0 ? sizeInBits : ((failSafeValue === null || failSafeValue === void 0 ? void 0 : failSafeValue.length) - 2) / 2);
166 }
167};
168/**
169 * @ignore for the README
170 *
171 * Helper parsing an EIP712 Type name to return its type and size(s)
172 * if it's an array or nested arrays
173 *
174 * @see EIP712MessageTypes
175 *
176 * @example "uint8[2][][4]" => [{name: "uint", bits: 8}, [2, null, 4]]
177 * @example "bool" => [{name: "bool", bits: null}, []]
178 *
179 * @param {String} typeName
180 * @returns {[{ name: string; bits: Number | null }, Array<Number | null | undefined>]}
181 */
182var destructTypeFromString = function (typeName) {
183 // Will split "any[][1][10]" in "any", "[][1][10]"
184 var splitNameAndArraysRegex = new RegExp(/^([^[\]]*)(\[.*\])*/g);
185 // Will match all numbers (or null) inside each array. [0][10][] => [0,10,null]
186 var splitArraysRegex = new RegExp(/\[(\d*)\]/g);
187 // Will separate the the name from the potential bits allocation. uint8 => [uint,8]
188 var splitNameAndNumberRegex = new RegExp(/(\D*)(\d*)/);
189 var _a = __read(splitNameAndArraysRegex.exec(typeName || "") || [], 3), type = _a[1], maybeArrays = _a[2];
190 var _b = __read(splitNameAndNumberRegex.exec(type || "") || [], 3), name = _b[1], bits = _b[2];
191 var typeDescription = name
192 ? { name: name, bits: bits ? Number(bits) : undefined }
193 : null;
194 var arrays = maybeArrays ? __spreadArray([], __read(maybeArrays.matchAll(splitArraysRegex)), false) : [];
195 // Parse each size to either a Number or null
196 var arraySizes = arrays.map(function (_a) {
197 var _b = __read(_a, 2), size = _b[1];
198 return (size ? Number(size) : null);
199 });
200 return [typeDescription, arraySizes];
201};
202exports.destructTypeFromString = destructTypeFromString;
203/**
204 * @ignore for the README
205 *
206 * Helper to construct the hexadecimal ByteString for the description
207 * of a field in an EIP712 Message
208 *
209 * @param isArray
210 * @param typeSize
211 * @param typeValue
212 * @returns {String} HexByteString
213 */
214var constructTypeDescByteString = function (isArray, typeSize, typeValue) {
215 if (typeValue >= 16) {
216 throw new Error("Eth utils - constructTypeDescByteString - Cannot accept a typeValue >= 16 because the typeValue can only be 4 bits in binary" +
217 { isArray: isArray, typeSize: typeSize, typeValue: typeValue });
218 }
219 // 1 is array, 0 is not array
220 var isArrayBit = isArray ? "1" : "0";
221 // 1 has type size, 0 has no type size
222 var hasTypeSize = typeof typeSize === "number" ? "1" : "0";
223 // 2 unused bits
224 var unusedBits = "00";
225 // type key as 4 bits
226 var typeValueBits = typeValue.toString(2).padStart(4, "0");
227 return (0, utils_1.intAsHexBytes)(parseInt(isArrayBit + hasTypeSize + unusedBits + typeValueBits, 2), 1);
228};
229exports.constructTypeDescByteString = constructTypeDescByteString;
230/**
231 * @ignore for the README
232 *
233 * Helper to create the buffer to describe an EIP712 types' entry structure
234 *
235 * @param {EIP712MessageTypesEntry} entry
236 * @returns {Buffer}
237 */
238var makeTypeEntryStructBuffer = function (_a) {
239 var _b, _c, _d, _e;
240 var name = _a.name, type = _a.type;
241 var _f = __read((0, exports.destructTypeFromString)(type), 2), typeDescription = _f[0], arrSizes = _f[1];
242 var isTypeAnArray = Boolean(arrSizes.length);
243 var typeProperties = exports.EIP712_TYPE_PROPERTIES[((_b = typeDescription === null || typeDescription === void 0 ? void 0 : typeDescription.name) === null || _b === void 0 ? void 0 : _b.toUpperCase()) || ""] ||
244 exports.EIP712_TYPE_PROPERTIES.CUSTOM;
245 var typeKey = typeProperties.key(typeDescription === null || typeDescription === void 0 ? void 0 : typeDescription.bits);
246 var typeSizeInBits = typeProperties.sizeInBits(typeDescription === null || typeDescription === void 0 ? void 0 : typeDescription.bits);
247 var typeDescData = (0, exports.constructTypeDescByteString)(isTypeAnArray, typeSizeInBits, typeKey);
248 var bufferArray = [Buffer.from(typeDescData, "hex")];
249 if (typeProperties === exports.EIP712_TYPE_PROPERTIES.CUSTOM) {
250 bufferArray.push(Buffer.from((0, utils_1.intAsHexBytes)((_d = (_c = typeDescription === null || typeDescription === void 0 ? void 0 : typeDescription.name) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0, 1), "hex"));
251 bufferArray.push(Buffer.from((_e = typeDescription === null || typeDescription === void 0 ? void 0 : typeDescription.name) !== null && _e !== void 0 ? _e : "", "utf-8"));
252 }
253 if (typeof typeSizeInBits === "number") {
254 bufferArray.push(Buffer.from((0, utils_1.intAsHexBytes)(typeSizeInBits, 1), "hex"));
255 }
256 if (isTypeAnArray) {
257 bufferArray.push(Buffer.from((0, utils_1.intAsHexBytes)(arrSizes.length, 1), "hex"));
258 arrSizes.forEach(function (size) {
259 if (typeof size === "number") {
260 bufferArray.push(Buffer.from((0, utils_1.intAsHexBytes)(EIP712_ARRAY_TYPE_VALUE.FIXED, 1), "hex"), Buffer.from((0, utils_1.intAsHexBytes)(size, 1), "hex"));
261 }
262 else {
263 bufferArray.push(Buffer.from((0, utils_1.intAsHexBytes)(EIP712_ARRAY_TYPE_VALUE.DYNAMIC, 1), "hex"));
264 }
265 });
266 }
267 bufferArray.push(Buffer.from((0, utils_1.intAsHexBytes)(name.length, 1), "hex"), Buffer.from(name, "utf-8"));
268 return Buffer.concat(bufferArray);
269};
270exports.makeTypeEntryStructBuffer = makeTypeEntryStructBuffer;
271// As defined in [spec](https://eips.ethereum.org/EIPS/eip-712), the properties below are all required.
272function isEIP712Message(message) {
273 return (typeof message === "object" &&
274 "types" in message &&
275 "primaryType" in message &&
276 "domain" in message &&
277 "message" in message);
278}
279exports.isEIP712Message = isEIP712Message;
280var sortObjectAlphabetically = function (obj) {
281 var keys = Object.keys(obj).sort();
282 return keys.reduce(function (acc, curr) {
283 var value = (function () {
284 if (Array.isArray(obj[curr])) {
285 return obj[curr].map(function (field) {
286 return (0, exports.sortObjectAlphabetically)(field);
287 });
288 }
289 return obj[curr];
290 })();
291 acc[curr] = value;
292 return acc;
293 }, {});
294};
295exports.sortObjectAlphabetically = sortObjectAlphabetically;
296var getSchemaHashForMessage = function (message) {
297 var types = message.types;
298 var sortedTypes = (0, exports.sortObjectAlphabetically)(types);
299 return (0, sha224_1["default"])(JSON.stringify(sortedTypes).replace(" ", "")).toString();
300};
301exports.getSchemaHashForMessage = getSchemaHashForMessage;
302/**
303 * @ignore for the README
304 *
305 * Tries to find the proper filters for a given EIP712 message
306 * in the CAL
307 *
308 * @param {EIP712Message} message
309 * @returns {MessageFilters | undefined}
310 */
311var getFiltersForMessage = function (message, remoteCryptoAssetsListURI) { return __awaiter(void 0, void 0, void 0, function () {
312 var schemaHash, messageId, dynamicCAL, e_1;
313 var _a, _b, _c, _d;
314 return __generator(this, function (_e) {
315 switch (_e.label) {
316 case 0:
317 schemaHash = (0, exports.getSchemaHashForMessage)(message);
318 messageId = "".concat((_b = (_a = message.domain) === null || _a === void 0 ? void 0 : _a.chainId) !== null && _b !== void 0 ? _b : 0, ":").concat((_d = (_c = message.domain) === null || _c === void 0 ? void 0 : _c.verifyingContract) !== null && _d !== void 0 ? _d : NULL_ADDRESS, ":").concat(schemaHash);
319 _e.label = 1;
320 case 1:
321 _e.trys.push([1, 4, , 5]);
322 if (!remoteCryptoAssetsListURI) return [3 /*break*/, 3];
323 return [4 /*yield*/, axios_1["default"].get("".concat(remoteCryptoAssetsListURI, "/eip712.json"))];
324 case 2:
325 dynamicCAL = (_e.sent()).data;
326 return [2 /*return*/, dynamicCAL[messageId] || eip712_1["default"][messageId]];
327 case 3: throw new Error();
328 case 4:
329 e_1 = _e.sent();
330 return [2 /*return*/, eip712_1["default"][messageId]];
331 case 5: return [2 /*return*/];
332 }
333 });
334}); };
335exports.getFiltersForMessage = getFiltersForMessage;
336//# sourceMappingURL=EIP712.utils.js.map
\No newline at end of file