@meshsdk/wallet
Version:
Wallets - https://meshjs.dev/apis/wallets
1,409 lines (1,401 loc) • 75.7 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// ../../node_modules/base32-encoding/index.js
var require_base32_encoding = __commonJS({
"../../node_modules/base32-encoding/index.js"(exports2) {
"use strict";
var std = "23456789abcdefghijkmnpqrstuvwxyz";
exports2.stringify = function(buf, alphabet2) {
if (alphabet2 == null) alphabet2 = std;
return from(base322(buf), (b) => alphabet2[b]).join("");
};
exports2.parse = function(str, alphabet2) {
if (alphabet2 == null) alphabet2 = std;
return base256(str.split("").map((s) => alphabet2.indexOf(s)));
};
function from(buf, map) {
var a = new Array(buf.length);
for (var i = 0; i < a.length; i++) {
a[i] = map(buf[i]);
}
return a;
}
exports2.encode = base322;
function base322(buf, arr, offset) {
exports2.encode.bytes = Math.ceil(buf.length * 8 / 5);
if (arr == null) arr = Buffer.alloc(exports2.encode.bytes);
if (offset == null) offset = 0;
for (var i = 0, j = offset; i + 5 <= buf.length; i += 5, j += 8) {
arr[j + 0] = (buf[i + 0] & 248) >>> 3;
arr[j + 1] = (buf[i + 0] & 7) << 2 | (buf[i + 1] & 192) >>> 6;
arr[j + 2] = (buf[i + 1] & 62) >>> 1;
arr[j + 3] = (buf[i + 1] & 1) << 4 | (buf[i + 2] & 240) >>> 4;
arr[j + 4] = (buf[i + 2] & 15) << 1 | (buf[i + 3] & 128) >>> 7;
arr[j + 5] = (buf[i + 3] & 124) >>> 2;
arr[j + 6] = (buf[i + 3] & 3) << 3 | (buf[i + 4] & 224) >>> 5;
arr[j + 7] = buf[i + 4] & 31;
}
switch (buf.length - i) {
// No need for 5 since we work in batches of 5 above
case 4:
arr[j + 4] |= (buf[i + 3] & 128) >>> 7;
arr[j + 5] |= (buf[i + 3] & 124) >>> 2;
arr[j + 6] |= (buf[i + 3] & 3) << 3;
case 3:
arr[j + 3] |= (buf[i + 2] & 240) >>> 4;
arr[j + 4] |= (buf[i + 2] & 15) << 1;
case 2:
arr[j + 1] |= (buf[i + 1] & 192) >>> 6;
arr[j + 2] |= (buf[i + 1] & 62) >>> 1;
arr[j + 3] |= (buf[i + 1] & 1) << 4;
case 1:
arr[j + 0] |= (buf[i + 0] & 248) >>> 3;
arr[j + 1] |= (buf[i + 0] & 7) << 2;
}
return arr;
}
exports2.decode = base256;
function base256(buf, arr, offset) {
exports2.decode.bytes = Math.floor(buf.length * 5 / 8);
if (arr == null) arr = Buffer.alloc(exports2.decode.bytes);
if (offset == null) offset = 0;
for (var i = 0, j = offset; i + 8 <= buf.length; i += 8, j += 5) {
arr[j + 0] = buf[i + 0] << 3 & 255 | buf[i + 1] >>> 2 & 255;
arr[j + 1] = buf[i + 1] << 6 & 255 | buf[i + 2] << 1 & 255 | buf[i + 3] >>> 4 & 255;
arr[j + 2] = buf[i + 3] << 4 & 255 | buf[i + 4] >>> 1 & 255;
arr[j + 3] = buf[i + 4] << 7 & 255 | buf[i + 5] << 2 & 255 | buf[i + 6] >> 3 & 255;
arr[j + 4] = buf[i + 6] << 5 & 255 | buf[i + 7] & 255;
}
switch (buf.length - i) {
case 7:
arr[j + 3] |= buf[i + 6] >> 3 & 255;
arr[j + 4] |= buf[i + 6] << 5 & 255;
case 6:
arr[j + 3] |= buf[i + 5] << 2 & 255;
case 5:
arr[j + 2] |= buf[i + 4] >>> 1 & 255;
arr[j + 3] |= buf[i + 4] << 7 & 255;
case 4:
arr[j + 1] |= buf[i + 3] >>> 4 & 255;
arr[j + 2] |= buf[i + 3] << 4 & 255;
case 3:
arr[j + 1] |= buf[i + 2] << 1 & 255;
case 2:
arr[j + 0] |= buf[i + 1] >>> 2 & 255;
arr[j + 1] |= buf[i + 1] << 6 & 255;
case 1:
arr[j + 0] |= buf[i + 0] << 3 & 255;
}
return arr;
}
exports2.encodingLength = function(buf) {
return Math.ceil(buf.length * 8 / 5);
};
}
});
// ../../node_modules/bech32/dist/index.js
var require_dist = __commonJS({
"../../node_modules/bech32/dist/index.js"(exports2) {
"use strict";
Object.defineProperty(exports2, "__esModule", { value: true });
exports2.bech32m = exports2.bech32 = void 0;
var ALPHABET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
var ALPHABET_MAP = {};
for (let z = 0; z < ALPHABET.length; z++) {
const x = ALPHABET.charAt(z);
ALPHABET_MAP[x] = z;
}
function polymodStep(pre) {
const b = pre >> 25;
return (pre & 33554431) << 5 ^ -(b >> 0 & 1) & 996825010 ^ -(b >> 1 & 1) & 642813549 ^ -(b >> 2 & 1) & 513874426 ^ -(b >> 3 & 1) & 1027748829 ^ -(b >> 4 & 1) & 705979059;
}
function prefixChk(prefix) {
let chk = 1;
for (let i = 0; i < prefix.length; ++i) {
const c = prefix.charCodeAt(i);
if (c < 33 || c > 126)
return "Invalid prefix (" + prefix + ")";
chk = polymodStep(chk) ^ c >> 5;
}
chk = polymodStep(chk);
for (let i = 0; i < prefix.length; ++i) {
const v = prefix.charCodeAt(i);
chk = polymodStep(chk) ^ v & 31;
}
return chk;
}
function convert(data, inBits, outBits, pad) {
let value = 0;
let bits = 0;
const maxV = (1 << outBits) - 1;
const result = [];
for (let i = 0; i < data.length; ++i) {
value = value << inBits | data[i];
bits += inBits;
while (bits >= outBits) {
bits -= outBits;
result.push(value >> bits & maxV);
}
}
if (pad) {
if (bits > 0) {
result.push(value << outBits - bits & maxV);
}
} else {
if (bits >= inBits)
return "Excess padding";
if (value << outBits - bits & maxV)
return "Non-zero padding";
}
return result;
}
function toWords(bytes) {
return convert(bytes, 8, 5, true);
}
function fromWordsUnsafe(words) {
const res = convert(words, 5, 8, false);
if (Array.isArray(res))
return res;
}
function fromWords(words) {
const res = convert(words, 5, 8, false);
if (Array.isArray(res))
return res;
throw new Error(res);
}
function getLibraryFromEncoding(encoding) {
let ENCODING_CONST;
if (encoding === "bech32") {
ENCODING_CONST = 1;
} else {
ENCODING_CONST = 734539939;
}
function encode(prefix, words, LIMIT) {
LIMIT = LIMIT || 90;
if (prefix.length + 7 + words.length > LIMIT)
throw new TypeError("Exceeds length limit");
prefix = prefix.toLowerCase();
let chk = prefixChk(prefix);
if (typeof chk === "string")
throw new Error(chk);
let result = prefix + "1";
for (let i = 0; i < words.length; ++i) {
const x = words[i];
if (x >> 5 !== 0)
throw new Error("Non 5-bit word");
chk = polymodStep(chk) ^ x;
result += ALPHABET.charAt(x);
}
for (let i = 0; i < 6; ++i) {
chk = polymodStep(chk);
}
chk ^= ENCODING_CONST;
for (let i = 0; i < 6; ++i) {
const v = chk >> (5 - i) * 5 & 31;
result += ALPHABET.charAt(v);
}
return result;
}
function __decode(str, LIMIT) {
LIMIT = LIMIT || 90;
if (str.length < 8)
return str + " too short";
if (str.length > LIMIT)
return "Exceeds length limit";
const lowered = str.toLowerCase();
const uppered = str.toUpperCase();
if (str !== lowered && str !== uppered)
return "Mixed-case string " + str;
str = lowered;
const split = str.lastIndexOf("1");
if (split === -1)
return "No separator character for " + str;
if (split === 0)
return "Missing prefix for " + str;
const prefix = str.slice(0, split);
const wordChars = str.slice(split + 1);
if (wordChars.length < 6)
return "Data too short";
let chk = prefixChk(prefix);
if (typeof chk === "string")
return chk;
const words = [];
for (let i = 0; i < wordChars.length; ++i) {
const c = wordChars.charAt(i);
const v = ALPHABET_MAP[c];
if (v === void 0)
return "Unknown character " + c;
chk = polymodStep(chk) ^ v;
if (i + 6 >= wordChars.length)
continue;
words.push(v);
}
if (chk !== ENCODING_CONST)
return "Invalid checksum for " + str;
return { prefix, words };
}
function decodeUnsafe(str, LIMIT) {
const res = __decode(str, LIMIT);
if (typeof res === "object")
return res;
}
function decode(str, LIMIT) {
const res = __decode(str, LIMIT);
if (typeof res === "object")
return res;
throw new Error(res);
}
return {
decodeUnsafe,
decode,
encode,
toWords,
fromWordsUnsafe,
fromWords
};
}
exports2.bech32 = getLibraryFromEncoding("bech32");
exports2.bech32m = getLibraryFromEncoding("bech32m");
}
});
// src/index.ts
var index_exports = {};
__export(index_exports, {
AppWallet: () => AppWallet,
BrowserWallet: () => BrowserWallet,
EmbeddedWallet: () => EmbeddedWallet,
MeshWallet: () => MeshWallet,
WalletStaticMethods: () => WalletStaticMethods,
connect: () => connect,
login: () => login,
register: () => register
});
module.exports = __toCommonJS(index_exports);
// src/app/index.ts
var import_core_cst2 = require("@meshsdk/core-cst");
// ../../node_modules/@scure/base/lib/esm/index.js
function isBytes(a) {
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
}
function isArrayOf(isString, arr) {
if (!Array.isArray(arr))
return false;
if (arr.length === 0)
return true;
if (isString) {
return arr.every((item) => typeof item === "string");
} else {
return arr.every((item) => Number.isSafeInteger(item));
}
}
function afn(input) {
if (typeof input !== "function")
throw new Error("function expected");
return true;
}
function astr(label, input) {
if (typeof input !== "string")
throw new Error(`${label}: string expected`);
return true;
}
function anumber(n) {
if (!Number.isSafeInteger(n))
throw new Error(`invalid integer: ${n}`);
}
function aArr(input) {
if (!Array.isArray(input))
throw new Error("array expected");
}
function astrArr(label, input) {
if (!isArrayOf(true, input))
throw new Error(`${label}: array of strings expected`);
}
function anumArr(label, input) {
if (!isArrayOf(false, input))
throw new Error(`${label}: array of numbers expected`);
}
// @__NO_SIDE_EFFECTS__
function chain(...args) {
const id = (a) => a;
const wrap = (a, b) => (c) => a(b(c));
const encode = args.map((x) => x.encode).reduceRight(wrap, id);
const decode = args.map((x) => x.decode).reduce(wrap, id);
return { encode, decode };
}
// @__NO_SIDE_EFFECTS__
function alphabet(letters) {
const lettersA = typeof letters === "string" ? letters.split("") : letters;
const len = lettersA.length;
astrArr("alphabet", lettersA);
const indexes = new Map(lettersA.map((l, i) => [l, i]));
return {
encode: (digits) => {
aArr(digits);
return digits.map((i) => {
if (!Number.isSafeInteger(i) || i < 0 || i >= len)
throw new Error(`alphabet.encode: digit index outside alphabet "${i}". Allowed: ${letters}`);
return lettersA[i];
});
},
decode: (input) => {
aArr(input);
return input.map((letter) => {
astr("alphabet.decode", letter);
const i = indexes.get(letter);
if (i === void 0)
throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`);
return i;
});
}
};
}
// @__NO_SIDE_EFFECTS__
function join(separator = "") {
astr("join", separator);
return {
encode: (from) => {
astrArr("join.decode", from);
return from.join(separator);
},
decode: (to) => {
astr("join.decode", to);
return to.split(separator);
}
};
}
var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
var radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
var powers = /* @__PURE__ */ (() => {
let res = [];
for (let i = 0; i < 40; i++)
res.push(2 ** i);
return res;
})();
function convertRadix2(data, from, to, padding) {
aArr(data);
if (from <= 0 || from > 32)
throw new Error(`convertRadix2: wrong from=${from}`);
if (to <= 0 || to > 32)
throw new Error(`convertRadix2: wrong to=${to}`);
if (/* @__PURE__ */ radix2carry(from, to) > 32) {
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${/* @__PURE__ */ radix2carry(from, to)}`);
}
let carry = 0;
let pos = 0;
const max = powers[from];
const mask = powers[to] - 1;
const res = [];
for (const n of data) {
anumber(n);
if (n >= max)
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
carry = carry << from | n;
if (pos + from > 32)
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
pos += from;
for (; pos >= to; pos -= to)
res.push((carry >> pos - to & mask) >>> 0);
const pow = powers[pos];
if (pow === void 0)
throw new Error("invalid carry");
carry &= pow - 1;
}
carry = carry << to - pos & mask;
if (!padding && pos >= from)
throw new Error("Excess padding");
if (!padding && carry > 0)
throw new Error(`Non-zero padding: ${carry}`);
if (padding && pos > 0)
res.push(carry >>> 0);
return res;
}
// @__NO_SIDE_EFFECTS__
function radix2(bits, revPadding = false) {
anumber(bits);
if (bits <= 0 || bits > 32)
throw new Error("radix2: bits should be in (0..32]");
if (/* @__PURE__ */ radix2carry(8, bits) > 32 || /* @__PURE__ */ radix2carry(bits, 8) > 32)
throw new Error("radix2: carry overflow");
return {
encode: (bytes) => {
if (!isBytes(bytes))
throw new Error("radix2.encode input should be Uint8Array");
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
},
decode: (digits) => {
anumArr("radix2.decode", digits);
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
}
};
}
function unsafeWrapper(fn) {
afn(fn);
return function(...args) {
try {
return fn.apply(null, args);
} catch (e) {
}
};
}
var BECH_ALPHABET = /* @__PURE__ */ chain(/* @__PURE__ */ alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ join(""));
var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
function bech32Polymod(pre) {
const b = pre >> 25;
let chk = (pre & 33554431) << 5;
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
if ((b >> i & 1) === 1)
chk ^= POLYMOD_GENERATORS[i];
}
return chk;
}
function bechChecksum(prefix, words, encodingConst = 1) {
const len = prefix.length;
let chk = 1;
for (let i = 0; i < len; i++) {
const c = prefix.charCodeAt(i);
if (c < 33 || c > 126)
throw new Error(`Invalid prefix (${prefix})`);
chk = bech32Polymod(chk) ^ c >> 5;
}
chk = bech32Polymod(chk);
for (let i = 0; i < len; i++)
chk = bech32Polymod(chk) ^ prefix.charCodeAt(i) & 31;
for (let v of words)
chk = bech32Polymod(chk) ^ v;
for (let i = 0; i < 6; i++)
chk = bech32Polymod(chk);
chk ^= encodingConst;
return BECH_ALPHABET.encode(convertRadix2([chk % powers[30]], 30, 5, false));
}
// @__NO_SIDE_EFFECTS__
function genBech32(encoding) {
const ENCODING_CONST = encoding === "bech32" ? 1 : 734539939;
const _words = /* @__PURE__ */ radix2(5);
const fromWords = _words.decode;
const toWords = _words.encode;
const fromWordsUnsafe = unsafeWrapper(fromWords);
function encode(prefix, words, limit = 90) {
astr("bech32.encode prefix", prefix);
if (isBytes(words))
words = Array.from(words);
anumArr("bech32.encode", words);
const plen = prefix.length;
if (plen === 0)
throw new TypeError(`Invalid prefix length ${plen}`);
const actualLength = plen + 7 + words.length;
if (limit !== false && actualLength > limit)
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
const lowered = prefix.toLowerCase();
const sum = bechChecksum(lowered, words, ENCODING_CONST);
return `${lowered}1${BECH_ALPHABET.encode(words)}${sum}`;
}
function decode(str, limit = 90) {
astr("bech32.decode input", str);
const slen = str.length;
if (slen < 8 || limit !== false && slen > limit)
throw new TypeError(`invalid string length: ${slen} (${str}). Expected (8..${limit})`);
const lowered = str.toLowerCase();
if (str !== lowered && str !== str.toUpperCase())
throw new Error(`String must be lowercase or uppercase`);
const sepIndex = lowered.lastIndexOf("1");
if (sepIndex === 0 || sepIndex === -1)
throw new Error(`Letter "1" must be present between prefix and data only`);
const prefix = lowered.slice(0, sepIndex);
const data = lowered.slice(sepIndex + 1);
if (data.length < 6)
throw new Error("Data must be at least 6 characters long");
const words = BECH_ALPHABET.decode(data).slice(0, -6);
const sum = bechChecksum(prefix, words, ENCODING_CONST);
if (!data.endsWith(sum))
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
return { prefix, words };
}
const decodeUnsafe = unsafeWrapper(decode);
function decodeToBytes(str) {
const { prefix, words } = decode(str, false);
return { prefix, words, bytes: fromWords(words) };
}
function encodeFromBytes(prefix, bytes) {
return encode(prefix, toWords(bytes));
}
return {
encode,
decode,
encodeFromBytes,
decodeToBytes,
decodeUnsafe,
fromWords,
fromWordsUnsafe,
toWords
};
}
var bech32 = /* @__PURE__ */ genBech32("bech32");
// src/embedded/index.ts
var import_common = require("@meshsdk/common");
var import_core_cst = require("@meshsdk/core-cst");
var WalletStaticMethods = class {
static privateKeyBech32ToPrivateKeyHex(_bech32) {
const bech32DecodedBytes = bech32.decodeToBytes(_bech32).bytes;
const bip32PrivateKey = import_core_cst.Bip32PrivateKey.fromBytes(bech32DecodedBytes);
return (0, import_common.bytesToHex)(bip32PrivateKey.bytes());
}
static mnemonicToPrivateKeyHex(words) {
const entropy = (0, import_common.mnemonicToEntropy)(words.join(" "));
const bip32PrivateKey = (0, import_core_cst.buildBip32PrivateKey)(entropy);
return (0, import_common.bytesToHex)(bip32PrivateKey.bytes());
}
static signingKeyToHexes(paymentKey, stakeKey) {
return [
paymentKey.startsWith("5820") ? paymentKey.slice(4) : paymentKey,
stakeKey.startsWith("5820") ? stakeKey.slice(4) : stakeKey
];
}
static bip32BytesToPrivateKeyHex(bip32Bytes) {
const bip32PrivateKey = import_core_cst.Bip32PrivateKey.fromBytes(bip32Bytes);
return (0, import_common.bytesToHex)(bip32PrivateKey.bytes());
}
static getAddresses(paymentKey, stakingKey, networkId = 0) {
const baseAddress = (0, import_core_cst.buildBaseAddress)(
networkId,
import_core_cst.Hash28ByteBase16.fromEd25519KeyHashHex(
paymentKey.toPublic().hash().hex()
),
import_core_cst.Hash28ByteBase16.fromEd25519KeyHashHex(
stakingKey.toPublic().hash().hex()
)
).toAddress();
const enterpriseAddress = (0, import_core_cst.buildEnterpriseAddress)(
networkId,
import_core_cst.Hash28ByteBase16.fromEd25519KeyHashHex(
paymentKey.toPublic().hash().hex()
)
).toAddress();
const rewardAddress = (0, import_core_cst.buildRewardAddress)(
networkId,
import_core_cst.Hash28ByteBase16.fromEd25519KeyHashHex(
stakingKey.toPublic().hash().hex()
)
).toAddress();
return {
baseAddress,
enterpriseAddress,
rewardAddress
};
}
static getDRepKey(dRepKey, networkId = 0) {
const pubDRepKey = dRepKey.toPublic().hex().toString();
const dRepIDBech32 = (0, import_core_cst.buildDRepID)(
(0, import_core_cst.Ed25519PublicKeyHex)(pubDRepKey),
networkId
);
const dRep = import_core_cst.DRep.newKeyHash(dRepKey.toPublic().hash().hex());
const dRepIDHash = dRep.toKeyHash();
const dRepIDCip105 = (0, import_core_cst.hexToBech32)("drep", dRepIDHash);
return {
pubDRepKey,
dRepIDBech32,
dRepIDHash,
dRepIDCip105
};
}
static generateMnemonic(strength = 256) {
const mnemonic = (0, import_common.generateMnemonic)(strength);
return mnemonic.split(" ");
}
static addWitnessSets(txHex, witnesses) {
let tx = (0, import_core_cst.deserializeTx)(txHex);
let witnessSet = tx.witnessSet();
let witnessSetVkeys = witnessSet.vkeys();
let witnessSetVkeysValues = witnessSetVkeys ? [...witnessSetVkeys.values(), ...witnesses] : witnesses;
witnessSet.setVkeys(
import_core_cst.Serialization.CborSet.fromCore(
witnessSetVkeysValues.map((vkw) => vkw.toCore()),
import_core_cst.VkeyWitness.fromCore
)
);
return new import_core_cst.Transaction(tx.body(), witnessSet, tx.auxiliaryData()).toCbor();
}
};
var EmbeddedWallet = class extends WalletStaticMethods {
_walletSecret;
_networkId;
cryptoIsReady = false;
constructor(options) {
super();
this._networkId = options.networkId;
switch (options.key.type) {
case "mnemonic":
this._walletSecret = WalletStaticMethods.mnemonicToPrivateKeyHex(
options.key.words
);
break;
case "root":
this._walletSecret = WalletStaticMethods.privateKeyBech32ToPrivateKeyHex(
options.key.bech32
);
break;
case "cli":
this._walletSecret = WalletStaticMethods.signingKeyToHexes(
options.key.payment,
options.key.stake ?? "f0".repeat(32)
);
break;
case "bip32Bytes":
this._walletSecret = WalletStaticMethods.bip32BytesToPrivateKeyHex(
options.key.bip32Bytes
);
break;
}
}
async init() {
await import_core_cst.Crypto.ready();
this.cryptoIsReady = true;
}
getAccount(accountIndex = 0, keyIndex = 0) {
if (this._walletSecret == void 0)
throw new Error("[EmbeddedWallet] No keys initialized");
const { paymentKey, stakeKey, dRepKey } = (0, import_core_cst.buildKeys)(
this._walletSecret,
accountIndex,
keyIndex
);
const { baseAddress, enterpriseAddress, rewardAddress } = WalletStaticMethods.getAddresses(paymentKey, stakeKey, this._networkId);
let _account = {
baseAddress,
enterpriseAddress,
rewardAddress,
baseAddressBech32: baseAddress.toBech32(),
enterpriseAddressBech32: enterpriseAddress.toBech32(),
rewardAddressBech32: rewardAddress.toBech32(),
paymentKey,
stakeKey,
paymentKeyHex: paymentKey.hex(),
stakeKeyHex: stakeKey.hex()
};
if (dRepKey) {
const { pubDRepKey, dRepIDBech32, dRepIDHash, dRepIDCip105 } = WalletStaticMethods.getDRepKey(dRepKey, this._networkId);
_account.drepKey = dRepKey;
_account.pubDRepKey = pubDRepKey;
_account.dRepIDBech32 = dRepIDBech32;
_account.dRepIDHash = dRepIDHash;
_account.dRepIDCip105 = dRepIDCip105;
}
return _account;
}
/**
* Get wallet network ID.
*
* @returns network ID
*/
getNetworkId() {
return this._networkId;
}
/**
* This endpoint utilizes the [CIP-8 - Message Signing](https://cips.cardano.org/cips/cip8/) to sign arbitrary data, to verify the data was signed by the owner of the private key.
*
* @param address - bech32 address to sign the data with
* @param payload - the data to be signed
* @param accountIndex account index (default: 0)
* @returns a signature
*/
signData(address, payload, accountIndex = 0, keyIndex = 0) {
try {
const {
baseAddress,
enterpriseAddress,
rewardAddress,
paymentKey,
stakeKey
} = this.getAccount(accountIndex, keyIndex);
const foundAddress = [baseAddress, enterpriseAddress, rewardAddress].find(
(a) => a.toBech32() === address
);
if (foundAddress === void 0)
throw new Error(
`[EmbeddedWallet] Address: ${address} doesn't belong to this account.`
);
return (0, import_core_cst.signData)(payload, {
address: import_core_cst.Address.fromBech32(address),
key: address === rewardAddress.toBech32() ? stakeKey : paymentKey
});
} catch (error) {
throw new Error(
`[EmbeddedWallet] An error occurred during signData: ${error}.`
);
}
}
/**
* This endpoints sign the provided transaction (unsignedTx) with the private key of the owner.
*
* @param unsignedTx - a transaction in CBOR
* @param accountIndex account index (default: 0)
* @param keyIndex key index (default: 0)
* @param accountType - type of the account (default: payment)
* @returns VkeyWitness
*/
signTx(unsignedTx, accountIndex = 0, keyIndex = 0, accountType = "payment") {
try {
const txHash = (0, import_core_cst.deserializeTxHash)((0, import_core_cst.resolveTxHash)(unsignedTx));
const { paymentKey, stakeKey, drepKey } = this.getAccount(
accountIndex,
keyIndex
);
let key = paymentKey;
if (accountType === "stake") {
key = stakeKey;
} else if (accountType === "drep") {
if (!drepKey) throw new Error("DRep key not found");
key = drepKey;
}
const vKeyWitness = new import_core_cst.VkeyWitness(
key.toPublic().hex(),
key.sign((0, import_core_cst.HexBlob)(txHash)).hex()
);
return vKeyWitness;
} catch (error) {
throw new Error(
`[EmbeddedWallet] An error occurred during signTx: ${error}.`
);
}
}
};
// src/app/index.ts
var AppWallet = class {
_fetcher;
_submitter;
_wallet;
constructor(options) {
this._fetcher = options.fetcher;
this._submitter = options.submitter;
switch (options.key.type) {
case "mnemonic":
this._wallet = new EmbeddedWallet({
networkId: options.networkId,
key: {
type: "mnemonic",
words: options.key.words
}
});
break;
case "root":
this._wallet = new EmbeddedWallet({
networkId: options.networkId,
key: {
type: "root",
bech32: options.key.bech32
}
});
break;
case "cli":
this._wallet = new EmbeddedWallet({
networkId: options.networkId,
key: {
type: "cli",
payment: options.key.payment,
stake: options.key.stake
}
});
}
}
/**
* Initializes the wallet. This is a required call as fetching addresses from the wallet is an async operation.
* @returns void
*/
async init() {
if (this._wallet) {
await this._wallet.init();
}
}
/**
* Get a list of UTXOs to be used as collateral inputs for transactions with plutus script inputs.
*
* This is used in transaction building.
*
* @returns a list of UTXOs
*/
async getCollateralUnspentOutput(accountIndex = 0, addressType = "payment") {
const utxos = await this.getUnspentOutputs(accountIndex, addressType);
const pureAdaUtxos = utxos.filter((utxo) => {
return utxo.output().amount().multiasset() === void 0;
});
pureAdaUtxos.sort((a, b) => {
return Number(a.output().amount().coin()) - Number(b.output().amount().coin());
});
for (const utxo of pureAdaUtxos) {
if (Number(utxo.output().amount().coin()) >= 5e6) {
return [utxo];
}
}
return [];
}
getEnterpriseAddress(accountIndex = 0, keyIndex = 0) {
const account = this._wallet.getAccount(accountIndex, keyIndex);
return account.enterpriseAddressBech32;
}
getPaymentAddress(accountIndex = 0, keyIndex = 0) {
const account = this._wallet.getAccount(accountIndex, keyIndex);
return account.baseAddressBech32;
}
getRewardAddress(accountIndex = 0, keyIndex = 0) {
const account = this._wallet.getAccount(accountIndex, keyIndex);
return account.rewardAddressBech32;
}
getNetworkId() {
return this._wallet.getNetworkId();
}
getUsedAddress(accountIndex = 0, keyIndex = 0, addressType = "payment") {
if (addressType === "enterprise") {
return (0, import_core_cst2.toAddress)(this.getEnterpriseAddress(accountIndex, keyIndex));
} else {
return (0, import_core_cst2.toAddress)(this.getPaymentAddress(accountIndex, keyIndex));
}
}
async getUnspentOutputs(accountIndex = 0, addressType = "payment") {
if (!this._fetcher) {
throw new Error(
"[AppWallet] Fetcher is required to fetch UTxOs. Please provide a fetcher."
);
}
const account = this._wallet.getAccount(accountIndex);
const utxos = await this._fetcher.fetchAddressUTxOs(
addressType == "enterprise" ? account.enterpriseAddressBech32 : account.baseAddressBech32
);
return utxos.map((utxo) => (0, import_core_cst2.toTxUnspentOutput)(utxo));
}
async signData(address, payload, accountIndex = 0, keyIndex = 0) {
try {
return this._wallet.signData(address, payload, accountIndex, keyIndex);
} catch (error) {
throw new Error(
`[AppWallet] An error occurred during signData: ${error}.`
);
}
}
async signTx(unsignedTx, partialSign = false, returnFullTx = true, accountIndex = 0, keyIndex = 0) {
try {
const tx = (0, import_core_cst2.deserializeTx)(unsignedTx);
if (!partialSign && tx.witnessSet().vkeys() !== void 0 && tx.witnessSet().vkeys().size() !== 0)
throw new Error(
"Signatures already exist in the transaction in a non partial sign call"
);
const newSignatures = this._wallet.signTx(
unsignedTx,
accountIndex,
keyIndex
);
if (!returnFullTx) {
let witnessSet = new import_core_cst2.TransactionWitnessSet();
witnessSet.setVkeys(
import_core_cst2.Serialization.CborSet.fromCore(
[newSignatures.toCore()],
import_core_cst2.VkeyWitness.fromCore
)
);
return witnessSet.toCbor();
}
let signedTx = EmbeddedWallet.addWitnessSets(unsignedTx, [newSignatures]);
return signedTx;
} catch (error) {
throw new Error(`[AppWallet] An error occurred during signTx: ${error}.`);
}
}
signTxSync(unsignedTx, partialSign = false, accountIndex = 0, keyIndex = 0) {
try {
throw new Error(`[AppWallet] signTxSync() is not implemented.`);
} catch (error) {
throw new Error(`[AppWallet] An error occurred during signTx: ${error}.`);
}
}
async signTxs(unsignedTxs, partialSign) {
throw new Error(`[AppWallet] signTxs() is not implemented.`);
}
submitTx(tx) {
if (!this._submitter) {
throw new Error(
"[AppWallet] Submitter is required to submit transactions. Please provide a submitter."
);
}
return this._submitter.submitTx(tx);
}
static brew(strength = 256) {
return EmbeddedWallet.generateMnemonic(strength);
}
};
// src/browser/browser-wallet.ts
var import_common2 = require("@meshsdk/common");
var import_core_cst3 = require("@meshsdk/core-cst");
var BrowserWallet = class _BrowserWallet {
constructor(_walletInstance, _walletName) {
this._walletInstance = _walletInstance;
this._walletName = _walletName;
this.walletInstance = { ..._walletInstance };
}
walletInstance;
/**
* Returns a list of wallets installed on user's device. Each wallet is an object with the following properties:
* - A name is provided to display wallet's name on the user interface.
* - A version is provided to display wallet's version on the user interface.
* - An icon is provided to display wallet's icon on the user interface.
*
* @returns a list of wallet names
*/
static async getAvailableWallets({
injectFn = void 0
} = {}) {
if (window === void 0) return [];
if (injectFn) await injectFn();
return _BrowserWallet.getInstalledWallets();
}
/**
* Returns a list of wallets installed on user's device. Each wallet is an object with the following properties:
* - A name is provided to display wallet's name on the user interface.
* - A version is provided to display wallet's version on the user interface.
* - An icon is provided to display wallet's icon on the user interface.
*
* @returns a list of wallet names
*/
static getInstalledWallets() {
if (window === void 0) return [];
if (window.cardano === void 0) return [];
let wallets = [];
for (const key in window.cardano) {
try {
const _wallet = window.cardano[key];
if (_wallet === void 0) continue;
if (_wallet.name === void 0) continue;
if (_wallet.icon === void 0) continue;
if (_wallet.apiVersion === void 0) continue;
wallets.push({
id: key,
name: key == "nufiSnap" ? "MetaMask" : _wallet.name,
icon: _wallet.icon,
version: _wallet.apiVersion
});
} catch (e) {
}
}
return wallets;
}
/**
* This is the entrypoint to start communication with the user's wallet. The wallet should request the user's permission to connect the web page to the user's wallet, and if permission has been granted, the wallet will be returned and exposing the full API for the app to use.
*
* Query BrowserWallet.getInstalledWallets() to get a list of available wallets, then provide the wallet name for which wallet the user would like to connect with.
*
* @param walletName - the name of the wallet to enable (e.g. "eternl", "begin")
* @param extensions - optional, a list of CIPs that the wallet should support
* @returns WalletInstance
*/
static async enable(walletName, extensions = []) {
try {
const walletInstance = await _BrowserWallet.resolveInstance(
walletName,
extensions
);
if (walletInstance !== void 0)
return new _BrowserWallet(walletInstance, walletName);
throw new Error(`Couldn't create an instance of wallet: ${walletName}`);
} catch (error) {
throw new Error(
`[BrowserWallet] An error occurred during enable: ${JSON.stringify(
error
)}.`
);
}
}
/**
* Returns a list of assets in the wallet. This API will return every assets in the wallet. Each asset is an object with the following properties:
* - A unit is provided to display asset's name on the user interface.
* - A quantity is provided to display asset's quantity on the user interface.
*
* @returns a list of assets and their quantities
*/
async getBalance() {
const balance = await this._walletInstance.getBalance();
return (0, import_core_cst3.fromValue)((0, import_core_cst3.deserializeValue)(balance));
}
/**
* Returns an address owned by the wallet that should be used as a change address to return leftover assets during transaction creation back to the connected wallet.
*
* @returns an address
*/
async getChangeAddress() {
const changeAddress = await this._walletInstance.getChangeAddress();
return (0, import_core_cst3.addressToBech32)((0, import_core_cst3.deserializeAddress)(changeAddress));
}
/**
* This function shall return a list of one or more UTXOs (unspent transaction outputs) controlled by the wallet that are required to reach AT LEAST the combined ADA value target specified in amount AND the best suitable to be used as collateral inputs for transactions with plutus script inputs (pure ADA-only UTXOs).
*
* If this cannot be attained, an error message with an explanation of the blocking problem shall be returned. NOTE: wallets are free to return UTXOs that add up to a greater total ADA value than requested in the amount parameter, but wallets must never return any result where UTXOs would sum up to a smaller total ADA value, instead in a case like that an error message must be returned.
*
* @param limit
* @returns a list of UTXOs
*/
async getCollateral() {
const deserializedCollateral = await this.getCollateralUnspentOutput();
return deserializedCollateral.map((dc) => (0, import_core_cst3.fromTxUnspentOutput)(dc));
}
/**
* Return a list of supported CIPs of the wallet.
*
* @returns a list of CIPs
*/
async getExtensions() {
try {
const _extensions = await this._walletInstance.getExtensions();
return _extensions.map((e) => e.cip);
} catch (e) {
return [];
}
}
/**
* Returns the network ID of the currently connected account. 0 is testnet and 1 is mainnet but other networks can possibly be returned by wallets. Those other network ID values are not governed by CIP-30. This result will stay the same unless the connected account has changed.
*
* @returns network ID
*/
getNetworkId() {
return this._walletInstance.getNetworkId();
}
/**
* Returns a list of reward addresses owned by the wallet. A reward address is a stake address that is used to receive rewards from staking, generally starts from `stake` prefix.
*
* @returns a list of reward addresses
*/
async getRewardAddresses() {
const rewardAddresses = await this._walletInstance.getRewardAddresses();
return rewardAddresses.map((ra) => (0, import_core_cst3.addressToBech32)((0, import_core_cst3.deserializeAddress)(ra)));
}
/**
* Returns a list of unused addresses controlled by the wallet.
*
* @returns a list of unused addresses
*/
async getUnusedAddresses() {
const unusedAddresses = await this._walletInstance.getUnusedAddresses();
return unusedAddresses.map(
(una) => (0, import_core_cst3.addressToBech32)((0, import_core_cst3.deserializeAddress)(una))
);
}
/**
* Returns a list of used addresses controlled by the wallet.
*
* @returns a list of used addresses
*/
async getUsedAddresses() {
const usedAddresses = await this._walletInstance.getUsedAddresses();
return usedAddresses.map((usa) => (0, import_core_cst3.addressToBech32)((0, import_core_cst3.deserializeAddress)(usa)));
}
/**
* Return a list of all UTXOs (unspent transaction outputs) controlled by the wallet.
*
* @returns a list of UTXOs
*/
async getUtxos() {
const deserializedUTxOs = await this.getUsedUTxOs();
return deserializedUTxOs.map((du) => (0, import_core_cst3.fromTxUnspentOutput)(du));
}
/**
* This endpoint utilizes the [CIP-8 - Message Signing](https://cips.cardano.org/cips/cip8/) to sign arbitrary data, to verify the data was signed by the owner of the private key.
*
* @param payload - the data to be signed
* @param address - optional, if not provided, the first staking address will be used
* @returns a signature
*/
async signData(payload, address, convertFromUTF8 = true) {
if (address === void 0) {
address = (await this.getUsedAddresses())[0];
if (address === void 0) {
address = await this.getChangeAddress();
}
}
const _payload = convertFromUTF8 ? (0, import_common2.fromUTF8)(payload) : payload;
if (address.startsWith("drep1")) {
return this._walletInstance.cip95.signData(address, _payload);
}
const signerAddress = (0, import_core_cst3.toAddress)(address).toBytes().toString();
return this._walletInstance.signData(signerAddress, _payload);
}
/**
* Requests user to sign the provided transaction (tx). The wallet should ask the user for permission, and if given, try to sign the supplied body and return a signed transaction. partialSign should be true if the transaction provided requires multiple signatures.
*
* @param unsignedTx - a transaction in CBOR
* @param partialSign - if the transaction is signed partially
* @param returnFullTx - if the full tx should be returned or only the witness set (default: true)
* @returns a signed transaction in CBOR
*/
async signTx(unsignedTx, partialSign = false, returnFullTx = true) {
const witness = await this._walletInstance.signTx(unsignedTx, partialSign);
if (witness === "") {
return unsignedTx;
}
if (!returnFullTx) {
return witness;
}
return _BrowserWallet.addBrowserWitnesses(unsignedTx, witness);
}
/**
* Experimental feature - sign multiple transactions at once (Supported wallet(s): Typhon)
*
* @param unsignedTxs - array of unsigned transactions in CborHex string
* @param partialSign - if the transactions are signed partially
* @returns array of signed transactions CborHex string
*/
async signTxs(unsignedTxs, partialSign = false) {
let witnessSets = void 0;
switch (this._walletName) {
case "Typhon Wallet":
if (this._walletInstance.signTxs) {
witnessSets = await this._walletInstance.signTxs(
unsignedTxs,
partialSign
);
}
break;
default:
if (this._walletInstance.signTxs) {
witnessSets = await this._walletInstance.signTxs(
unsignedTxs.map((cbor) => ({
cbor,
partialSign
}))
);
} else if (this._walletInstance.experimental.signTxs) {
witnessSets = await this._walletInstance.experimental.signTxs(
unsignedTxs.map((cbor) => ({
cbor,
partialSign
}))
);
}
break;
}
if (!witnessSets) throw new Error("Wallet does not support signTxs");
const signedTxs = [];
for (let i = 0; i < witnessSets.length; i++) {
const unsignedTx = unsignedTxs[i];
const cWitness = witnessSets[i];
if (cWitness === "") {
signedTxs.push(unsignedTx);
} else {
const signedTx = _BrowserWallet.addBrowserWitnesses(
unsignedTx,
cWitness
);
signedTxs.push(signedTx);
}
}
return signedTxs;
}
/**
* Submits the signed transaction to the blockchain network.
*
* As wallets should already have this ability to submit transaction, we allow apps to request that a transaction be sent through it. If the wallet accepts the transaction and tries to send it, it shall return the transaction ID for the app to track. The wallet can return error messages or failure if there was an error in sending it.
*
* @param tx
* @returns a transaction hash
*/
submitTx(tx) {
return this._walletInstance.submitTx(tx);
}
/**
* Get a used address of type Address from the wallet.
*
* This is used in transaction building.
*
* @returns an Address object
*/
async getUsedAddress() {
const usedAddresses = await this._walletInstance.getUsedAddresses();
if (usedAddresses.length === 0) throw new Error("No used addresses found");
return (0, import_core_cst3.deserializeAddress)(usedAddresses[0]);
}
/**
* Get a list of UTXOs to be used as collateral inputs for transactions with plutus script inputs.
*
* This is used in transaction building.
*
* @returns a list of UTXOs
*/
async getCollateralUnspentOutput(limit = import_common2.DEFAULT_PROTOCOL_PARAMETERS.maxCollateralInputs) {
let collateral = [];
try {
collateral = await this._walletInstance.getCollateral() ?? [];
} catch (e) {
try {
collateral = await this._walletInstance.experimental.getCollateral() ?? [];
} catch (e2) {
console.error(e2);
}
}
return collateral.map((c) => (0, import_core_cst3.deserializeTxUnspentOutput)(c)).slice(0, limit);
}
/**
* Get a list of UTXOs to be used for transaction building.
*
* This is used in transaction building.
*
* @returns a list of UTXOs
*/
async getUsedUTxOs() {
const utxos = await this._walletInstance.getUtxos() ?? [];
return utxos.map((u) => (0, import_core_cst3.deserializeTxUnspentOutput)(u));
}
/**
* A helper function to get the assets in the wallet.
*
* @returns a list of assets
*/
async getAssets() {
const balance = await this.getBalance();
return balance.filter((v) => v.unit !== "lovelace").map((v) => {
const policyId = v.unit.slice(0, import_common2.POLICY_ID_LENGTH);
const assetName = v.unit.slice(import_common2.POLICY_ID_LENGTH);
const fingerprint = (0, import_common2.resolveFingerprint)(policyId, assetName);
return {
unit: v.unit,
policyId,
assetName,
fingerprint,
quantity: v.quantity
};
});
}
/**
* A helper function to get the lovelace balance in the wallet.
*
* @returns lovelace balance
*/
async getLovelace() {
const balance = await this.getBalance();
const nativeAsset = balance.find((v) => v.unit === "lovelace");
return nativeAsset !== void 0 ? nativeAsset.quantity : "0";
}
/**
* A helper function to get the assets of a specific policy ID in the wallet.
*
* @param policyId
* @returns a list of assets
*/
async getPolicyIdAssets(policyId) {
const assets = await this.getAssets();
return assets.filter((v) => v.policyId === policyId);
}
/**
* A helper function to get the policy IDs of all the assets in the wallet.
*
* @returns a list of policy IDs
*/
async getPolicyIds() {
const balance = await this.getBalance();
return Array.from(
new Set(balance.map((v) => v.unit.slice(0, import_common2.POLICY_ID_LENGTH)))
).filter((p) => p !== "lovelace");
}
/**
* The connected wallet account provides the account's public DRep Key, derivation as described in CIP-0105.
* These are used by the client to identify the user's on-chain CIP-1694 interactions, i.e. if a user has registered to be a DRep.
*
* @returns DRep object
*/
async getDRep() {
const pubDRepKey = await this.getPubDRepKey();
try {
if (pubDRepKey === void 0) return void 0;
const { dRepIDHash } = await _BrowserWallet.dRepKeyToDRepID(pubDRepKey);
const dRepIDCip105 = (0, import_core_cst3.hexToBech32)("drep", dRepIDHash);
return {
publicKey: pubDRepKey,
publicKeyHash: dRepIDHash,
dRepIDCip105
};
} catch (e) {
console.error(e);
return void 0;
}
}
/**
* The connected wallet account provides the account's public DRep Key, derivation as described in CIP-0105.
* These are used by the client to identify the user's on-chain CIP-1694 interactions, i.e. if a user has registered to be a DRep.
*
* @returns wallet account's public DRep Key
*/
async getPubDRepKey() {
try {
if (this._walletInstance.cip95 === void 0) return void 0;
const pubDRepKey = await this._walletInstance.cip95.getPubDRepKey();
return pubDRepKey;
} catch (e) {
console.error(e);
return void 0;
}
}
async getRegisteredPubStakeKeys() {
try {
if (this._walletInstance.cip95 === void 0) return void 0;
const pubStakeKeys = await this._walletInstance.cip95.getRegisteredPubStakeKeys();
const pubStakeKeyHashes = await Promise.all(
pubStakeKeys.map(async (pubStakeKey) => {
const { dRepIDHash } = await _BrowserWallet.dRepKeyToDRepID(pubStakeKey);
return dRepIDHash;
})
);
return {
pubStakeKeys,
pubStakeKeyHashes
};
} catch (e) {
console.error(e);
return void 0;
}
}
async getUnregisteredPubStakeKeys() {
try {
if (this._walletInstance.cip95 === void 0) return void 0;
const pubStakeKeys = await this._walletInstance.cip95.getUnregisteredPubStakeKeys();
const pubStakeKeyHashes = await Promise.all(
pubStakeKeys.map(async (pubStakeKey) => {
const { dRepIDHash } = await _BrowserWallet.dRepKeyToDRepID(pubStakeKey);
return dRepIDHash;
})
);
return {
pubStakeKeys,
pubStakeKeyHashes
};
} catch (e) {
console.error(e);
return void 0;
}
}
static async dRepKeyToDRepID(dRepKey) {
const dRepKeyHex = (0, import_core_cst3.Ed25519PublicKeyHex)(dRepKey);
const dRepID = import_core_cst3.Ed25519PublicKey.fromHex(dRepKeyHex);
const dRepIDHash = (await dRepID.hash()).