Add prettier support

pull/25/head
HenryNguyen5 6 years ago
parent 87aaa28655
commit 6f3142aa1c

@ -1,40 +1,31 @@
{ {
"env": { "env": {
"browser": true, "browser": true,
"commonjs": true, "commonjs": true,
"es6": true, "es6": true,
"node": true "node": true
}, },
"globals": { "globals": {
"LocalFileSystem": false, "LocalFileSystem": false,
"cordova": false, "cordova": false,
"device": false "device": false
}, },
"extends": "eslint:recommended", "extends": "eslint:recommended",
"rules": { "rules": {
"indent": [ "indent": ["off", "tab"],
"off", "linebreak-style": ["error", "unix"],
"tab" "no-unused-vars": [
], "off",
"linebreak-style": [ {
"error", "vars": "all",
"unix" "args": "after-used",
], "ignoreRestSiblings": false
"no-unused-vars": [ }
"off", ],
{ "no-console": ["warn", { "allow": ["warn", "error"] }],
"vars": "all", "no-extra-semi": ["warn"],
"args": "after-used", "no-redeclare": ["warn"],
"ignoreRestSiblings": false // "no-unreachable": [ "warn" ],
} "no-inner-declarations": ["warn"]
], }
"no-console": [ }
"warn",
{ "allow": [ "warn", "error" ] }
],
"no-extra-semi": [ "warn" ],
"no-redeclare": [ "warn" ],
// "no-unreachable": [ "warn" ],
"no-inner-declarations": [ "warn" ]
}
}

@ -0,0 +1,10 @@
cryptonote_utils/biginteger.js
cryptonote_utils/sha3.js
cryptonote_utils/nacl-fast-cn.js
cryptonote_utils/mnemonic.js
cryptonote_utils/cryptonote_crypto_EMSCRIPTEN.js
cryptonote_utils/crc32.js
package.json
yarn.lock

@ -0,0 +1,8 @@
{
"printWidth": 80,
"singleQuote": false,
"useTabs": true,
"semi": true,
"tabWidth": 4,
"trailingComma": "all"
}

@ -1,21 +1,21 @@
// Copyright (c) 2014-2018, MyMonero.com // Copyright (c) 2014-2018, MyMonero.com
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -26,15 +26,14 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// v--- These should maybe be injected into context // v--- These should maybe be injected into context
const JSBigInt = require('./biginteger').BigInteger const JSBigInt = require("./biginteger").BigInteger;
var cnBase58 = (function () var cnBase58 = (function() {
{
var b58 = {}; var b58 = {};
// //
var alphabet_str = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; var alphabet_str =
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
var alphabet = []; var alphabet = [];
for (var i = 0; i < alphabet_str.length; i++) { for (var i = 0; i < alphabet_str.length; i++) {
alphabet.push(alphabet_str.charCodeAt(i)); alphabet.push(alphabet_str.charCodeAt(i));
@ -88,25 +87,25 @@ var cnBase58 = (function ()
var twopow8 = new JSBigInt(2).pow(8); var twopow8 = new JSBigInt(2).pow(8);
var i = 0; var i = 0;
switch (9 - data.length) { switch (9 - data.length) {
case 1: case 1:
res = res.add(data[i++]); res = res.add(data[i++]);
case 2: case 2:
res = res.multiply(twopow8).add(data[i++]); res = res.multiply(twopow8).add(data[i++]);
case 3: case 3:
res = res.multiply(twopow8).add(data[i++]); res = res.multiply(twopow8).add(data[i++]);
case 4: case 4:
res = res.multiply(twopow8).add(data[i++]); res = res.multiply(twopow8).add(data[i++]);
case 5: case 5:
res = res.multiply(twopow8).add(data[i++]); res = res.multiply(twopow8).add(data[i++]);
case 6: case 6:
res = res.multiply(twopow8).add(data[i++]); res = res.multiply(twopow8).add(data[i++]);
case 7: case 7:
res = res.multiply(twopow8).add(data[i++]); res = res.multiply(twopow8).add(data[i++]);
case 8: case 8:
res = res.multiply(twopow8).add(data[i++]); res = res.multiply(twopow8).add(data[i++]);
break; break;
default: default:
throw "Impossible condition"; throw "Impossible condition";
} }
return res; return res;
} }
@ -124,7 +123,7 @@ var cnBase58 = (function ()
return res; return res;
} }
b58.encode_block = function (data, buf, index) { b58.encode_block = function(data, buf, index) {
if (data.length < 1 || data.length > full_encoded_block_size) { if (data.length < 1 || data.length > full_encoded_block_size) {
throw "Invalid block length: " + data.length; throw "Invalid block length: " + data.length;
} }
@ -143,14 +142,16 @@ var cnBase58 = (function ()
return buf; return buf;
}; };
b58.encode = function (hex) { b58.encode = function(hex) {
var data = hextobin(hex); var data = hextobin(hex);
if (data.length === 0) { if (data.length === 0) {
return ""; return "";
} }
var full_block_count = Math.floor(data.length / full_block_size); var full_block_count = Math.floor(data.length / full_block_size);
var last_block_size = data.length % full_block_size; var last_block_size = data.length % full_block_size;
var res_size = full_block_count * full_encoded_block_size + encoded_block_sizes[last_block_size]; var res_size =
full_block_count * full_encoded_block_size +
encoded_block_sizes[last_block_size];
var res = new Uint8Array(res_size); var res = new Uint8Array(res_size);
var i; var i;
@ -158,15 +159,29 @@ var cnBase58 = (function ()
res[i] = alphabet[0]; res[i] = alphabet[0];
} }
for (i = 0; i < full_block_count; i++) { for (i = 0; i < full_block_count; i++) {
res = b58.encode_block(data.subarray(i * full_block_size, i * full_block_size + full_block_size), res, i * full_encoded_block_size); res = b58.encode_block(
data.subarray(
i * full_block_size,
i * full_block_size + full_block_size,
),
res,
i * full_encoded_block_size,
);
} }
if (last_block_size > 0) { if (last_block_size > 0) {
res = b58.encode_block(data.subarray(full_block_count * full_block_size, full_block_count * full_block_size + last_block_size), res, full_block_count * full_encoded_block_size) res = b58.encode_block(
data.subarray(
full_block_count * full_block_size,
full_block_count * full_block_size + last_block_size,
),
res,
full_block_count * full_encoded_block_size,
);
} }
return bintostr(res); return bintostr(res);
}; };
b58.decode_block = function (data, buf, index) { b58.decode_block = function(data, buf, index) {
if (data.length < 1 || data.length > full_encoded_block_size) { if (data.length < 1 || data.length > full_encoded_block_size) {
throw "Invalid block length: " + data.length; throw "Invalid block length: " + data.length;
} }
@ -190,31 +205,52 @@ var cnBase58 = (function ()
res_num = product; res_num = product;
order = order.multiply(alphabet_size); order = order.multiply(alphabet_size);
} }
if (res_size < full_block_size && (new JSBigInt(2).pow(8 * res_size).compare(res_num) <= 0)) { if (
res_size < full_block_size &&
new JSBigInt(2).pow(8 * res_size).compare(res_num) <= 0
) {
throw "Overflow 2"; throw "Overflow 2";
} }
buf.set(uint64_to_8be(res_num, res_size), index); buf.set(uint64_to_8be(res_num, res_size), index);
return buf; return buf;
}; };
b58.decode = function (enc) { b58.decode = function(enc) {
enc = strtobin(enc); enc = strtobin(enc);
if (enc.length === 0) { if (enc.length === 0) {
return ""; return "";
} }
var full_block_count = Math.floor(enc.length / full_encoded_block_size); var full_block_count = Math.floor(enc.length / full_encoded_block_size);
var last_block_size = enc.length % full_encoded_block_size; var last_block_size = enc.length % full_encoded_block_size;
var last_block_decoded_size = encoded_block_sizes.indexOf(last_block_size); var last_block_decoded_size = encoded_block_sizes.indexOf(
last_block_size,
);
if (last_block_decoded_size < 0) { if (last_block_decoded_size < 0) {
throw "Invalid encoded length"; throw "Invalid encoded length";
} }
var data_size = full_block_count * full_block_size + last_block_decoded_size; var data_size =
full_block_count * full_block_size + last_block_decoded_size;
var data = new Uint8Array(data_size); var data = new Uint8Array(data_size);
for (var i = 0; i < full_block_count; i++) { for (var i = 0; i < full_block_count; i++) {
data = b58.decode_block(enc.subarray(i * full_encoded_block_size, i * full_encoded_block_size + full_encoded_block_size), data, i * full_block_size); data = b58.decode_block(
enc.subarray(
i * full_encoded_block_size,
i * full_encoded_block_size + full_encoded_block_size,
),
data,
i * full_block_size,
);
} }
if (last_block_size > 0) { if (last_block_size > 0) {
data = b58.decode_block(enc.subarray(full_block_count * full_encoded_block_size, full_block_count * full_encoded_block_size + last_block_size), data, full_block_count * full_block_size); data = b58.decode_block(
enc.subarray(
full_block_count * full_encoded_block_size,
full_block_count * full_encoded_block_size +
last_block_size,
),
data,
full_block_count * full_block_size,
);
} }
return bintohex(data); return bintohex(data);
}; };
@ -222,4 +258,4 @@ var cnBase58 = (function ()
return b58; return b58;
})(); })();
exports.cnBase58 = cnBase58 exports.cnBase58 = cnBase58;

File diff suppressed because it is too large Load Diff

@ -1,21 +1,21 @@
// Copyright (c) 2014-2018, MyMonero.com // Copyright (c) 2014-2018, MyMonero.com
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -26,13 +26,12 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"use strict" "use strict";
var network_type = var network_type = {
{
MAINNET: 0, MAINNET: 0,
TESTNET: 1, TESTNET: 1,
STAGENET: 2 STAGENET: 2,
}; };
exports.network_type = network_type; exports.network_type = network_type;
// //
@ -48,49 +47,46 @@ var __STAGENET_CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 24;
var __STAGENET_CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 25; var __STAGENET_CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 25;
var __STAGENET_CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 36; var __STAGENET_CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 36;
// //
function cryptonoteBase58PrefixForStandardAddressOn(nettype) function cryptonoteBase58PrefixForStandardAddressOn(nettype) {
{ if (nettype == null || typeof nettype === "undefined") {
if (nettype == null || typeof nettype === 'undefined') { console.warn("Unexpected nil nettype");
console.warn("Unexpected nil nettype")
} }
if (nettype == network_type.MAINNET) { if (nettype == network_type.MAINNET) {
return __MAINNET_CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX; return __MAINNET_CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX;
} else if (nettype == network_type.TESTNET) { } else if (nettype == network_type.TESTNET) {
return __TESTNET_CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX return __TESTNET_CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX;
} else if (nettype == network_type.STAGENET) { } else if (nettype == network_type.STAGENET) {
return __STAGENET_CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX return __STAGENET_CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX;
} }
throw "Illegal nettype" throw "Illegal nettype";
} }
function cryptonoteBase58PrefixForIntegratedAddressOn(nettype) function cryptonoteBase58PrefixForIntegratedAddressOn(nettype) {
{ if (nettype == null || typeof nettype === "undefined") {
if (nettype == null || typeof nettype === 'undefined') { console.warn("Unexpected nil nettype");
console.warn("Unexpected nil nettype")
} }
if (nettype == network_type.MAINNET) { if (nettype == network_type.MAINNET) {
return __MAINNET_CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; return __MAINNET_CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
} else if (nettype == network_type.TESTNET) { } else if (nettype == network_type.TESTNET) {
return __TESTNET_CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX return __TESTNET_CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
} else if (nettype == network_type.STAGENET) { } else if (nettype == network_type.STAGENET) {
return __STAGENET_CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX return __STAGENET_CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
} }
throw "Illegal nettype" throw "Illegal nettype";
} }
function cryptonoteBase58PrefixForSubAddressOn(nettype) function cryptonoteBase58PrefixForSubAddressOn(nettype) {
{ if (nettype == null || typeof nettype === "undefined") {
if (nettype == null || typeof nettype === 'undefined') { console.warn("Unexpected nil nettype");
console.warn("Unexpected nil nettype")
} }
if (nettype == network_type.MAINNET) { if (nettype == network_type.MAINNET) {
return __MAINNET_CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX; return __MAINNET_CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX;
} else if (nettype == network_type.TESTNET) { } else if (nettype == network_type.TESTNET) {
return __TESTNET_CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX return __TESTNET_CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX;
} else if (nettype == network_type.STAGENET) { } else if (nettype == network_type.STAGENET) {
return __STAGENET_CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX return __STAGENET_CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX;
} }
throw "Illegal nettype" throw "Illegal nettype";
} }
// //
exports.cryptonoteBase58PrefixForStandardAddressOn = cryptonoteBase58PrefixForStandardAddressOn; exports.cryptonoteBase58PrefixForStandardAddressOn = cryptonoteBase58PrefixForStandardAddressOn;
exports.cryptonoteBase58PrefixForIntegratedAddressOn = cryptonoteBase58PrefixForIntegratedAddressOn; exports.cryptonoteBase58PrefixForIntegratedAddressOn = cryptonoteBase58PrefixForIntegratedAddressOn;
exports.cryptonoteBase58PrefixForSubAddressOn = cryptonoteBase58PrefixForSubAddressOn; exports.cryptonoteBase58PrefixForSubAddressOn = cryptonoteBase58PrefixForSubAddressOn;

