You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
5.3 KiB
157 lines
5.3 KiB
// Copyright (c) 2014-2019, MyMonero.com
|
|
//
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without modification, are
|
|
// permitted provided that the following conditions are met:
|
|
//
|
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
// conditions and the following disclaimer.
|
|
//
|
|
// 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
|
|
// materials provided with the distribution.
|
|
//
|
|
// 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
|
|
// prior written permission.
|
|
//
|
|
// 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
|
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
// 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.
|
|
//
|
|
"use strict";
|
|
//
|
|
const response_parser_utils = require("./response_parser_utils");
|
|
const JSBigInt = require("../cryptonote_utils/biginteger").BigInteger; // important: grab defined export
|
|
//
|
|
function New_ParametersForWalletRequest(address, view_key__private) {
|
|
return {
|
|
address: address,
|
|
view_key: view_key__private,
|
|
};
|
|
}
|
|
exports.New_ParametersForWalletRequest = New_ParametersForWalletRequest;
|
|
//
|
|
function AddUserAgentParamters(
|
|
parameters,
|
|
appUserAgent_product,
|
|
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
|
|
parameters["app_name"] = appUserAgent_product;
|
|
parameters["app_version"] = appUserAgent_version;
|
|
}
|
|
exports.AddUserAgentParamters = AddUserAgentParamters;
|
|
//
|
|
function HTTPRequest(
|
|
request_conformant_module, // such as 'request' or 'xhr' .. TODO: consider switching to 'fetch'
|
|
apiAddress_authority, // authority means [subdomain.]host.…[:…] with no trailing slash
|
|
endpointPath,
|
|
final_parameters,
|
|
fn,
|
|
) {
|
|
// fn: (err?, data?) -> new Request
|
|
if (typeof final_parameters == "undefined" || final_parameters == null) {
|
|
throw "final_parameters must not be nil";
|
|
// return null
|
|
}
|
|
const completeURL =
|
|
_new_APIAddress_baseURLString(apiAddress_authority) + endpointPath;
|
|
console.log("📡 " + completeURL);
|
|
//
|
|
const request_options = _new_requestOptions_base(
|
|
"POST",
|
|
completeURL,
|
|
final_parameters,
|
|
);
|
|
const requestHandle = request_conformant_module(request_options, function(
|
|
err_orProgressEvent,
|
|
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;
|
|
}
|
|
exports.HTTPRequest = HTTPRequest;
|
|
//
|
|
function _new_APIAddress_baseURLString(
|
|
apiAddress_authority, // authority means [subdomain.]host.…[:…]
|
|
) {
|
|
return "https" + "://" + apiAddress_authority + "/";
|
|
}
|
|
function _new_requestOptions_base(methodName, completeURL, json_parameters) {
|
|
return {
|
|
method: methodName,
|
|
url: completeURL,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Accept: "application/json",
|
|
},
|
|
json: json_parameters,
|
|
useXDR: true, // CORS
|
|
withCredentials: true, // CORS
|
|
};
|
|
}
|
|
function _new_HTTPRequestHandlerFunctionCallingFn(fn) {
|
|
return function(completeURL, err_orProgressEvent, res, body) {
|
|
// err appears to actually be a ProgressEvent
|
|
var err = null;
|
|
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
|
|
err = new Error("Connection Failure");
|
|
} else if (statusCode !== 200) {
|
|
const body_Error =
|
|
body && typeof body == "object" ? body.Error : undefined;
|
|
const statusMessage =
|
|
res && res.statusMessage ? res.statusMessage : undefined;
|
|
if (typeof body_Error !== "undefined" && body_Error) {
|
|
err = new Error(body_Error);
|
|
} else if (typeof statusMessage !== "undefined" && statusMessage) {
|
|
err = new Error(statusMessage);
|
|
} else {
|
|
err = new Error("Unknown " + statusCode + " error");
|
|
}
|
|
}
|
|
if (err) {
|
|
console.error("❌ " + err);
|
|
// console.error("Body:", body)
|
|
fn(err, null);
|
|
return;
|
|
}
|
|
var json;
|
|
if (typeof body === "string") {
|
|
try {
|
|
json = JSON.parse(body);
|
|
} catch (e) {
|
|
console.error(
|
|
"❌ HostedMoneroAPIClient Error: Unable to parse json with exception:",
|
|
e,
|
|
"\nbody:",
|
|
body,
|
|
);
|
|
fn(e, null);
|
|
}
|
|
} else {
|
|
json = body;
|
|
}
|
|
console.log("✅ " + completeURL + " " + statusCode);
|
|
fn(null, json);
|
|
};
|
|
}
|