@planetarium/account
Version:
Libplanet accounts for JavaScript/TypeScript
371 lines (362 loc) • 11.8 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
}) : x)(function(x) {
if (typeof require !== "undefined")
return require.apply(this, arguments);
throw new Error('Dynamic require of "' + x + '" is not supported');
});
var __accessCheck = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
var __privateGet = (obj, member, getter) => {
__accessCheck(obj, member, "read from private field");
return getter ? getter.call(obj) : member.get(obj);
};
var __privateAdd = (obj, member, value) => {
if (member.has(obj))
throw TypeError("Cannot add the same private member more than once");
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
var __privateSet = (obj, member, value, setter) => {
__accessCheck(obj, member, "write to private field");
setter ? setter.call(obj, value) : member.set(obj, value);
return value;
};
var __privateMethod = (obj, member, method) => {
__accessCheck(obj, member, "access private method");
return method;
};
// src/Account.ts
function isAccount(account) {
return typeof account === "object" && account != null && "getAddress" in account && account.getAddress instanceof Function && "getPublicKey" in account && account.getPublicKey instanceof Function && "sign" in account && account.sign instanceof Function;
}
__name(isAccount, "isAccount");
// src/Address.ts
import { Buffer as Buffer3 } from "buffer";
import { keccak_256 } from "@noble/hashes/sha3";
// src/PublicKey.ts
import { Buffer as Buffer2 } from "buffer";
import * as secp256k12 from "@noble/secp256k1";
// src/Message.ts
import { sha256 } from "@noble/hashes/sha256";
async function hashMessage(message) {
return sha256(message);
}
__name(hashMessage, "hashMessage");
// src/Signature.ts
import * as secp256k1 from "@noble/secp256k1";
var Signature2 = class {
#signature;
constructor(signature) {
if (signature.hasHighS())
throw new RangeError(
"A signature with high S is unsupported; normalize it to get rid of high S"
);
this.#signature = signature;
}
static fromBytes(bytes) {
return new Signature2(secp256k1.Signature.fromDER(bytes));
}
static fromHex(hex) {
return new Signature2(secp256k1.Signature.fromDER(hex));
}
toBytes() {
return this.#signature.toDERRawBytes();
}
toHex() {
return this.#signature.toDERHex();
}
toString() {
return this.toHex();
}
[Symbol.for("nodejs.util.inspect.custom")]() {
return `Signature { ${this.toHex()} }`;
}
};
__name(Signature2, "Signature");
var Signature_default = Signature2;
// src/PublicKey.ts
var PublicKey = class {
#point;
constructor(point) {
this.#point = point;
}
static fromBytes(bytes, form) {
if (!(bytes instanceof Uint8Array)) {
throw new Error(`Expected a Uint8Array, but got ${typeof bytes}`);
}
const header = bytes[0];
if (form === "compressed") {
if (bytes.length !== 33) {
throw new Error(
`Invalid compressed public key: expected 33 bytes, but got ${bytes.length} bytes`
);
} else if (header !== 2 && header !== 3) {
throw new Error(
`Invalid compressed public key: expected either 0x02 or 0x03 as the header, but got 0x${header.toString(16).padStart(2, "0")}`
);
}
} else if (form === "uncompressed") {
if (bytes.length !== 65) {
throw new Error(
`Invalid uncompressed public key expected 65 bytes, but got ${bytes.length} bytes`
);
} else if (header !== 4) {
throw new Error(
`Invalid compressed public key: expected 0x04 as the header, but got 0x${header.toString(16).padStart(2, "0")}`
);
}
} else {
throw new Error(
"Invalid public key form: choose 'compressed' or 'uncompressed'"
);
}
return new PublicKey(secp256k12.Point.fromHex(bytes));
}
// TODO: more explicit length checking
static fromHex(hex, form) {
if (typeof hex !== "string") {
throw new Error(`Expected a string, but got ${typeof hex}`);
} else if (form === "compressed" && hex.length !== 66) {
throw new Error(
`Invalid compressed public key: expected 33 hexadigits, but got ${hex.length} hexadigits`
);
} else if (form === "uncompressed" && hex.length !== 130) {
throw new Error(
`Invalid uncompressed public key expected 130 hexadigits, but got ${hex.length} hexadigits`
);
}
const bytes = new Uint8Array(Buffer2.from(hex, "hex"));
return this.fromBytes(bytes, form);
}
async verify(message, signature) {
if (!(message instanceof Uint8Array)) {
throw new Error(`Expected Uint8Array, but got ${typeof message}`);
} else if (!(signature instanceof Signature_default)) {
throw new Error(`Expected Signature, but got ${typeof signature}`);
}
const msgHash = await hashMessage(message);
return secp256k12.verify(signature.toBytes(), msgHash, this.#point);
}
toBytes(form) {
if (form !== "compressed" && form !== "uncompressed") {
throw new Error(
"Invalid public key form: choose 'compressed' or 'uncompressed'"
);
}
return this.#point.toRawBytes(form === "compressed");
}
toHex(form) {
if (form !== "compressed" && form !== "uncompressed") {
throw new Error(
"Invalid public key form: choose 'compressed' or 'uncompressed'"
);
}
return this.#point.toHex(form === "compressed");
}
equals(other) {
return other instanceof PublicKey && this.#point.equals(other.#point);
}
};
__name(PublicKey, "PublicKey");
var PublicKey_default = PublicKey;
// src/Address.ts
if (typeof globalThis.TextEncoder === "undefined") {
globalThis.TextEncoder = __require("node:util").TextEncoder;
}
function toHex(bytes) {
let hex = "";
for (let i = 0; i < bytes.length; i++) {
hex += bytes[i].toString(16).padStart(2, "0");
}
return hex;
}
__name(toHex, "toHex");
function checksum(hex) {
hex = hex.toLowerCase();
const hexAsciiIntoBytes = new TextEncoder().encode(hex);
const hashedAddr = toHex(keccak_256(hexAsciiIntoBytes));
let checksum2 = "";
for (let nibbleIdx = 0; nibbleIdx < hex.length; nibbleIdx++) {
const nibbleHex = hex.charAt(nibbleIdx);
if (nibbleHex.match(/^[0-9]$/)) {
checksum2 += nibbleHex;
continue;
} else {
const nibble = parseInt(hashedAddr.charAt(nibbleIdx), 16);
checksum2 += nibble > 7 ? nibbleHex.toUpperCase() : nibbleHex;
}
}
return checksum2;
}
__name(checksum, "checksum");
var _bytes, _deriveFrom, deriveFrom_fn;
var _Address = class {
constructor(bytes) {
__privateAdd(this, _bytes, void 0);
__privateSet(this, _bytes, bytes);
}
static deriveFrom(publicKey) {
if (isAccount(publicKey)) {
return publicKey.getPublicKey().then(__privateMethod(this, _deriveFrom, deriveFrom_fn));
} else if (publicKey instanceof PublicKey) {
return __privateMethod(this, _deriveFrom, deriveFrom_fn).call(this, publicKey);
}
throw new Error(
`Expected either PublicKey or Account, got ${typeof publicKey}`
);
}
static fromHex(hex, ignoreChecksum = false) {
if (typeof hex !== "string") {
throw new Error(`Expected a string, but ${typeof hex} was given.`);
} else if (!hex.match(/^(0x)?[0-9a-f]{40}$/i)) {
throw new Error(
`Expected a string of 40 hexadecimals, but ${JSON.stringify(
hex
)} was given.`
);
}
if (hex.match(/^0x/i)) {
hex = hex.slice(2);
}
const addr = new _Address(new Uint8Array(Buffer3.from(hex, "hex")));
if (ignoreChecksum) {
return addr;
}
const expectedChecksum = checksum(hex);
if (expectedChecksum !== hex) {
throw new Error(
`Expected checksum is 0x${expectedChecksum}, but 0x${hex} was given.`
);
}
return addr;
}
static fromBytes(bytes) {
if (!(bytes instanceof Uint8Array)) {
throw new Error(`Expected a Uint8Array, but ${typeof bytes} was given.`);
}
if (bytes.length !== 20) {
throw new Error(
`Expected 20 bytes, but ${bytes.length} bytes were given.`
);
}
return new _Address(bytes);
}
toBytes() {
return __privateGet(this, _bytes);
}
toHex(casing = "checksum") {
const hex = toHex(__privateGet(this, _bytes));
return casing === "checksum" ? checksum(hex) : hex;
}
equals(other) {
if (!(other instanceof _Address))
return false;
for (let i = 0; i < 20; i++) {
if (__privateGet(this, _bytes)[i] !== __privateGet(other, _bytes)[i])
return false;
}
return true;
}
isAddressOf(publicKey) {
return _Address.deriveFrom(publicKey).equals(this);
}
toString() {
return `0x${this.toHex()}`;
}
};
var Address = _Address;
__name(Address, "Address");
_bytes = new WeakMap();
_deriveFrom = new WeakSet();
deriveFrom_fn = /* @__PURE__ */ __name(function(publicKey) {
const pub = publicKey.toBytes("uncompressed").slice(1);
const digest = keccak_256(pub);
const addr = digest.slice(digest.length - 20);
return new _Address(addr);
}, "#deriveFrom");
__privateAdd(Address, _deriveFrom);
var Address_default = Address;
// src/RawPrivateKey.ts
import { Buffer as Buffer4 } from "buffer";
import * as secp256k13 from "@noble/secp256k1";
var RawPrivateKey = class {
#privatePart;
#publicPart;
constructor(privatePart) {
this.#privatePart = privatePart;
}
static fromBytes(bytes) {
if (!(bytes instanceof Uint8Array)) {
throw new Error(`Expected Uint8Array, but got ${typeof bytes}`);
} else if (bytes.length !== 32) {
throw new Error(
`Incorrect private key length; expected 32 bytes, but got ${bytes.length} bytes`
);
} else if (!secp256k13.utils.isValidPrivateKey(bytes)) {
throw new Error("Invalid private key");
}
return new RawPrivateKey(new Uint8Array(bytes));
}
static fromHex(hex) {
if (typeof hex !== "string") {
throw new Error(`Expected string, but got ${typeof hex}`);
} else if (hex.length !== 64) {
throw new Error(
`Incorrect private key length; expected 64 hexadigits, but got ${hex.length} hexadigits`
);
}
const bytes = new Uint8Array(Buffer4.from(hex, "hex"));
if (!secp256k13.utils.isValidPrivateKey(bytes)) {
throw new Error("Invalid private key");
}
return new RawPrivateKey(bytes);
}
static generate() {
return this.fromBytes(secp256k13.utils.randomPrivateKey());
}
getAddress() {
return Promise.resolve(Address_default.deriveFrom(this.publicKey));
}
/**
* @deprecated Use {@link getPublicKey()} instead.
*/
get publicKey() {
if (typeof this.#publicPart === "undefined") {
this.#publicPart = PublicKey_default.fromBytes(
secp256k13.getPublicKey(this.#privatePart),
"uncompressed"
);
}
return this.#publicPart;
}
getPublicKey() {
return Promise.resolve(this.publicKey);
}
async sign(message) {
const sig = await secp256k13.sign(
await hashMessage(message),
this.#privatePart,
{ der: true }
);
return Signature_default.fromBytes(sig);
}
exportPrivateKey() {
return Promise.resolve(this);
}
toBytes() {
return new Uint8Array(this.#privatePart);
}
};
__name(RawPrivateKey, "RawPrivateKey");
export {
Address,
PublicKey,
RawPrivateKey,
Signature2 as Signature
};
/*! For license information please see index.js.LEGAL.txt */
//# sourceMappingURL=index.js.map