@ -26,117 +26,131 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
"use strict" "use strict";
// //
const response_parser_utils = require('./response_parser_utils') const response_parser_utils = require("./response_parser_utils");
const JSBigInt = require('../cryptonote_utils/biginteger').BigInteger // important: grab defined export const JSBigInt = require("../cryptonote_utils/biginteger").BigInteger; // important: grab defined export
// //
function New_ParametersForWalletRequest(address, view_key__private) function New_ParametersForWalletRequest(address, view_key__private) {
{
return { return {
address: address, address: address,
view_key: view_key__private view_key: view_key__private,
} };
} }
exports.New_ParametersForWalletRequest = New_ParametersForWalletRequest exports.New_ParametersForWalletRequest = New_ParametersForWalletRequest;
// //
function AddUserAgentParamters( function AddUserAgentParamters(
parameters, parameters,
appUserAgent_product, appUserAgent_product,
appUserAgent_version appUserAgent_version,
) { ) {
// setting these on params instead of as header field User-Agent so as to retain all info found in User-Agent, such as platform… and these are set so server has option to control delivery // setting these on params instead of as header field User-Agent so as to retain all info found in User-Agent, such as platform… and these are set so server has option to control delivery
parameters["app_name"] = appUserAgent_product parameters["app_name"] = appUserAgent_product;
parameters["app_version"] = appUserAgent_version parameters["app_version"] = appUserAgent_version;
} }
exports.AddUserAgentParamters = AddUserAgentParamters exports.AddUserAgentParamters = AddUserAgentParamters;
// //
function HTTPRequest( function HTTPRequest(
request_conformant_module, // such as 'request' or 'xhr' .. TODO: consider switching to 'fetch' request_conformant_module, // such as 'request' or 'xhr' .. TODO: consider switching to 'fetch'
apiAddress_authority, // authority means [subdomain.]host.…[:…] with no trailing slash apiAddress_authority, // authority means [subdomain.]host.…[:…] with no trailing slash
endpointPath, endpointPath,
final_parameters, final_parameters,
fn fn,
) { // fn: (err?, data?) -> new Request ) {
if (typeof final_parameters == 'undefined' || final_parameters == null) { // fn: (err?, data?) -> new Request
throw "final_parameters must not be nil" if (typeof final_parameters == "undefined" || final_parameters == null) {
throw "final_parameters must not be nil";
// return null // return null
} }
const completeURL = _new_APIAddress_baseURLString(apiAddress_authority) + endpointPath const completeURL =
console.log("📡 " + completeURL) _new_APIAddress_baseURLString(apiAddress_authority) + endpointPath;
console.log("📡 " + completeURL);
// //
const request_options = _new_requestOptions_base("POST", completeURL, final_parameters) const request_options = _new_requestOptions_base(
const requestHandle = request_conformant_module( "POST",
request_options, completeURL,
function(err_orProgressEvent, res, body) final_parameters,
{ );
_new_HTTPRequestHandlerFunctionCallingFn(fn)( // <- called manually instead of directly passed to request_conformant_module call to enable passing completeURL const requestHandle = request_conformant_module(request_options, function(
completeURL, err_orProgressEvent,
err_orProgressEvent, res, body res,
) body,
} ) {
) _new_HTTPRequestHandlerFunctionCallingFn(fn)(
// <- called manually instead of directly passed to request_conformant_module call to enable passing completeURL
completeURL,
err_orProgressEvent,
res,
body,
);
});
// //
return requestHandle return requestHandle;
} }
exports.HTTPRequest = HTTPRequest exports.HTTPRequest = HTTPRequest;
// //
function _new_APIAddress_baseURLString(apiAddress_authority) // authority means [subdomain.]host.…[:…] function _new_APIAddress_baseURLString(
{ apiAddress_authority, // authority means [subdomain.]host.…[:…]
return "https" + "://" + apiAddress_authority + "/" ) {
return "https" + "://" + apiAddress_authority + "/";
} }
function _new_requestOptions_base(methodName, completeURL, json_parameters) function _new_requestOptions_base(methodName, completeURL, json_parameters) {
{
return { return {
method: methodName, method: methodName,
url: completeURL, url: completeURL,
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"Accept": "application/json" Accept: "application/json",
}, },
json: json_parameters, json: json_parameters,
useXDR: true, // CORS useXDR: true, // CORS
withCredentials: true // CORS withCredentials: true, // CORS
} };
} }
function _new_HTTPRequestHandlerFunctionCallingFn(fn) function _new_HTTPRequestHandlerFunctionCallingFn(fn) {
{ return function(completeURL, err_orProgressEvent, res, body) {
return function(completeURL, err_orProgressEvent, res, body)
{
// err appears to actually be a ProgressEvent // err appears to actually be a ProgressEvent
var err = null var err = null;
const statusCode = typeof res !== 'undefined' ? res.statusCode : -1 const statusCode = typeof res !== "undefined" ? res.statusCode : -1;
if (statusCode == 0 || statusCode == -1) { // we'll treat 0 as a lack of internet connection.. unless there's a better way to make use of err_orProgressEvent which is apparently going to be typeof ProgressEvent here if (statusCode == 0 || statusCode == -1) {
err = new Error("Connection Failure") // we'll treat 0 as a lack of internet connection.. unless there's a better way to make use of err_orProgressEvent which is apparently going to be typeof ProgressEvent here
err = new Error("Connection Failure");
} else if (statusCode !== 200) { } else if (statusCode !== 200) {
const body_Error = body && typeof body == 'object' ? body.Error : undefined const body_Error =
const statusMessage = res && res.statusMessage ? res.statusMessage : undefined body && typeof body == "object" ? body.Error : undefined;
if (typeof body_Error !== 'undefined' && body_Error) { const statusMessage =
err = new Error(body_Error) res && res.statusMessage ? res.statusMessage : undefined;
} else if (typeof statusMessage !== 'undefined' && statusMessage) { if (typeof body_Error !== "undefined" && body_Error) {
err = new Error(statusMessage) err = new Error(body_Error);
} else if (typeof statusMessage !== "undefined" && statusMessage) {
err = new Error(statusMessage);
} else { } else {
err = new Error("Unknown " + statusCode + " error") err = new Error("Unknown " + statusCode + " error");
} }
} }
if (err) { if (err) {
console.error("❌ " + err); console.error("❌ " + err);
// console.error("Body:", body) // console.error("Body:", body)
fn(err, null) fn(err, null);
return return;
} }
var json; var json;
if (typeof body === 'string') { if (typeof body === "string") {
try { try {
json = JSON.parse(body); json = JSON.parse(body);
} catch (e) { } catch (e) {
console.error("❌ HostedMoneroAPIClient Error: Unable to parse json with exception:", e, "\nbody:", body); console.error(
fn(e, null) "❌ HostedMoneroAPIClient Error: Unable to parse json with exception:",
e,
"\nbody:",
body,
);
fn(e, null);
} }
} else { } else {
json = body json = body;
} }
console.log("✅ " + completeURL + " " + statusCode) console.log("✅ " + completeURL + " " + statusCode);
fn(null, json) fn(null, json);
} };
} }

