@spruceid/siwe-parser
Advanced tools
Comparing version 2.0.0 to 2.0.1
@@ -5,2 +5,3 @@ "use strict"; | ||
}; | ||
var _a; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -152,4 +153,4 @@ exports.ParsedMessage = void 0; | ||
`; | ||
class ParsedMessage { | ||
constructor(msg) { | ||
class GrammarApi { | ||
static generateApi() { | ||
const api = new api_1.default(GRAMMAR); | ||
@@ -163,3 +164,9 @@ api.generate(); | ||
} | ||
const grammarObj = api.toObject(); | ||
return api.toObject(); | ||
} | ||
} | ||
_a = GrammarApi; | ||
GrammarApi.grammarObj = _a.generateApi(); | ||
class ParsedMessage { | ||
constructor(msg) { | ||
const parser = new node_exports_1.default.parser(); | ||
@@ -213,3 +220,3 @@ parser.ast = new node_exports_1.default.ast(); | ||
if (state === id.SEM_PRE) { | ||
data.chainId = parseInt(node_exports_1.default.utils.charsToString(chars, phraseIndex, phraseLength)); | ||
data.chainId = (0, utils_1.parseIntegerNumber)(node_exports_1.default.utils.charsToString(chars, phraseIndex, phraseLength)); | ||
} | ||
@@ -270,3 +277,3 @@ return ret; | ||
parser.ast.callbacks.resources = resources; | ||
const result = parser.parse(grammarObj, "sign-in-with-ethereum", msg); | ||
const result = parser.parse(GrammarApi.grammarObj, "sign-in-with-ethereum", msg); | ||
if (!result.success) { | ||
@@ -273,0 +280,0 @@ throw new Error(`Invalid message: ${JSON.stringify(result)}`); |
import { ParsedMessage as ABNFParsedMessage } from "./abnf"; | ||
import { ParsedMessage as RegExpParsedMessage } from "./regex"; | ||
export * from './utils'; | ||
export { ABNFParsedMessage as ParsedMessage, RegExpParsedMessage as ParsedMessageRegExp, }; | ||
export { ABNFParsedMessage as ParsedMessage }; |
@@ -17,7 +17,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ParsedMessageRegExp = exports.ParsedMessage = void 0; | ||
exports.ParsedMessage = void 0; | ||
const abnf_1 = require("./abnf"); | ||
Object.defineProperty(exports, "ParsedMessage", { enumerable: true, get: function () { return abnf_1.ParsedMessage; } }); | ||
const regex_1 = require("./regex"); | ||
Object.defineProperty(exports, "ParsedMessageRegExp", { enumerable: true, get: function () { return regex_1.ParsedMessage; } }); | ||
__exportStar(require("./utils"), exports); |
@@ -58,23 +58,1 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
}); | ||
describe("Successfully parses with RegExp Client", () => { | ||
let ParsedMessage; | ||
beforeEach(() => __awaiter(this, void 0, void 0, function* () { return (ParsedMessage = (yield Promise.resolve().then(() => __importStar(require("./regex")))).ParsedMessage); })); | ||
test.concurrent.each(Object.entries(parsingPositive))("Parses message successfully: %s", (test_name, test) => { | ||
const parsedMessage = new ParsedMessage(test.message); | ||
for (const [field, value] of Object.entries(test.fields)) { | ||
if (typeof value === "object") { | ||
expect(parsedMessage[field]).toStrictEqual(value); | ||
} | ||
else { | ||
expect(parsedMessage[field]).toBe(value); | ||
} | ||
} | ||
}); | ||
}); | ||
describe("Successfully fails with RegExp Client", () => { | ||
let ParsedMessage; | ||
beforeEach(() => __awaiter(this, void 0, void 0, function* () { return (ParsedMessage = (yield Promise.resolve().then(() => __importStar(require(`./regex`)))).ParsedMessage); })); | ||
test.concurrent.each(Object.entries(parsingNegative))("Fails to parse message: %s", (test_name, test) => { | ||
expect(() => new ParsedMessage(test)).toThrow(); | ||
}); | ||
}); |
@@ -37,3 +37,3 @@ "use strict"; | ||
const NONCE = "\\nNonce: (?<nonce>[a-zA-Z0-9]{8,})"; | ||
const DATETIME = `([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([\+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))`; | ||
const DATETIME = `[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(.[0-9]+)?(([Zz])|([+|-]([01][0-9]|2[0-3]):[0-5][0-9]))`; | ||
const ISSUED_AT = `\\nIssued At: (?<issuedAt>${DATETIME})`; | ||
@@ -69,3 +69,3 @@ const EXPIRATION_TIME = `(\\nExpiration Time: (?<expirationTime>${DATETIME}))?`; | ||
this.nonce = (_f = match === null || match === void 0 ? void 0 : match.groups) === null || _f === void 0 ? void 0 : _f.nonce; | ||
this.chainId = parseInt((_g = match === null || match === void 0 ? void 0 : match.groups) === null || _g === void 0 ? void 0 : _g.chainId); | ||
this.chainId = (0, utils_1.parseIntegerNumber)((_g = match === null || match === void 0 ? void 0 : match.groups) === null || _g === void 0 ? void 0 : _g.chainId); | ||
this.issuedAt = (_h = match === null || match === void 0 ? void 0 : match.groups) === null || _h === void 0 ? void 0 : _h.issuedAt; | ||
@@ -72,0 +72,0 @@ this.expirationTime = (_j = match === null || match === void 0 ? void 0 : match.groups) === null || _j === void 0 ? void 0 : _j.expirationTime; |
@@ -7,1 +7,2 @@ /** | ||
export declare const isEIP55Address: (address: string) => boolean; | ||
export declare const parseIntegerNumber: (number: string) => number; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isEIP55Address = void 0; | ||
exports.parseIntegerNumber = exports.isEIP55Address = void 0; | ||
const sha3_1 = require("@noble/hashes/sha3"); | ||
const utils_1 = require("@noble/hashes/utils"); | ||
/** | ||
@@ -10,5 +12,7 @@ * This method is supposed to check if an address is conforming to EIP-55. | ||
const isEIP55Address = (address) => { | ||
const createKeccakHash = require('keccak'); | ||
if (address.length != 42) { | ||
return false; | ||
} | ||
const lowerAddress = `${address}`.toLowerCase().replace('0x', ''); | ||
var hash = createKeccakHash('keccak256').update(lowerAddress).digest('hex'); | ||
var hash = (0, utils_1.bytesToHex)((0, sha3_1.keccak_256)(lowerAddress)); | ||
var ret = '0x'; | ||
@@ -26,1 +30,10 @@ for (var i = 0; i < lowerAddress.length; i++) { | ||
exports.isEIP55Address = isEIP55Address; | ||
const parseIntegerNumber = (number) => { | ||
const parsed = parseInt(number); | ||
if (parsed === NaN) | ||
throw new Error("Invalid number."); | ||
if (parsed === Infinity) | ||
throw new Error("Invalid number."); | ||
return parsed; | ||
}; | ||
exports.parseIntegerNumber = parseIntegerNumber; |
import apgApi from "apg-js/src/apg-api/api"; | ||
import apgLib from "apg-js/src/apg-lib/node-exports"; | ||
import { isEIP55Address } from "./utils"; | ||
import { isEIP55Address, parseIntegerNumber } from "./utils"; | ||
@@ -147,2 +147,18 @@ const GRAMMAR = ` | ||
class GrammarApi { | ||
static grammarObj = this.generateApi(); | ||
static generateApi() { | ||
const api = new apgApi(GRAMMAR); | ||
api.generate(); | ||
if (api.errors.length) { | ||
console.error(api.errorsToAscii()); | ||
console.error(api.linesToAscii()); | ||
console.log(api.displayAttributeErrors()); | ||
throw new Error(`ABNF grammar has errors`); | ||
} | ||
return api.toObject(); | ||
} | ||
} | ||
export class ParsedMessage { | ||
@@ -163,12 +179,2 @@ domain: string; | ||
constructor(msg: string) { | ||
const api = new apgApi(GRAMMAR); | ||
api.generate(); | ||
if (api.errors.length) { | ||
console.error(api.errorsToAscii()); | ||
console.error(api.linesToAscii()); | ||
console.log(api.displayAttributeErrors()); | ||
throw new Error(`ABNF grammar has errors`); | ||
} | ||
const grammarObj = api.toObject(); | ||
const parser = new apgLib.parser(); | ||
@@ -244,3 +250,3 @@ parser.ast = new apgLib.ast(); | ||
if (state === id.SEM_PRE) { | ||
data.chainId = parseInt( | ||
data.chainId = parseIntegerNumber( | ||
apgLib.utils.charsToString(chars, phraseIndex, phraseLength) | ||
@@ -330,3 +336,3 @@ ); | ||
const result = parser.parse(grammarObj, "sign-in-with-ethereum", msg); | ||
const result = parser.parse(GrammarApi.grammarObj, "sign-in-with-ethereum", msg); | ||
if (!result.success) { | ||
@@ -333,0 +339,0 @@ throw new Error(`Invalid message: ${JSON.stringify(result)}`); |
@@ -39,36 +39,1 @@ const parsingPositive: Object = require("../../../test/parsing_positive.json"); | ||
}); | ||
describe("Successfully parses with RegExp Client", () => { | ||
let ParsedMessage; | ||
beforeEach( | ||
async () => (ParsedMessage = (await import("./regex")).ParsedMessage) | ||
); | ||
test.concurrent.each(Object.entries(parsingPositive))( | ||
"Parses message successfully: %s", | ||
(test_name, test) => { | ||
const parsedMessage = new ParsedMessage(test.message); | ||
for (const [field, value] of Object.entries(test.fields)) { | ||
if (typeof value === "object") { | ||
expect(parsedMessage[field]).toStrictEqual(value); | ||
} else { | ||
expect(parsedMessage[field]).toBe(value); | ||
} | ||
} | ||
} | ||
); | ||
}); | ||
describe("Successfully fails with RegExp Client", () => { | ||
let ParsedMessage; | ||
beforeEach( | ||
async () => (ParsedMessage = (await import(`./regex`)).ParsedMessage) | ||
); | ||
test.concurrent.each(Object.entries(parsingNegative))( | ||
"Fails to parse message: %s", | ||
(test_name, test) => { | ||
expect(() => new ParsedMessage(test)).toThrow(); | ||
} | ||
); | ||
}); |
import { ParsedMessage as ABNFParsedMessage } from "./abnf"; | ||
import { ParsedMessage as RegExpParsedMessage } from "./regex"; | ||
export * from './utils'; | ||
export { | ||
ABNFParsedMessage as ParsedMessage, | ||
RegExpParsedMessage as ParsedMessageRegExp, | ||
ABNFParsedMessage as ParsedMessage | ||
}; | ||
@@ -0,1 +1,3 @@ | ||
import { keccak_256 } from '@noble/hashes/sha3'; | ||
import { bytesToHex } from '@noble/hashes/utils'; | ||
/** | ||
@@ -7,12 +9,15 @@ * This method is supposed to check if an address is conforming to EIP-55. | ||
export const isEIP55Address = (address: string) => { | ||
const createKeccakHash = require('keccak') | ||
const lowerAddress = `${address}`.toLowerCase().replace('0x', '') | ||
var hash = createKeccakHash('keccak256').update(lowerAddress).digest('hex') | ||
var ret = '0x' | ||
if(address.length != 42) { | ||
return false; | ||
} | ||
const lowerAddress = `${address}`.toLowerCase().replace('0x', ''); | ||
var hash = bytesToHex(keccak_256(lowerAddress)); | ||
var ret = '0x'; | ||
for (var i = 0; i < lowerAddress.length; i++) { | ||
if (parseInt(hash[i], 16) >= 8) { | ||
ret += lowerAddress[i].toUpperCase() | ||
ret += lowerAddress[i].toUpperCase(); | ||
} else { | ||
ret += lowerAddress[i] | ||
ret += lowerAddress[i]; | ||
} | ||
@@ -22,1 +27,8 @@ } | ||
} | ||
export const parseIntegerNumber = (number: string): number => { | ||
const parsed = parseInt(number); | ||
if(parsed === NaN) throw new Error("Invalid number."); | ||
if(parsed === Infinity) throw new Error("Invalid number."); | ||
return parsed; | ||
} |
{ | ||
"name": "@spruceid/siwe-parser", | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"description": "Parse Messages that conform to EIP-4361: Sign-In with Ethereum (SIWE)", | ||
@@ -30,3 +30,3 @@ "main": "dist/parsers.js", | ||
"peerDependencies": { | ||
"keccak": "^3.0.2" | ||
"@noble/hashes": "^1.1.2" | ||
}, | ||
@@ -40,2 +40,2 @@ "repository": { | ||
} | ||
} | ||
} |
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
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
0
0
35675
17
890
1