@ -26,11 +26,11 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
"use strict" "use strict";
// //
const JSBigInt = require('../cryptonote_utils/biginteger').BigInteger const JSBigInt = require("../cryptonote_utils/biginteger").BigInteger;
const monero_utils = require('../monero_utils/monero_cryptonote_utils_instance') const monero_utils = require("../monero_utils/monero_cryptonote_utils_instance");
const monero_keyImage_cache_utils = require('../monero_utils/monero_keyImage_cache_utils') const monero_keyImage_cache_utils = require("../monero_utils/monero_keyImage_cache_utils");
// //
function Parsed_AddressInfo__sync( function Parsed_AddressInfo__sync(
keyImage_cache, keyImage_cache,
@ -38,18 +38,19 @@ function Parsed_AddressInfo__sync(
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) { // -> returnValuesByKey ) {
// -> returnValuesByKey
const total_received = new JSBigInt(data.total_received || 0); const total_received = new JSBigInt(data.total_received || 0);
const locked_balance = new JSBigInt(data.locked_funds || 0); const locked_balance = new JSBigInt(data.locked_funds || 0);
var total_sent = new JSBigInt(data.total_sent || 0) // will be modified in place var total_sent = new JSBigInt(data.total_sent || 0); // will be modified in place
// //
const account_scanned_tx_height = data.scanned_height || 0; const account_scanned_tx_height = data.scanned_height || 0;
const account_scanned_block_height = data.scanned_block_height || 0; const account_scanned_block_height = data.scanned_block_height || 0;
const account_scan_start_height = data.start_height || 0; const account_scan_start_height = data.start_height || 0;
const transaction_height = data.transaction_height || 0; const transaction_height = data.transaction_height || 0;
const blockchain_height = data.blockchain_height || 0; const blockchain_height = data.blockchain_height || 0;
const spent_outputs = data.spent_outputs || [] const spent_outputs = data.spent_outputs || [];
// //
for (let spent_output of spent_outputs) { for (let spent_output of spent_outputs) {
var key_image = monero_keyImage_cache_utils.Lazy_KeyImage( var key_image = monero_keyImage_cache_utils.Lazy_KeyImage(
@ -59,20 +60,23 @@ function Parsed_AddressInfo__sync(
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) );
if (spent_output.key_image !== key_image) { if (spent_output.key_image !== key_image) {
// console.log('💬 Output used as mixin (' + spent_output.key_image + '/' + key_image + ')') // console.log('💬 Output used as mixin (' + spent_output.key_image + '/' + key_image + ')')
total_sent = new JSBigInt(total_sent).subtract(spent_output.amount) total_sent = new JSBigInt(total_sent).subtract(spent_output.amount);
} }
} }
// //
const ratesBySymbol = data.rates || {} // jic it's not there const ratesBySymbol = data.rates || {}; // jic it's not there
// //
const returnValuesByKey = const returnValuesByKey = {
{ total_received_String: total_received
total_received_String: total_received ? total_received.toString() : null, ? total_received.toString()
locked_balance_String: locked_balance ? locked_balance.toString() : null, : null,
locked_balance_String: locked_balance
? locked_balance.toString()
: null,
total_sent_String: total_sent ? total_sent.toString() : null, total_sent_String: total_sent ? total_sent.toString() : null,
// ^serialized JSBigInt // ^serialized JSBigInt
spent_outputs: spent_outputs, spent_outputs: spent_outputs,
@ -82,26 +86,29 @@ function Parsed_AddressInfo__sync(
transaction_height: transaction_height, transaction_height: transaction_height,
blockchain_height: blockchain_height, blockchain_height: blockchain_height,
// //
ratesBySymbol: ratesBySymbol ratesBySymbol: ratesBySymbol,
} };
return returnValuesByKey return returnValuesByKey;
} }
function Parsed_AddressInfo__sync__keyImageManaged( function Parsed_AddressInfo__sync__keyImageManaged(
data, data,
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) { // -> returnValuesByKey ) {
const keyImageCache = monero_keyImage_cache_utils.Lazy_KeyImageCacheForWalletWith(address) // -> returnValuesByKey
const keyImageCache = monero_keyImage_cache_utils.Lazy_KeyImageCacheForWalletWith(
address,
);
return Parsed_AddressInfo__sync( return Parsed_AddressInfo__sync(
keyImageCache, keyImageCache,
data, data,
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) );
} }
function Parsed_AddressInfo( function Parsed_AddressInfo(
keyImage_cache, keyImage_cache,
@ -110,7 +117,7 @@ function Parsed_AddressInfo(
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private, spend_key__private,
fn // (err?, returnValuesByKey) -> Void fn, // (err?, returnValuesByKey) -> Void
) { ) {
const returnValuesByKey = Parsed_AddressInfo__sync( const returnValuesByKey = Parsed_AddressInfo__sync(
keyImage_cache, keyImage_cache,
@ -118,9 +125,9 @@ function Parsed_AddressInfo(
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) );
fn(null, returnValuesByKey) fn(null, returnValuesByKey);
} }
function Parsed_AddressInfo__keyImageManaged( function Parsed_AddressInfo__keyImageManaged(
data, data,
@ -128,8 +135,9 @@ function Parsed_AddressInfo__keyImageManaged(
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private, spend_key__private,
fn fn,
) { // -> returnValuesByKey ) {
// -> returnValuesByKey
Parsed_AddressInfo( Parsed_AddressInfo(
monero_keyImage_cache_utils.Lazy_KeyImageCacheForWalletWith(address), monero_keyImage_cache_utils.Lazy_KeyImageCacheForWalletWith(address),
data, data,
@ -137,13 +145,13 @@ function Parsed_AddressInfo__keyImageManaged(
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private, spend_key__private,
fn fn,
) );
} }
exports.Parsed_AddressInfo = Parsed_AddressInfo exports.Parsed_AddressInfo = Parsed_AddressInfo;
exports.Parsed_AddressInfo__keyImageManaged = Parsed_AddressInfo__keyImageManaged // in case you can't send a mutable key image cache dictionary exports.Parsed_AddressInfo__keyImageManaged = Parsed_AddressInfo__keyImageManaged; // in case you can't send a mutable key image cache dictionary
exports.Parsed_AddressInfo__sync__keyImageManaged = Parsed_AddressInfo__sync__keyImageManaged // in case you can't send a mutable key image cache dictionary exports.Parsed_AddressInfo__sync__keyImageManaged = Parsed_AddressInfo__sync__keyImageManaged; // in case you can't send a mutable key image cache dictionary
exports.Parsed_AddressInfo__sync = Parsed_AddressInfo__sync exports.Parsed_AddressInfo__sync = Parsed_AddressInfo__sync;
// //
function Parsed_AddressTransactions( function Parsed_AddressTransactions(
keyImage_cache, keyImage_cache,
@ -152,7 +160,7 @@ function Parsed_AddressTransactions(
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private, spend_key__private,
fn // (err?, returnValuesByKey) -> Void fn, // (err?, returnValuesByKey) -> Void
) { ) {
const returnValuesByKey = Parsed_AddressTransactions__sync( const returnValuesByKey = Parsed_AddressTransactions__sync(
keyImage_cache, keyImage_cache,
@ -160,9 +168,9 @@ function Parsed_AddressTransactions(
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) );
fn(null, returnValuesByKey) fn(null, returnValuesByKey);
} }
function Parsed_AddressTransactions__sync( function Parsed_AddressTransactions__sync(
keyImage_cache, keyImage_cache,
@ -170,15 +178,15 @@ function Parsed_AddressTransactions__sync(
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) { ) {
const account_scanned_height = data.scanned_height || 0 const account_scanned_height = data.scanned_height || 0;
const account_scanned_block_height = data.scanned_block_height || 0 const account_scanned_block_height = data.scanned_block_height || 0;
const account_scan_start_height = data.start_height || 0 const account_scan_start_height = data.start_height || 0;
const transaction_height = data.transaction_height || 0 const transaction_height = data.transaction_height || 0;
const blockchain_height = data.blockchain_height || 0 const blockchain_height = data.blockchain_height || 0;
// //
const transactions = data.transactions || [] const transactions = data.transactions || [];
// //
// TODO: rewrite this with more clarity if possible // TODO: rewrite this with more clarity if possible
for (let i = 0; i < transactions.length; ++i) { for (let i = 0; i < transactions.length; ++i) {
@ -191,80 +199,99 @@ function Parsed_AddressTransactions__sync(
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) );
if (transactions[i].spent_outputs[j].key_image !== key_image) { if (transactions[i].spent_outputs[j].key_image !== key_image) {
// console.log('Output used as mixin, ignoring (' + transactions[i].spent_outputs[j].key_image + '/' + key_image + ')') // console.log('Output used as mixin, ignoring (' + transactions[i].spent_outputs[j].key_image + '/' + key_image + ')')
transactions[i].total_sent = new JSBigInt(transactions[i].total_sent).subtract(transactions[i].spent_outputs[j].amount).toString() transactions[i].total_sent = new JSBigInt(
transactions[i].spent_outputs.splice(j, 1) transactions[i].total_sent,
j-- )
.subtract(transactions[i].spent_outputs[j].amount)
.toString();
transactions[i].spent_outputs.splice(j, 1);
j--;
} }
} }
} }
if (new JSBigInt(transactions[i].total_received || 0).add(transactions[i].total_sent || 0).compare(0) <= 0) { if (
transactions.splice(i, 1) new JSBigInt(transactions[i].total_received || 0)
i-- .add(transactions[i].total_sent || 0)
continue .compare(0) <= 0
) {
transactions.splice(i, 1);
i--;
continue;
} }
transactions[i].amount = new JSBigInt(transactions[i].total_received || 0).subtract(transactions[i].total_sent || 0).toString() transactions[i].amount = new JSBigInt(
transactions[i].approx_float_amount = parseFloat(monero_utils.formatMoney(transactions[i].amount)) transactions[i].total_received || 0,
transactions[i].timestamp = transactions[i].timestamp )
const record__payment_id = transactions[i].payment_id .subtract(transactions[i].total_sent || 0)
if (typeof record__payment_id !== 'undefined' && record__payment_id) { .toString();
if (record__payment_id.length == 16) { // short (encrypted) pid transactions[i].approx_float_amount = parseFloat(
if (transactions[i].approx_float_amount < 0) { // outgoing monero_utils.formatMoney(transactions[i].amount),
delete transactions[i]["payment_id"] // need to filter these out .. because the server can't filter out short (encrypted) pids on outgoing txs );
transactions[i].timestamp = transactions[i].timestamp;
const record__payment_id = transactions[i].payment_id;
if (typeof record__payment_id !== "undefined" && record__payment_id) {
if (record__payment_id.length == 16) {
// short (encrypted) pid
if (transactions[i].approx_float_amount < 0) {
// outgoing
delete transactions[i]["payment_id"]; // need to filter these out .. because the server can't filter out short (encrypted) pids on outgoing txs
} }
} }
} }
} }
transactions.sort(function(a, b) transactions.sort(function(a, b) {
{
if (a.mempool == true) { if (a.mempool == true) {
if (b.mempool != true) { if (b.mempool != true) {
return -1 // a first return -1; // a first
} }
// both mempool - fall back to .id compare // both mempool - fall back to .id compare
} else if (b.mempool == true) { } else if (b.mempool == true) {
return 1 // b first return 1; // b first
} }
return b.id - a.id return b.id - a.id;
}) });
// prepare transactions to be serialized // prepare transactions to be serialized
for (let transaction of transactions) { for (let transaction of transactions) {
transaction.amount = transaction.amount.toString() // JSBigInt -> String transaction.amount = transaction.amount.toString(); // JSBigInt -> String
if (typeof transaction.total_sent !== 'undefined' && transaction.total_sent !== null) { if (
transaction.total_sent = transaction.total_sent.toString() typeof transaction.total_sent !== "undefined" &&
transaction.total_sent !== null
) {
transaction.total_sent = transaction.total_sent.toString();
} }
} }
// on the other side, we convert transactions timestamp to Date obj // on the other side, we convert transactions timestamp to Date obj
const returnValuesByKey = const returnValuesByKey = {
{
account_scanned_height: account_scanned_height, account_scanned_height: account_scanned_height,
account_scanned_block_height: account_scanned_block_height, account_scanned_block_height: account_scanned_block_height,
account_scan_start_height: account_scan_start_height, account_scan_start_height: account_scan_start_height,
transaction_height: transaction_height, transaction_height: transaction_height,
blockchain_height: blockchain_height, blockchain_height: blockchain_height,
serialized_transactions: transactions serialized_transactions: transactions,
} };
return returnValuesByKey return returnValuesByKey;
} }
function Parsed_AddressTransactions__sync__keyImageManaged( function Parsed_AddressTransactions__sync__keyImageManaged(
data, data,
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) { ) {
const keyImageCache = monero_keyImage_cache_utils.Lazy_KeyImageCacheForWalletWith(address) const keyImageCache = monero_keyImage_cache_utils.Lazy_KeyImageCacheForWalletWith(
address,
);
return Parsed_AddressTransactions__sync( return Parsed_AddressTransactions__sync(
keyImageCache, keyImageCache,
data, data,
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) );
} }
function Parsed_AddressTransactions__keyImageManaged( function Parsed_AddressTransactions__keyImageManaged(
data, data,
@ -272,7 +299,7 @@ function Parsed_AddressTransactions__keyImageManaged(
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private, spend_key__private,
fn fn,
) { ) {
Parsed_AddressTransactions( Parsed_AddressTransactions(
monero_keyImage_cache_utils.Lazy_KeyImageCacheForWalletWith(address), monero_keyImage_cache_utils.Lazy_KeyImageCacheForWalletWith(address),
@ -281,13 +308,13 @@ function Parsed_AddressTransactions__keyImageManaged(
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private, spend_key__private,
fn fn,
) );
} }
exports.Parsed_AddressTransactions = Parsed_AddressTransactions exports.Parsed_AddressTransactions = Parsed_AddressTransactions;
exports.Parsed_AddressTransactions__keyImageManaged = Parsed_AddressTransactions__keyImageManaged exports.Parsed_AddressTransactions__keyImageManaged = Parsed_AddressTransactions__keyImageManaged;
exports.Parsed_AddressTransactions__sync = Parsed_AddressTransactions__sync exports.Parsed_AddressTransactions__sync = Parsed_AddressTransactions__sync;
exports.Parsed_AddressTransactions__sync__keyImageManaged = Parsed_AddressTransactions__sync__keyImageManaged exports.Parsed_AddressTransactions__sync__keyImageManaged = Parsed_AddressTransactions__sync__keyImageManaged;
// //
function Parsed_UnspentOuts( function Parsed_UnspentOuts(
keyImage_cache, keyImage_cache,
@ -296,7 +323,7 @@ function Parsed_UnspentOuts(
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private, spend_key__private,
fn // (err?, returnValuesByKey) fn, // (err?, returnValuesByKey)
) { ) {
const returnValuesByKey = Parsed_UnspentOuts__sync( const returnValuesByKey = Parsed_UnspentOuts__sync(
keyImage_cache, keyImage_cache,
@ -304,9 +331,9 @@ function Parsed_UnspentOuts(
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) );
fn(null, returnValuesByKey) fn(null, returnValuesByKey);
} }
function Parsed_UnspentOuts__sync( function Parsed_UnspentOuts__sync(
keyImage_cache, keyImage_cache,
@ -314,33 +341,53 @@ function Parsed_UnspentOuts__sync(
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) { ) {
const data_outputs = data.outputs const data_outputs = data.outputs;
const finalized_unspentOutputs = data.outputs || [] // to finalize: const finalized_unspentOutputs = data.outputs || []; // to finalize:
for (var i = 0; i < finalized_unspentOutputs.length; i++) { for (var i = 0; i < finalized_unspentOutputs.length; i++) {
const unspent_output = finalized_unspentOutputs[i] const unspent_output = finalized_unspentOutputs[i];
if (unspent_output === null if (
|| typeof unspent_output === 'undefined' unspent_output === null ||
|| !unspent_output // just preserving what was in the original code typeof unspent_output === "undefined" ||
!unspent_output // just preserving what was in the original code
) { ) {
throw "unspent_output at index " + i + " was null" throw "unspent_output at index " + i + " was null";
} }
const spend_key_images = unspent_output.spend_key_images const spend_key_images = unspent_output.spend_key_images;
if (spend_key_images === null || typeof spend_key_images === 'undefined') { if (
throw "spend_key_images of unspent_output at index " + i + " was null" spend_key_images === null ||
typeof spend_key_images === "undefined"
) {
throw "spend_key_images of unspent_output at index " +
i +
" was null";
} }
for (var j = 0; j < spend_key_images.length; j++) { for (var j = 0; j < spend_key_images.length; j++) {
const finalized_unspentOutput_atI_beforeSplice = finalized_unspentOutputs[i] const finalized_unspentOutput_atI_beforeSplice =
if (!finalized_unspentOutput_atI_beforeSplice || typeof finalized_unspentOutput_atI_beforeSplice === 'undefined') { finalized_unspentOutputs[i];
console.warn(`This unspent output at i ${i} was literally undefined! Skipping.`) // NOTE: Looks like the i-- code below should exit earlier if this is necessary if (
continue !finalized_unspentOutput_atI_beforeSplice ||
typeof finalized_unspentOutput_atI_beforeSplice === "undefined"
) {
console.warn(
`This unspent output at i ${i} was literally undefined! Skipping.`,
); // NOTE: Looks like the i-- code below should exit earlier if this is necessary
continue;
} }
const beforeSplice__tx_pub_key = finalized_unspentOutput_atI_beforeSplice.tx_pub_key const beforeSplice__tx_pub_key =
const beforeSplice__index = finalized_unspentOutput_atI_beforeSplice.index finalized_unspentOutput_atI_beforeSplice.tx_pub_key;
if (typeof beforeSplice__tx_pub_key === 'undefined' || !beforeSplice__tx_pub_key) { const beforeSplice__index =
console.warn("This unspent out was missing a tx_pub_key! Skipping.", finalized_unspentOutput_atI_beforeSplice) finalized_unspentOutput_atI_beforeSplice.index;
continue if (
typeof beforeSplice__tx_pub_key === "undefined" ||
!beforeSplice__tx_pub_key
) {
console.warn(
"This unspent out was missing a tx_pub_key! Skipping.",
finalized_unspentOutput_atI_beforeSplice,
);
continue;
} }
var key_image = monero_keyImage_cache_utils.Lazy_KeyImage( var key_image = monero_keyImage_cache_utils.Lazy_KeyImage(
keyImage_cache, keyImage_cache,
@ -349,48 +396,61 @@ function Parsed_UnspentOuts__sync(
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) );
if (key_image === finalized_unspentOutput_atI_beforeSplice.spend_key_images[j]) { if (
key_image ===
finalized_unspentOutput_atI_beforeSplice.spend_key_images[j]
) {
// console.log("💬 Output was spent; key image: " + key_image + " amount: " + monero_utils.formatMoneyFull(finalized_unspentOutputs[i].amount)); // console.log("💬 Output was spent; key image: " + key_image + " amount: " + monero_utils.formatMoneyFull(finalized_unspentOutputs[i].amount));
// Remove output from list // Remove output from list
finalized_unspentOutputs.splice(i, 1); finalized_unspentOutputs.splice(i, 1);
const finalized_unspentOutput_atI_afterSplice = finalized_unspentOutputs[i] const finalized_unspentOutput_atI_afterSplice =
finalized_unspentOutputs[i];
if (finalized_unspentOutput_atI_afterSplice) { if (finalized_unspentOutput_atI_afterSplice) {
j = finalized_unspentOutput_atI_afterSplice.spend_key_images.length; j =
finalized_unspentOutput_atI_afterSplice.spend_key_images
.length;
} }
i--; i--;
} else { } else {
console.log("💬 Output used as mixin (" + key_image + "/" + finalized_unspentOutputs[i].spend_key_images[j] + ")"); console.log(
"💬 Output used as mixin (" +
key_image +
"/" +
finalized_unspentOutputs[i].spend_key_images[j] +
")",
);
} }
} }
} }
console.log("Unspent outs: " + JSON.stringify(finalized_unspentOutputs)); console.log("Unspent outs: " + JSON.stringify(finalized_unspentOutputs));
const unusedOuts = finalized_unspentOutputs.slice(0) const unusedOuts = finalized_unspentOutputs.slice(0);
const returnValuesByKey = const returnValuesByKey = {
{
unspentOutputs: finalized_unspentOutputs, unspentOutputs: finalized_unspentOutputs,
unusedOuts: unusedOuts, unusedOuts: unusedOuts,
per_kb_fee: data.per_kb_fee // String per_kb_fee: data.per_kb_fee, // String
} };
return returnValuesByKey return returnValuesByKey;
} }
function Parsed_UnspentOuts__sync__keyImageManaged( function Parsed_UnspentOuts__sync__keyImageManaged(
data, data,
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) { ) {
const keyImageCache = monero_keyImage_cache_utils.Lazy_KeyImageCacheForWalletWith(address) const keyImageCache = monero_keyImage_cache_utils.Lazy_KeyImageCacheForWalletWith(
address,
);
return Parsed_UnspentOuts__sync( return Parsed_UnspentOuts__sync(
keyImageCache, keyImageCache,
data, data,
address, address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) );
} }
function Parsed_UnspentOuts__keyImageManaged( function Parsed_UnspentOuts__keyImageManaged(
data, data,
@ -398,7 +458,7 @@ function Parsed_UnspentOuts__keyImageManaged(
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private, spend_key__private,
fn fn,
) { ) {
Parsed_UnspentOuts( Parsed_UnspentOuts(
monero_keyImage_cache_utils.Lazy_KeyImageCacheForWalletWith(address), monero_keyImage_cache_utils.Lazy_KeyImageCacheForWalletWith(address),
@ -407,10 +467,10 @@ function Parsed_UnspentOuts__keyImageManaged(
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private, spend_key__private,
fn fn,
) );
} }
exports.Parsed_UnspentOuts = Parsed_UnspentOuts exports.Parsed_UnspentOuts = Parsed_UnspentOuts;
exports.Parsed_UnspentOuts__keyImageManaged = Parsed_UnspentOuts__keyImageManaged exports.Parsed_UnspentOuts__keyImageManaged = Parsed_UnspentOuts__keyImageManaged;
exports.Parsed_UnspentOuts__sync = Parsed_UnspentOuts__sync exports.Parsed_UnspentOuts__sync = Parsed_UnspentOuts__sync;
exports.Parsed_UnspentOuts__sync__keyImageManaged = Parsed_UnspentOuts__sync__keyImageManaged exports.Parsed_UnspentOuts__sync__keyImageManaged = Parsed_UnspentOuts__sync__keyImageManaged;

@ -1,21 +1,21 @@
// Copyright (c) 2014-2018, MyMonero.com // Copyright (c) 2014-2018, MyMonero.com
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -26,23 +26,23 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
"use strict" "use strict";
// //
// NOTE: The main downside to using an index.js file like this is that it will pull in all the code - rather than the consumer requiring code module-by-module // NOTE: The main downside to using an index.js file like this is that it will pull in all the code - rather than the consumer requiring code module-by-module
// It's of course possible to construct your own stripped-down index.[custom name].js file for, e.g., special webpack bundling usages. // It's of course possible to construct your own stripped-down index.[custom name].js file for, e.g., special webpack bundling usages.
const mymonero_core_js = {} const mymonero_core_js = {};
mymonero_core_js.monero_utils = require('./monero_utils/monero_cryptonote_utils_instance') mymonero_core_js.monero_utils = require("./monero_utils/monero_cryptonote_utils_instance");
mymonero_core_js.monero_wallet_utils = require('./monero_utils/monero_wallet_utils') mymonero_core_js.monero_wallet_utils = require("./monero_utils/monero_wallet_utils");
mymonero_core_js.monero_config = require('./monero_utils/monero_config') mymonero_core_js.monero_config = require("./monero_utils/monero_config");
mymonero_core_js.monero_txParsing_utils = require('./monero_utils/monero_txParsing_utils') mymonero_core_js.monero_txParsing_utils = require("./monero_utils/monero_txParsing_utils");
mymonero_core_js.monero_sendingFunds_utils = require('./monero_utils/monero_sendingFunds_utils') mymonero_core_js.monero_sendingFunds_utils = require("./monero_utils/monero_sendingFunds_utils");
mymonero_core_js.monero_requestURI_utils = require('./monero_utils/monero_requestURI_utils') mymonero_core_js.monero_requestURI_utils = require("./monero_utils/monero_requestURI_utils");
mymonero_core_js.monero_keyImage_cache_utils = require('./monero_utils/monero_keyImage_cache_utils') mymonero_core_js.monero_keyImage_cache_utils = require("./monero_utils/monero_keyImage_cache_utils");
mymonero_core_js.monero_wallet_locale = require('./monero_utils/monero_wallet_locale') mymonero_core_js.monero_wallet_locale = require("./monero_utils/monero_wallet_locale");
mymonero_core_js.monero_paymentID_utils = require('./monero_utils/monero_paymentID_utils') mymonero_core_js.monero_paymentID_utils = require("./monero_utils/monero_paymentID_utils");
mymonero_core_js.api_response_parser_utils = require('./hostAPI/response_parser_utils') mymonero_core_js.api_response_parser_utils = require("./hostAPI/response_parser_utils");
// //
mymonero_core_js.nettype_utils = require('./cryptonote_utils/nettype_utils') mymonero_core_js.nettype_utils = require("./cryptonote_utils/nettype_utils");
mymonero_core_js.JSBigInt = require('./cryptonote_utils/biginteger').BigInteger // so that it is available to a hypothetical consumer's language-bridging web context for constructing string arguments to the above modules mymonero_core_js.JSBigInt = require("./cryptonote_utils/biginteger").BigInteger; // so that it is available to a hypothetical consumer's language-bridging web context for constructing string arguments to the above modules
// //
module.exports = mymonero_core_js module.exports = mymonero_core_js;

@ -1,21 +1,21 @@
// Copyright (c) 2014-2018, MyMonero.com // Copyright (c) 2014-2018, MyMonero.com
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -26,12 +26,11 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
"use strict" "use strict";
// //
const JSBigInt = require('../cryptonote_utils/biginteger').BigInteger const JSBigInt = require("../cryptonote_utils/biginteger").BigInteger;
// //
module.exports = module.exports = {
{
// Number of atomic units in one unit of currency. e.g. 12 => 10^12 = 1000000000000 // Number of atomic units in one unit of currency. e.g. 12 => 10^12 = 1000000000000
coinUnitPlaces: 12, coinUnitPlaces: 12,
@ -39,16 +38,16 @@ module.exports =
txMinConfirms: 10, txMinConfirms: 10,
// Currency symbol // Currency symbol
coinSymbol: 'XMR', coinSymbol: "XMR",
// OpenAlias prefix // OpenAlias prefix
openAliasPrefix: "xmr", openAliasPrefix: "xmr",
// Currency name // Currency name
coinName: 'Monero', coinName: "Monero",
// Payment URI Prefix // Payment URI Prefix
coinUriPrefix: 'monero:', coinUriPrefix: "monero:",
// Prefix code for addresses // Prefix code for addresses
addressPrefix: 18, // 18 => addresses start with "4" addressPrefix: 18, // 18 => addresses start with "4"
@ -57,11 +56,11 @@ module.exports =
// Dust threshold in atomic units // Dust threshold in atomic units
// 2*10^9 used for choosing outputs/change - we decompose all the way down if the receiver wants now regardless of threshold // 2*10^9 used for choosing outputs/change - we decompose all the way down if the receiver wants now regardless of threshold
dustThreshold: new JSBigInt('2000000000'), dustThreshold: new JSBigInt("2000000000"),
// Maximum block number, used for tx unlock time // Maximum block number, used for tx unlock time
maxBlockNumber: 500000000, maxBlockNumber: 500000000,
// Average block time in seconds, used for unlock time estimation // Average block time in seconds, used for unlock time estimation
avgBlockTime: 60 avgBlockTime: 60,
} };

@ -1,21 +1,21 @@
// Copyright (c) 2014-2018, MyMonero.com // Copyright (c) 2014-2018, MyMonero.com
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -26,10 +26,10 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
"use strict" "use strict";
// //
const monero_config = require('./monero_config') const monero_config = require("./monero_config");
const cryptonote_utils = require('../cryptonote_utils/cryptonote_utils').cnUtil const cryptonote_utils = require("../cryptonote_utils/cryptonote_utils").cnUtil;
const monero_cryptonote_utils_instance = cryptonote_utils(monero_config) const monero_cryptonote_utils_instance = cryptonote_utils(monero_config);
// //
module.exports = monero_cryptonote_utils_instance module.exports = monero_cryptonote_utils_instance;

@ -1,21 +1,21 @@
// Copyright (c) 2014-2018, MyMonero.com // Copyright (c) 2014-2018, MyMonero.com
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -26,70 +26,76 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
"use strict" "use strict";
// //
const monero_utils = require('./monero_cryptonote_utils_instance') const monero_utils = require("./monero_cryptonote_utils_instance");
// //
const Lazy_KeyImage = function( const Lazy_KeyImage = function(
mutable_keyImagesByCacheKey, // pass a mutable JS dictionary mutable_keyImagesByCacheKey, // pass a mutable JS dictionary
tx_pub_key, tx_pub_key,
out_index, out_index,
public_address, public_address,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private spend_key__private,
) { ) {
var cache_index = tx_pub_key + ':' + public_address + ':' + out_index var cache_index = tx_pub_key + ":" + public_address + ":" + out_index;
const cached__key_image = mutable_keyImagesByCacheKey[cache_index] const cached__key_image = mutable_keyImagesByCacheKey[cache_index];
if (typeof cached__key_image !== 'undefined' && cached__key_image !== null) { if (
return cached__key_image typeof cached__key_image !== "undefined" &&
cached__key_image !== null
) {
return cached__key_image;
} }
var key_image = monero_utils.generate_key_image( var key_image = monero_utils.generate_key_image(
tx_pub_key, tx_pub_key,
view_key__private, view_key__private,
spend_key__public, spend_key__public,
spend_key__private, spend_key__private,
out_index out_index,
).key_image ).key_image;
// cache: // cache:
mutable_keyImagesByCacheKey[cache_index] = key_image mutable_keyImagesByCacheKey[cache_index] = key_image;
// //
return key_image return key_image;
} };
exports.Lazy_KeyImage = Lazy_KeyImage exports.Lazy_KeyImage = Lazy_KeyImage;
// //
// //
// Managed caches - Can be used by apps which can't send a mutable_keyImagesByCacheKey // Managed caches - Can be used by apps which can't send a mutable_keyImagesByCacheKey
const __global_managed_keyImageCaches_by_walletId = {} const __global_managed_keyImageCaches_by_walletId = {};
function _managedKeyImageCacheWalletIdForWalletWith(public_address) function _managedKeyImageCacheWalletIdForWalletWith(public_address) {
{ // NOTE: making the assumption that public_address is unique enough to identify a wallet for caching.... // NOTE: making the assumption that public_address is unique enough to identify a wallet for caching....
// FIXME: with subaddresses, is that still the case? would we need to split them up by subaddr anyway? // FIXME: with subaddresses, is that still the case? would we need to split them up by subaddr anyway?
if (public_address == "" || !public_address || typeof public_address == 'undefined') { if (
throw "managedKeyImageCacheIdentifierForWalletWith: Illegal public_address" public_address == "" ||
!public_address ||
typeof public_address == "undefined"
) {
throw "managedKeyImageCacheIdentifierForWalletWith: Illegal public_address";
} }
return (""+public_address) return "" + public_address;
} }
const Lazy_KeyImageCacheForWalletWith = function(public_address) const Lazy_KeyImageCacheForWalletWith = function(public_address) {
{ var cacheId = _managedKeyImageCacheWalletIdForWalletWith(public_address);
var cacheId = _managedKeyImageCacheWalletIdForWalletWith(public_address) var cache = __global_managed_keyImageCaches_by_walletId[cacheId];
var cache = __global_managed_keyImageCaches_by_walletId[cacheId] if (typeof cache === "undefined" || !cache) {
if (typeof cache === 'undefined' || !cache) { cache = {};
cache = {} __global_managed_keyImageCaches_by_walletId[cacheId] = cache;
__global_managed_keyImageCaches_by_walletId[cacheId] = cache
} }
return cache return cache;
} };
exports.Lazy_KeyImageCacheForWalletWith = Lazy_KeyImageCacheForWalletWith; exports.Lazy_KeyImageCacheForWalletWith = Lazy_KeyImageCacheForWalletWith;
// //
const DeleteManagedKeyImagesForWalletWith = function(public_address) const DeleteManagedKeyImagesForWalletWith = function(public_address) {
{ // IMPORTANT: Ensure you call this method when you want to clear your wallet from // IMPORTANT: Ensure you call this method when you want to clear your wallet from
// memory or delete it, or else you could leak key images and public addresses. // memory or delete it, or else you could leak key images and public addresses.
const cacheId = _managedKeyImageCacheWalletIdForWalletWith(public_address) const cacheId = _managedKeyImageCacheWalletIdForWalletWith(public_address);
delete __global_managed_keyImageCaches_by_walletId[cacheId] delete __global_managed_keyImageCaches_by_walletId[cacheId];
// //
const cache = __global_managed_keyImageCaches_by_walletId[cacheId] const cache = __global_managed_keyImageCaches_by_walletId[cacheId];
if (typeof cache !== 'undefined') { if (typeof cache !== "undefined") {
throw "Key image cache still exists after deletion" throw "Key image cache still exists after deletion";
} }
} };
exports.DeleteManagedKeyImagesForWalletWith = DeleteManagedKeyImagesForWalletWith; exports.DeleteManagedKeyImagesForWalletWith = DeleteManagedKeyImagesForWalletWith;

@ -1,21 +1,21 @@
// Copyright (c) 2014-2018, MyMonero.com // Copyright (c) 2014-2018, MyMonero.com
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -26,22 +26,24 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
"use strict" "use strict";
// //
const monero_utils = require('./monero_cryptonote_utils_instance') const monero_utils = require("./monero_cryptonote_utils_instance");
// //
// Note: long (64 char, plaintext) payment ids are deprecated. // Note: long (64 char, plaintext) payment ids are deprecated.
// //
function New_Short_TransactionID() function New_Short_TransactionID() {
{ return monero_utils.rand_8();
return monero_utils.rand_8()
} }
exports.New_Short_TransactionID = New_Short_TransactionID; exports.New_Short_TransactionID = New_Short_TransactionID;
exports.New_TransactionID = New_Short_TransactionID; exports.New_TransactionID = New_Short_TransactionID;
// //
function IsValidPaymentIDOrNoPaymentID(payment_id__orNil) function IsValidPaymentIDOrNoPaymentID(payment_id__orNil) {
{ if (
if (payment_id__orNil == null || payment_id__orNil == "" || typeof payment_id__orNil == "undefined") { payment_id__orNil == null ||
payment_id__orNil == "" ||
typeof payment_id__orNil == "undefined"
) {
return true; // no pid return true; // no pid
} }
let payment_id = payment_id__orNil; let payment_id = payment_id__orNil;
@ -55,31 +57,30 @@ function IsValidPaymentIDOrNoPaymentID(payment_id__orNil)
} }
exports.IsValidPaymentIDOrNoPaymentID = IsValidPaymentIDOrNoPaymentID; exports.IsValidPaymentIDOrNoPaymentID = IsValidPaymentIDOrNoPaymentID;
// //
function IsValidShortPaymentID(payment_id) function IsValidShortPaymentID(payment_id) {
{
return IsValidPaymentIDOfLength(payment_id, 16); return IsValidPaymentIDOfLength(payment_id, 16);
} }
exports.IsValidShortPaymentID = IsValidShortPaymentID; exports.IsValidShortPaymentID = IsValidShortPaymentID;
// //
function IsValidLongPaymentID(payment_id) function IsValidLongPaymentID(payment_id) {
{
return IsValidPaymentIDOfLength(payment_id, 64); return IsValidPaymentIDOfLength(payment_id, 64);
} }
exports.IsValidLongPaymentID = IsValidLongPaymentID; exports.IsValidLongPaymentID = IsValidLongPaymentID;
// //
function IsValidPaymentIDOfLength(payment_id, required_length) function IsValidPaymentIDOfLength(payment_id, required_length) {
{
if (required_length != 16 && required_length != 64) { if (required_length != 16 && required_length != 64) {
throw "unexpected IsValidPaymentIDOfLength required_length"; throw "unexpected IsValidPaymentIDOfLength required_length";
} }
let payment_id_length = payment_id.length; let payment_id_length = payment_id.length;
if (payment_id_length !== required_length) { // new encrypted short if (payment_id_length !== required_length) {
// new encrypted short
return false; // invalid length return false; // invalid length
} }
let pattern = RegExp("^[0-9a-fA-F]{" + required_length + "}$"); let pattern = RegExp("^[0-9a-fA-F]{" + required_length + "}$");
if (pattern.test(payment_id) != true) { // not a valid required_length char pid if (pattern.test(payment_id) != true) {
// not a valid required_length char pid
return false; // then not valid return false; // then not valid
} }
return true; return true;
} }
exports.IsValidShortPaymentID = IsValidShortPaymentID; exports.IsValidShortPaymentID = IsValidShortPaymentID;

@ -1,21 +1,21 @@
// Copyright (c) 2014-2018, MyMonero.com // Copyright (c) 2014-2018, MyMonero.com
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -26,126 +26,137 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
"use strict" "use strict";
// //
const monero_config = require('./monero_config') const monero_config = require("./monero_config");
const monero_utils = require('./monero_cryptonote_utils_instance') const monero_utils = require("./monero_cryptonote_utils_instance");
// //
const URITypes = const URITypes = {
{
addressAsFirstPathComponent: 1, addressAsFirstPathComponent: 1,
addressAsAuthority: 2 addressAsAuthority: 2,
}; };
exports.URITypes = URITypes; exports.URITypes = URITypes;
// //
function New_RequestFunds_URI( function New_RequestFunds_URI(args) {
args // -> String?
) { // -> String? const address = args.address;
const address = args.address
if (!address) { if (!address) {
throw "missing address" throw "missing address";
// return null // return null
} }
var mutable_uri = "" var mutable_uri = "";
mutable_uri += monero_config.coinUriPrefix mutable_uri += monero_config.coinUriPrefix;
{ {
const uriType = args.uriType; const uriType = args.uriType;
if (uriType === URITypes.addressAsAuthority) { if (uriType === URITypes.addressAsAuthority) {
mutable_uri += "//" // use for inserting a // so data detectors pick it up… mutable_uri += "//"; // use for inserting a // so data detectors pick it up…
} else if (uriType === URITypes.addressAsFirstPathComponent) { } else if (uriType === URITypes.addressAsFirstPathComponent) {
// nothing to do // nothing to do
} else { } else {
throw "Illegal args.uriType" throw "Illegal args.uriType";
} }
} }
mutable_uri += address mutable_uri += address;
var isAppendingParam0 = true var isAppendingParam0 = true;
function addParam(parameterName, value) function addParam(parameterName, value) {
{ if (
if (value == null || value == ""/*important*/ || typeof value === 'undefined') { value == null ||
return value == "" /*important*/ ||
typeof value === "undefined"
) {
return;
} }
var conjunctionStr = "&" var conjunctionStr = "&";
if (isAppendingParam0 === true) { if (isAppendingParam0 === true) {
isAppendingParam0 = false isAppendingParam0 = false;
conjunctionStr = "?" conjunctionStr = "?";
} }
mutable_uri += conjunctionStr mutable_uri += conjunctionStr;
mutable_uri += parameterName + '=' + encodeURIComponent(value) mutable_uri += parameterName + "=" + encodeURIComponent(value);
} }
{ {
addParam('tx_amount', args.amount) addParam("tx_amount", args.amount);
if ((args.amountCcySymbol || "").toLowerCase() != monero_config.coinSymbol.toLowerCase()) { if (
addParam('tx_amount_ccy', args.amountCcySymbol) (args.amountCcySymbol || "").toLowerCase() !=
monero_config.coinSymbol.toLowerCase()
) {
addParam("tx_amount_ccy", args.amountCcySymbol);
} }
addParam('tx_description', args.description) addParam("tx_description", args.description);
addParam('tx_payment_id', args.payment_id) addParam("tx_payment_id", args.payment_id);
addParam('tx_message', args.message) addParam("tx_message", args.message);
} }
return mutable_uri return mutable_uri;
} }
exports.New_RequestFunds_URI = New_RequestFunds_URI exports.New_RequestFunds_URI = New_RequestFunds_URI;
// //
function New_ParsedPayload_FromPossibleRequestURIString(string, nettype) function New_ParsedPayload_FromPossibleRequestURIString(string, nettype) {
{ // throws; -> {} // throws; -> {}
// //
// detect no-scheme moneroAddr and possible OA addr - if has no monero: prefix // detect no-scheme moneroAddr and possible OA addr - if has no monero: prefix
if (string.indexOf(monero_config.coinUriPrefix) !== 0) { if (string.indexOf(monero_config.coinUriPrefix) !== 0) {
const stringHasQMark = string.indexOf("?") !== -1 const stringHasQMark = string.indexOf("?") !== -1;
if (stringHasQMark) { // fairly sure this is correct.. (just an extra failsafe/filter) if (stringHasQMark) {
throw "Unrecognized URI format" // fairly sure this is correct.. (just an extra failsafe/filter)
throw "Unrecognized URI format";
} }
let couldBeOAAddress = string.indexOf(".") != -1 // contains period - would be nice to get this from DoesStringContainPeriodChar_excludingAsXMRAddress_qualifyingAsPossibleOAAddress so maybe mymonero_core_js should gain local_modules/OpenAlias let couldBeOAAddress = string.indexOf(".") != -1; // contains period - would be nice to get this from DoesStringContainPeriodChar_excludingAsXMRAddress_qualifyingAsPossibleOAAddress so maybe mymonero_core_js should gain local_modules/OpenAlias
if (couldBeOAAddress) { if (couldBeOAAddress) {
return { return {
address: string address: string,
} };
} }
var address__decode_result; var address__decode_result;
try { try {
address__decode_result = monero_utils.decode_address(string, nettype) address__decode_result = monero_utils.decode_address(
string,
nettype,
);
} catch (e) { } catch (e) {
throw "No Monero request info" throw "No Monero request info";
return return;
} }
// then it looks like a monero address // then it looks like a monero address
return { return {
address: string address: string,
} };
} }
const uriString = string const uriString = string;
const url = new URL(uriString) const url = new URL(uriString);
const protocol = url.protocol const protocol = url.protocol;
if (protocol !== monero_config.coinUriPrefix) { if (protocol !== monero_config.coinUriPrefix) {
throw "Request URI has non-Monero protocol" throw "Request URI has non-Monero protocol";
} }
var target_address = url.pathname // var instead of const as have to finalize it var target_address = url.pathname; // var instead of const as have to finalize it
// it seems that if the URL has // in it, pathname will be empty, but host will contain the address instead // it seems that if the URL has // in it, pathname will be empty, but host will contain the address instead
if (target_address === "" || typeof target_address === 'undefined' || !target_address) { if (
target_address = url.host || url.hostname target_address === "" ||
typeof target_address === "undefined" ||
!target_address
) {
target_address = url.host || url.hostname;
} }
if (target_address.indexOf("//") == 0) { if (target_address.indexOf("//") == 0) {
target_address = target_address.slice(0 + "//".length, target_address.length) // strip prefixing "//" in case URL had protocol:// instead of protocol: target_address = target_address.slice(
0 + "//".length,
target_address.length,
); // strip prefixing "//" in case URL had protocol:// instead of protocol:
} }
const searchParams = url.searchParams // needs to be parsed it seems const searchParams = url.searchParams; // needs to be parsed it seems
// //
const payload = const payload = {
{ address: target_address,
address: target_address };
} const keyPrefixToTrim = "tx_";
const keyPrefixToTrim = "tx_" const lengthOf_keyPrefixToTrim = keyPrefixToTrim.length;
const lengthOf_keyPrefixToTrim = keyPrefixToTrim.length searchParams.forEach(function(value, key) {
searchParams.forEach( var storeAt_key = key;
function(value, key) if (key.indexOf(keyPrefixToTrim) === 0) {
{ storeAt_key = key.slice(lengthOf_keyPrefixToTrim, key.length);
var storeAt_key = key
if (key.indexOf(keyPrefixToTrim) === 0) {
storeAt_key = key.slice(lengthOf_keyPrefixToTrim, key.length)
}
payload["" + storeAt_key] = value
} }
) payload["" + storeAt_key] = value;
});
// //
return payload return payload;
} }
exports.New_ParsedPayload_FromPossibleRequestURIString = New_ParsedPayload_FromPossibleRequestURIString exports.New_ParsedPayload_FromPossibleRequestURIString = New_ParsedPayload_FromPossibleRequestURIString;

File diff suppressed because it is too large Load Diff

@ -1,21 +1,21 @@
// Copyright (c) 2014-2018, MyMonero.com // Copyright (c) 2014-2018, MyMonero.com
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -26,25 +26,25 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
"use strict" "use strict";
// //
const monero_config = require('./monero_config') const monero_config = require("./monero_config");
const monero_utils = require('./monero_cryptonote_utils_instance') const monero_utils = require("./monero_cryptonote_utils_instance");
// //
function IsTransactionConfirmed(tx, blockchain_height) function IsTransactionConfirmed(tx, blockchain_height) {
{ return blockchain_height - tx.height > monero_config.txMinConfirms;
return (blockchain_height - tx.height) > monero_config.txMinConfirms
} }
exports.IsTransactionConfirmed = IsTransactionConfirmed exports.IsTransactionConfirmed = IsTransactionConfirmed;
// //
function IsTransactionUnlocked(tx, blockchain_height) function IsTransactionUnlocked(tx, blockchain_height) {
{ return monero_utils.is_tx_unlocked(tx.unlock_time || 0, blockchain_height);
return monero_utils.is_tx_unlocked(tx.unlock_time || 0, blockchain_height)
} }
exports.IsTransactionUnlocked = IsTransactionUnlocked exports.IsTransactionUnlocked = IsTransactionUnlocked;
// //
function TransactionLockedReason(tx, blockchain_height) function TransactionLockedReason(tx, blockchain_height) {
{ return monero_utils.tx_locked_reason(
return monero_utils.tx_locked_reason(tx.unlock_time || 0, blockchain_height) tx.unlock_time || 0,
blockchain_height,
);
} }
exports.TransactionLockedReason = TransactionLockedReason exports.TransactionLockedReason = TransactionLockedReason;

@ -26,22 +26,24 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
"use strict" "use strict";
// //
const monero_wallet_utils = require('./monero_wallet_utils') const monero_wallet_utils = require("./monero_wallet_utils");
// //
function MnemonicWordsetNameWithLocale(currentLocale) // e.g. 'en' function MnemonicWordsetNameWithLocale(
{ currentLocale, // e.g. 'en'
const mnemonicWordsetNamesByAppLocaleNames = monero_wallet_utils.MnemonicWordsetNamesByAppLocaleNames ) {
if (currentLocale.indexOf('en') === 0) { const mnemonicWordsetNamesByAppLocaleNames =
return mnemonicWordsetNamesByAppLocaleNames.English monero_wallet_utils.MnemonicWordsetNamesByAppLocaleNames;
} else if (currentLocale.indexOf('es') === 0) { if (currentLocale.indexOf("en") === 0) {
return mnemonicWordsetNamesByAppLocaleNames.Spanish return mnemonicWordsetNamesByAppLocaleNames.English;
} else if (currentLocale.indexOf('pt') === 0) { } else if (currentLocale.indexOf("es") === 0) {
return mnemonicWordsetNamesByAppLocaleNames.Portuguese return mnemonicWordsetNamesByAppLocaleNames.Spanish;
} else if (currentLocale.indexOf('ja') === 0) { } else if (currentLocale.indexOf("pt") === 0) {
return mnemonicWordsetNamesByAppLocaleNames.Japanese return mnemonicWordsetNamesByAppLocaleNames.Portuguese;
} else if (currentLocale.indexOf("ja") === 0) {
return mnemonicWordsetNamesByAppLocaleNames.Japanese;
} }
return monero_wallet_utils.DefaultWalletMnemonicWordsetName // which would be .English return monero_wallet_utils.DefaultWalletMnemonicWordsetName; // which would be .English
} }
exports.MnemonicWordsetNameWithLocale = MnemonicWordsetNameWithLocale exports.MnemonicWordsetNameWithLocale = MnemonicWordsetNameWithLocale;

@ -1,21 +1,21 @@
// Copyright (c) 2014-2018, MyMonero.com // Copyright (c) 2014-2018, MyMonero.com
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -26,305 +26,352 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"use strict" "use strict";
// //
const mnemonic = require('../cryptonote_utils/mnemonic') const mnemonic = require("../cryptonote_utils/mnemonic");
const monero_utils = require('./monero_cryptonote_utils_instance') const monero_utils = require("./monero_cryptonote_utils_instance");
const monero_config = require('./monero_config') const monero_config = require("./monero_config");
// //
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Mnemonic wordset utilities - Exposing available names // Mnemonic wordset utilities - Exposing available names
// //
const wordsetNamesByWordsetName = {} const wordsetNamesByWordsetName = {};
const allWordsetNames = Object.keys(mnemonic.mn_words) const allWordsetNames = Object.keys(mnemonic.mn_words);
for (let wordsetName of allWordsetNames) { for (let wordsetName of allWordsetNames) {
wordsetNamesByWordsetName[wordsetName] = wordsetName wordsetNamesByWordsetName[wordsetName] = wordsetName;
} }
exports.WordsetNamesByWordsetName = wordsetNamesByWordsetName exports.WordsetNamesByWordsetName = wordsetNamesByWordsetName;
exports.AllWordsetNames = allWordsetNames exports.AllWordsetNames = allWordsetNames;
// //
// //
// Mnemonic wordset utilities - Comparison // Mnemonic wordset utilities - Comparison
// TODO: perhaps move this to mnemonic.js // TODO: perhaps move this to mnemonic.js
function AreEqualMnemonics( function AreEqualMnemonics(a, b, a__wordsetName, b__wordsetName) {
a,
b,
a__wordsetName,
b__wordsetName
) {
if (a__wordsetName !== b__wordsetName) { if (a__wordsetName !== b__wordsetName) {
return false return false;
} }
const wordsetName = a__wordsetName const wordsetName = a__wordsetName;
const wordset = mnemonic.mn_words[wordsetName] const wordset = mnemonic.mn_words[wordsetName];
const prefix_len = wordset.prefix_len const prefix_len = wordset.prefix_len;
// since mnemonics can be entered with only the first N letters, we must check equality of mnemonics by prefix // since mnemonics can be entered with only the first N letters, we must check equality of mnemonics by prefix
let a__mnemonicString_words = a.split(" ") let a__mnemonicString_words = a.split(" ");
let b__mnemonicString_words = b.split(" ") let b__mnemonicString_words = b.split(" ");
if (a__mnemonicString_words.length != b__mnemonicString_words.length) { if (a__mnemonicString_words.length != b__mnemonicString_words.length) {
return false return false;
} }
let numberOf_mnemonicString_words = a__mnemonicString_words.length let numberOf_mnemonicString_words = a__mnemonicString_words.length;
for (var i = 0 ; i < numberOf_mnemonicString_words ; i++) { for (var i = 0; i < numberOf_mnemonicString_words; i++) {
let a__word = a__mnemonicString_words[i] let a__word = a__mnemonicString_words[i];
let b__word = b__mnemonicString_words[i] let b__word = b__mnemonicString_words[i];
// ... We're assuming that a and b are already valid mneminics // ... We're assuming that a and b are already valid mneminics
const a_prefix = a__word.slice(0, prefix_len) const a_prefix = a__word.slice(0, prefix_len);
const b_prefix = b__word.slice(0, prefix_len) const b_prefix = b__word.slice(0, prefix_len);
if (a_prefix !== b_prefix) { if (a_prefix !== b_prefix) {
return false return false;
} }
} }
return true return true;
} }
exports.AreEqualMnemonics = AreEqualMnemonics exports.AreEqualMnemonics = AreEqualMnemonics;
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Mnemonic wordset utilities - Wordset name detection by mnemonic contents // Mnemonic wordset utilities - Wordset name detection by mnemonic contents
// TODO: perhaps move this to mnemonic.js // TODO: perhaps move this to mnemonic.js
function WordsetNameAccordingToMnemonicString(mnemonicString) // throws function WordsetNameAccordingToMnemonicString(
{ mnemonicString, // throws
const mnemonicString_words = mnemonicString.split(' ') ) {
const mnemonicString_words = mnemonicString.split(" ");
if (mnemonicString_words.length == 0) { if (mnemonicString_words.length == 0) {
throw "Invalid mnemonic" throw "Invalid mnemonic";
} }
var wholeMnemonicSuspectedAsWordsetNamed = null // to derive var wholeMnemonicSuspectedAsWordsetNamed = null; // to derive
for (let mnemonicString_word of mnemonicString_words) { for (let mnemonicString_word of mnemonicString_words) {
var thisWordIsInWordsetNamed = null // to derive var thisWordIsInWordsetNamed = null; // to derive
for (let wordsetName of allWordsetNames) { for (let wordsetName of allWordsetNames) {
if (wordsetName === 'electrum') { if (wordsetName === "electrum") {
continue // skip because it conflicts with 'english' continue; // skip because it conflicts with 'english'
} }
const wordset = mnemonic.mn_words[wordsetName] const wordset = mnemonic.mn_words[wordsetName];
const prefix_len = wordset.prefix_len const prefix_len = wordset.prefix_len;
if (mnemonicString_word.length < prefix_len) { if (mnemonicString_word.length < prefix_len) {
throw "Please enter more than " + (prefix_len-1) + " letters per word" throw "Please enter more than " +
(prefix_len - 1) +
" letters per word";
} }
const wordsetWords = wordset.words const wordsetWords = wordset.words;
for (let wordsetWord of wordsetWords) { for (let wordsetWord of wordsetWords) {
if (wordsetWord.indexOf(mnemonicString_word) == 0) { // we can safely check prefix b/c we've checked mnemonicString_word is of at least min length if (wordsetWord.indexOf(mnemonicString_word) == 0) {
thisWordIsInWordsetNamed = wordsetName // we can safely check prefix b/c we've checked mnemonicString_word is of at least min length
break // done looking; exit interior then exterior loops thisWordIsInWordsetNamed = wordsetName;
break; // done looking; exit interior then exterior loops
} }
} }
if (thisWordIsInWordsetNamed != null) { // just found if (thisWordIsInWordsetNamed != null) {
break // also exit // just found
break; // also exit
} }
// haven't found it yet; keep looking // haven't found it yet; keep looking
} }
if (thisWordIsInWordsetNamed === null) { // didn't find this word in any of the mnemonic wordsets if (thisWordIsInWordsetNamed === null) {
throw "Unrecognized mnemonic language" // didn't find this word in any of the mnemonic wordsets
throw "Unrecognized mnemonic language";
} }
if (wholeMnemonicSuspectedAsWordsetNamed === null) { // haven't found it yet if (wholeMnemonicSuspectedAsWordsetNamed === null) {
wholeMnemonicSuspectedAsWordsetNamed = thisWordIsInWordsetNamed // haven't found it yet
} else if (thisWordIsInWordsetNamed !== wholeMnemonicSuspectedAsWordsetNamed) { wholeMnemonicSuspectedAsWordsetNamed = thisWordIsInWordsetNamed;
throw "Ambiguous mnemonic language" // multiple wordset names detected } else if (
thisWordIsInWordsetNamed !== wholeMnemonicSuspectedAsWordsetNamed
) {
throw "Ambiguous mnemonic language"; // multiple wordset names detected
} else { } else {
// nothing to do but keep verifying the rest of the words that it's the same suspsected wordset // nothing to do but keep verifying the rest of the words that it's the same suspsected wordset
} }
} }
if (wholeMnemonicSuspectedAsWordsetNamed === null) { // this might be redundant, but for logical rigor…… if (wholeMnemonicSuspectedAsWordsetNamed === null) {
throw "Unrecognized mnemonic language" // this might be redundant, but for logical rigor……
throw "Unrecognized mnemonic language";
} }
// //
return wholeMnemonicSuspectedAsWordsetNamed return wholeMnemonicSuspectedAsWordsetNamed;
} }
exports.WordsetNameAccordingToMnemonicString = WordsetNameAccordingToMnemonicString exports.WordsetNameAccordingToMnemonicString = WordsetNameAccordingToMnemonicString;
// //
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Mnemonic wordset utilities - By locale // Mnemonic wordset utilities - By locale
// //
const mnemonicWordsetNamesByAppLocaleNames = const mnemonicWordsetNamesByAppLocaleNames = {
{
English: "english", English: "english",
Japanese: "japanese", Japanese: "japanese",
Spanish: "spanish", Spanish: "spanish",
Portuguese: "portuguese" Portuguese: "portuguese",
// NOTE: no support for 'electrum' wordset here // NOTE: no support for 'electrum' wordset here
} };
exports.MnemonicWordsetNamesByAppLocaleNames = mnemonicWordsetNamesByAppLocaleNames exports.MnemonicWordsetNamesByAppLocaleNames = mnemonicWordsetNamesByAppLocaleNames;
// //
exports.DefaultWalletMnemonicWordsetName = mnemonicWordsetNamesByAppLocaleNames.English exports.DefaultWalletMnemonicWordsetName =
mnemonicWordsetNamesByAppLocaleNames.English;
// //
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Wallet creation: // Wallet creation:
// //
function NewlyCreatedWallet(mnemonic_wordsetName, nettype) function NewlyCreatedWallet(mnemonic_wordsetName, nettype) {
{ const seed = monero_utils.random_scalar(); // to generate a 32-byte (25-word) but reduced seed
const seed = monero_utils.random_scalar() // to generate a 32-byte (25-word) but reduced seed const mnemonicString = mnemonic.mn_encode(seed, mnemonic_wordsetName);
const mnemonicString = mnemonic.mn_encode(seed, mnemonic_wordsetName) const keys = monero_utils.create_address(seed, nettype);
const keys = monero_utils.create_address(seed, nettype)
// //
return { return {
seed: seed, seed: seed,
mnemonicString: mnemonicString, mnemonicString: mnemonicString,
keys: keys keys: keys,
} };
} }
exports.NewlyCreatedWallet = NewlyCreatedWallet exports.NewlyCreatedWallet = NewlyCreatedWallet;
// //
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Wallet login: // Wallet login:
// //
function MnemonicStringFromSeed(account_seed, mnemonic_wordsetName) function MnemonicStringFromSeed(account_seed, mnemonic_wordsetName) {
{ const mnemonicString = mnemonic.mn_encode(
const mnemonicString = mnemonic.mn_encode(account_seed, mnemonic_wordsetName) account_seed,
mnemonic_wordsetName,
);
// //
return mnemonicString return mnemonicString;
} }
exports.MnemonicStringFromSeed = MnemonicStringFromSeed exports.MnemonicStringFromSeed = MnemonicStringFromSeed;
// //
function SeedAndKeysFromMnemonic_sync(mnemonicString, mnemonic_wordsetName, nettype) function SeedAndKeysFromMnemonic_sync(
{ // -> {err_str?, seed?, keys?} mnemonicString,
mnemonicString = mnemonicString.toLowerCase() || "" mnemonic_wordsetName,
nettype,
) {
// -> {err_str?, seed?, keys?}
mnemonicString = mnemonicString.toLowerCase() || "";
try { try {
var seed = null var seed = null;
var keys = null var keys = null;
switch (mnemonic_wordsetName) { switch (mnemonic_wordsetName) {
case 'english': case "english":
try { try {
seed = mnemonic.mn_decode(mnemonicString) seed = mnemonic.mn_decode(mnemonicString);
} catch (e) { } catch (e) {
// Try decoding as an electrum seed, on failure throw the original exception // Try decoding as an electrum seed, on failure throw the original exception
try { try {
seed = mnemonic.mn_decode(mnemonicString, "electrum") seed = mnemonic.mn_decode(mnemonicString, "electrum");
} catch (ee) { } catch (ee) {
throw e throw e;
} }
} }
break break;
default: default:
seed = mnemonic.mn_decode(mnemonicString, mnemonic_wordsetName) seed = mnemonic.mn_decode(mnemonicString, mnemonic_wordsetName);
break break;
} }
if (seed === null) { if (seed === null) {
return { err_str: "Unable to derive seed", seed: null, keys: null } return { err_str: "Unable to derive seed", seed: null, keys: null };
} }
keys = monero_utils.create_address(seed, nettype) keys = monero_utils.create_address(seed, nettype);
if (keys === null) { if (keys === null) {
return { err_str: "Unable to derive keys from seed", seed: seed, keys: null } return {
err_str: "Unable to derive keys from seed",
seed: seed,
keys: null,
};
} }
return { err_str: null, seed: seed, keys: keys } return { err_str: null, seed: seed, keys: keys };
} catch (e) { } catch (e) {
console.error("Invalid mnemonic!") console.error("Invalid mnemonic!");
return { err_str: typeof e === 'string' ? e : ""+e, seed: null, keys: null } return {
err_str: typeof e === "string" ? e : "" + e,
seed: null,
keys: null,
};
} }
} }
exports.SeedAndKeysFromMnemonic_sync = SeedAndKeysFromMnemonic_sync exports.SeedAndKeysFromMnemonic_sync = SeedAndKeysFromMnemonic_sync;
function SeedAndKeysFromMnemonic(mnemonicString, mnemonic_wordsetName, nettype, fn) // made available via callback not because it's async but for convenience function SeedAndKeysFromMnemonic(
{ // fn: (err?, seed?, keys?) mnemonicString,
const payload = SeedAndKeysFromMnemonic_sync(mnemonicString, mnemonic_wordsetName, nettype) mnemonic_wordsetName,
const err = payload.err_str ? new Error(payload.err_str) : null nettype,
const seed = payload.seed fn, // made available via callback not because it's async but for convenience
const keys = payload.keys ) {
fn(err, seed, keys) // fn: (err?, seed?, keys?)
const payload = SeedAndKeysFromMnemonic_sync(
mnemonicString,
mnemonic_wordsetName,
nettype,
);
const err = payload.err_str ? new Error(payload.err_str) : null;
const seed = payload.seed;
const keys = payload.keys;
fn(err, seed, keys);
} }
exports.SeedAndKeysFromMnemonic = SeedAndKeysFromMnemonic exports.SeedAndKeysFromMnemonic = SeedAndKeysFromMnemonic;
// //
function VerifiedComponentsForLogIn_sync( function VerifiedComponentsForLogIn_sync(
address, address,
nettype, nettype,
view_key, view_key,
spend_key_orUndefinedForViewOnly, spend_key_orUndefinedForViewOnly,
seed_orUndefined, seed_orUndefined,
wasAGeneratedWallet wasAGeneratedWallet,
) { ) {
var spend_key = typeof spend_key_orUndefinedForViewOnly !== 'undefined' && spend_key_orUndefinedForViewOnly != null && spend_key_orUndefinedForViewOnly != "" ? spend_key_orUndefinedForViewOnly : null var spend_key =
typeof spend_key_orUndefinedForViewOnly !== "undefined" &&
spend_key_orUndefinedForViewOnly != null &&
spend_key_orUndefinedForViewOnly != ""
? spend_key_orUndefinedForViewOnly
: null;
var isInViewOnlyMode = spend_key == null; var isInViewOnlyMode = spend_key == null;
if (!view_key || view_key.length !== 64 || (isInViewOnlyMode ? false : spend_key.length !== 64)) { if (
return { err_str: "invalid secret key length" } !view_key ||
view_key.length !== 64 ||
(isInViewOnlyMode ? false : spend_key.length !== 64)
) {
return { err_str: "invalid secret key length" };
} }
if (!monero_utils.valid_hex(view_key) || (isInViewOnlyMode ? false : !monero_utils.valid_hex(spend_key))) { if (
return { err_str: "invalid hex formatting" } !monero_utils.valid_hex(view_key) ||
(isInViewOnlyMode ? false : !monero_utils.valid_hex(spend_key))
) {
return { err_str: "invalid hex formatting" };
} }
var public_keys; var public_keys;
try { try {
public_keys = monero_utils.decode_address(address, nettype) public_keys = monero_utils.decode_address(address, nettype);
} catch (e) { } catch (e) {
return { err_str: "invalid address" } return { err_str: "invalid address" };
} }
var expected_view_pub; var expected_view_pub;
try { try {
expected_view_pub = monero_utils.sec_key_to_pub(view_key) expected_view_pub = monero_utils.sec_key_to_pub(view_key);
} catch (e) { } catch (e) {
return { err_str: "invalid view key" } return { err_str: "invalid view key" };
} }
var expected_spend_pub var expected_spend_pub;
if (spend_key.length === 64) { if (spend_key.length === 64) {
try { try {
expected_spend_pub = monero_utils.sec_key_to_pub(spend_key) expected_spend_pub = monero_utils.sec_key_to_pub(spend_key);
} catch (e) { } catch (e) {
return { err_str: "invalid spend key" } return { err_str: "invalid spend key" };
} }
} }
if (public_keys.view !== expected_view_pub) { if (public_keys.view !== expected_view_pub) {
return { err_str: "invalid view key" } return { err_str: "invalid view key" };
} }
if (!isInViewOnlyMode && (public_keys.spend !== expected_spend_pub)) { if (!isInViewOnlyMode && public_keys.spend !== expected_spend_pub) {
return { err_str: "invalid spend key" } return { err_str: "invalid spend key" };
} }
const private_keys = const private_keys = {
{
view: view_key, view: view_key,
spend: spend_key spend: spend_key,
} };
var account_seed = null; // default var account_seed = null; // default
if (typeof seed_orUndefined !== 'undefined' && seed_orUndefined && seed_orUndefined.length != 0) { if (
typeof seed_orUndefined !== "undefined" &&
seed_orUndefined &&
seed_orUndefined.length != 0
) {
var expected_account; var expected_account;
try { try {
expected_account = monero_utils.create_address(seed_orUndefined, nettype) expected_account = monero_utils.create_address(
seed_orUndefined,
nettype,
);
} catch (e) { } catch (e) {
return { err_str: "invalid seed" } return { err_str: "invalid seed" };
} }
if (expected_account.view.sec !== view_key || if (
expected_account.view.sec !== view_key ||
expected_account.spend.sec !== spend_key || expected_account.spend.sec !== spend_key ||
expected_account.public_addr !== address) { expected_account.public_addr !== address
return { err_str: "invalid seed" } ) {
return { err_str: "invalid seed" };
} }
account_seed = seed_orUndefined account_seed = seed_orUndefined;
} }
const payload = const payload = {
{
err_str: null, // err err_str: null, // err
address: address, address: address,
account_seed: account_seed !== "" ? account_seed : null, account_seed: account_seed !== "" ? account_seed : null,
public_keys: public_keys, public_keys: public_keys,
private_keys: private_keys, private_keys: private_keys,
isInViewOnlyMode: isInViewOnlyMode isInViewOnlyMode: isInViewOnlyMode,
} };
return payload return payload;
} }
exports.VerifiedComponentsForLogIn_sync = VerifiedComponentsForLogIn_sync exports.VerifiedComponentsForLogIn_sync = VerifiedComponentsForLogIn_sync;
// //
function VerifiedComponentsForLogIn( function VerifiedComponentsForLogIn(
address, address,
nettype, nettype,
view_key, view_key,
spend_key_orUndefinedForViewOnly, spend_key_orUndefinedForViewOnly,
seed_orUndefined, seed_orUndefined,
wasAGeneratedWallet, wasAGeneratedWallet,
fn fn,
) { // fn: (err?, address, account_seed, public_keys, private_keys, isInViewOnlyMode) -> Void ) {
// fn: (err?, address, account_seed, public_keys, private_keys, isInViewOnlyMode) -> Void
const payload = VerifiedComponentsForLogIn_sync( const payload = VerifiedComponentsForLogIn_sync(
address, address,
nettype, nettype,
view_key, view_key,
spend_key_orUndefinedForViewOnly, spend_key_orUndefinedForViewOnly,
seed_orUndefined, seed_orUndefined,
wasAGeneratedWallet wasAGeneratedWallet,
) );
fn( fn(
payload.err_str ? new Error(payload.err_str) : null, payload.err_str ? new Error(payload.err_str) : null,
payload.address, payload.address,
payload.account_seed, payload.account_seed,
payload.public_keys, payload.public_keys,
payload.private_keys, payload.private_keys,
payload.isInViewOnlyMode payload.isInViewOnlyMode,
) );
} }
exports.VerifiedComponentsForLogIn = VerifiedComponentsForLogIn exports.VerifiedComponentsForLogIn = VerifiedComponentsForLogIn;

@ -7,6 +7,9 @@
"type": "git", "type": "git",
"url": "git+https://github.com/mymonero/mymonero-core-js.git" "url": "git+https://github.com/mymonero/mymonero-core-js.git"
}, },
"scripts": {
"format": "find . -name '*.js*' | xargs prettier --write --config ./.prettierrc --config-precedence file-override"
},
"keywords": [ "keywords": [
"monero", "monero",
"mymonero", "mymonero",

@ -1,61 +1,120 @@
"use strict" "use strict";
const mymonero = require('mymonero-core-js'); const mymonero = require("mymonero-core-js");
const assert = require('assert'); const assert = require("assert");
var public_key = "904e49462268d771cc1649084c35aa1296bfb214880fe2e7f373620a3e2ba597"; var public_key =
var private_key = "52aa4c69b93b780885c9d7f51e6fd5795904962c61a2e07437e130784846f70d"; "904e49462268d771cc1649084c35aa1296bfb214880fe2e7f373620a3e2ba597";
var private_key =
"52aa4c69b93b780885c9d7f51e6fd5795904962c61a2e07437e130784846f70d";
var nettype = mymonero.nettype_utils.network_type.MAINNNET; var nettype = mymonero.nettype_utils.network_type.MAINNNET;
describe('cryptonote_utils tests', function() { describe("cryptonote_utils tests", function() {
it("is valid hex", function() {
it('is valid hex', function() {
var valid = mymonero.monero_utils.valid_hex(private_key); var valid = mymonero.monero_utils.valid_hex(private_key);
assert.strictEqual(valid, true); assert.strictEqual(valid, true);
}); });
it('fast hash / keccak-256', function() { it("fast hash / keccak-256", function() {
var hash = mymonero.monero_utils.cn_fast_hash(private_key , private_key.length); var hash = mymonero.monero_utils.cn_fast_hash(
assert.equal(hash, "64997ff54f0d82ee87d51e971a0329d4315481eaeb4ad2403c65d5843480c414"); private_key,
private_key.length,
);
assert.equal(
hash,
"64997ff54f0d82ee87d51e971a0329d4315481eaeb4ad2403c65d5843480c414",
);
}); });
it('generate key derivation', function() { it("generate key derivation", function() {
var derivation = mymonero.monero_utils.generate_key_derivation(public_key, private_key); var derivation = mymonero.monero_utils.generate_key_derivation(
assert.equal(derivation, "591c749f1868c58f37ec3d2a9d2f08e7f98417ac4f8131e3a57c1fd71273ad00"); public_key,
private_key,
);
assert.equal(
derivation,
"591c749f1868c58f37ec3d2a9d2f08e7f98417ac4f8131e3a57c1fd71273ad00",
);
}); });
it('decode mainnet primary address', function() { it("decode mainnet primary address", function() {
var decoded = mymonero.monero_utils.decode_address("49qwWM9y7j1fvaBK684Y5sMbN8MZ3XwDLcSaqcKwjh5W9kn9qFigPBNBwzdq6TCAm2gKxQWrdZuEZQBMjQodi9cNRHuCbTr", nettype); var decoded = mymonero.monero_utils.decode_address(
var expected = { spend: "d8f1e81ecbe25ce8b596d426fb02fe7b1d4bb8d14c06b3d3e371a60eeea99534", view: "576f0e61e250d941746ed147f602b5eb1ea250ca385b028a935e166e18f74bd7" } "49qwWM9y7j1fvaBK684Y5sMbN8MZ3XwDLcSaqcKwjh5W9kn9qFigPBNBwzdq6TCAm2gKxQWrdZuEZQBMjQodi9cNRHuCbTr",
nettype,
);
var expected = {
spend:
"d8f1e81ecbe25ce8b596d426fb02fe7b1d4bb8d14c06b3d3e371a60eeea99534",
view:
"576f0e61e250d941746ed147f602b5eb1ea250ca385b028a935e166e18f74bd7",
};
assert.deepEqual(decoded, expected); assert.deepEqual(decoded, expected);
}); });
it('decode mainnet integrated address', function() { it("decode mainnet integrated address", function() {
var decoded = mymonero.monero_utils.decode_address("4KYcX9yTizXfvaBK684Y5sMbN8MZ3XwDLcSaqcKwjh5W9kn9qFigPBNBwzdq6TCAm2gKxQWrdZuEZQBMjQodi9cNd3mZpgrjXBKMx9ee7c", nettype); var decoded = mymonero.monero_utils.decode_address(
var expected = { spend: "d8f1e81ecbe25ce8b596d426fb02fe7b1d4bb8d14c06b3d3e371a60eeea99534", view: "576f0e61e250d941746ed147f602b5eb1ea250ca385b028a935e166e18f74bd7", intPaymentId: "83eab71fbee84eb9" } "4KYcX9yTizXfvaBK684Y5sMbN8MZ3XwDLcSaqcKwjh5W9kn9qFigPBNBwzdq6TCAm2gKxQWrdZuEZQBMjQodi9cNd3mZpgrjXBKMx9ee7c",
nettype,
);
var expected = {
spend:
"d8f1e81ecbe25ce8b596d426fb02fe7b1d4bb8d14c06b3d3e371a60eeea99534",
view:
"576f0e61e250d941746ed147f602b5eb1ea250ca385b028a935e166e18f74bd7",
intPaymentId: "83eab71fbee84eb9",
};
assert.deepEqual(decoded, expected); assert.deepEqual(decoded, expected);
}); });
it('hash_to_scalar', function() { it("hash_to_scalar", function() {
var scalar = mymonero.monero_utils.hash_to_scalar(private_key); var scalar = mymonero.monero_utils.hash_to_scalar(private_key);
assert.equal(scalar, "77c5899835aa6f96b13827f43b094abf315481eaeb4ad2403c65d5843480c404"); assert.equal(
scalar,
"77c5899835aa6f96b13827f43b094abf315481eaeb4ad2403c65d5843480c404",
);
}); });
it('derivation_to_scalar', function() { it("derivation_to_scalar", function() {
var derivation = mymonero.monero_utils.generate_key_derivation(public_key, private_key); var derivation = mymonero.monero_utils.generate_key_derivation(
public_key,
private_key,
);
var scalar = mymonero.monero_utils.derivation_to_scalar(derivation, 1); var scalar = mymonero.monero_utils.derivation_to_scalar(derivation, 1);
assert.equal(scalar, "201ce3c258e09eeb6132ec266d24ee1ca957828f384ce052d5bc217c2c55160d"); assert.equal(
}); scalar,
"201ce3c258e09eeb6132ec266d24ee1ca957828f384ce052d5bc217c2c55160d",
it('derive public key', function() { );
var derivation = mymonero.monero_utils.generate_key_derivation(public_key, private_key); });
var output_key = mymonero.monero_utils.derive_public_key(derivation, 1, public_key);
assert.equal(output_key, "da26518ddb54cde24ccfc59f36df13bbe9bdfcb4ef1b223d9ab7bef0a50c8be3"); it("derive public key", function() {
}); var derivation = mymonero.monero_utils.generate_key_derivation(
public_key,
it('derive subaddress public key', function() { private_key,
var derivation = mymonero.monero_utils.generate_key_derivation(public_key, private_key); );
var subaddress_public_key = mymonero.monero_utils.derive_subaddress_public_key(public_key, derivation, 1); var output_key = mymonero.monero_utils.derive_public_key(
assert.equal(subaddress_public_key, "dfc9e4a0039e913204c1c0f78e954a7ec7ce291d8ffe88265632f0da9d8de1be") derivation,
1,
public_key,
);
assert.equal(
output_key,
"da26518ddb54cde24ccfc59f36df13bbe9bdfcb4ef1b223d9ab7bef0a50c8be3",
);
});
it("derive subaddress public key", function() {
var derivation = mymonero.monero_utils.generate_key_derivation(
public_key,
private_key,
);
var subaddress_public_key = mymonero.monero_utils.derive_subaddress_public_key(
public_key,
derivation,
1,
);
assert.equal(
subaddress_public_key,
"dfc9e4a0039e913204c1c0f78e954a7ec7ce291d8ffe88265632f0da9d8de1be",
);
}); });
}); });

@ -0,0 +1,17 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
async@^2.6.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610"
dependencies:
lodash "^4.17.10"
lodash@^4.17.10:
version "4.17.10"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
prettier@^1.13.5:
version "1.13.5"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.5.tgz#7ae2076998c8edce79d63834e9b7b09fead6bfd0"
Loading…
Cancel
Save