Refactor request URI (#12)

pull/40/head
HenryNguyen5 6 years ago committed by GitHub
parent 8144743eda
commit baaf82f381
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -35,7 +35,7 @@ mymonero_core_js.monero_utils = require("./monero_utils/monero_cryptonote_utils_
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_sendingFunds_utils = require("./monero_utils/monero_sendingFunds_utils");
mymonero_core_js.monero_requestURI_utils = require("./monero_utils/monero_requestURI_utils");
mymonero_core_js.request_funds_uri_utils = require("./monero_utils/request_funds_uri_utils");
mymonero_core_js.key_image_utils = require("./monero_utils/key_image_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");

@ -1,162 +0,0 @@
// Copyright (c) 2014-2018, 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 monero_config = require("./monero_config");
const monero_utils = require("./monero_cryptonote_utils_instance");
//
const URITypes = {
addressAsFirstPathComponent: 1,
addressAsAuthority: 2,
};
exports.URITypes = URITypes;
//
function New_RequestFunds_URI(args) {
// -> String?
const address = args.address;
if (!address) {
throw "missing address";
// return null
}
var mutable_uri = "";
mutable_uri += monero_config.coinUriPrefix;
{
const uriType = args.uriType;
if (uriType === URITypes.addressAsAuthority) {
mutable_uri += "//"; // use for inserting a // so data detectors pick it up…
} else if (uriType === URITypes.addressAsFirstPathComponent) {
// nothing to do
} else {
throw "Illegal args.uriType";
}
}
mutable_uri += address;
var isAppendingParam0 = true;
function addParam(parameterName, value) {
if (
value == null ||
value == "" /*important*/ ||
typeof value === "undefined"
) {
return;
}
var conjunctionStr = "&";
if (isAppendingParam0 === true) {
isAppendingParam0 = false;
conjunctionStr = "?";
}
mutable_uri += conjunctionStr;
mutable_uri += parameterName + "=" + encodeURIComponent(value);
}
{
addParam("tx_amount", args.amount);
if (
(args.amountCcySymbol || "").toLowerCase() !=
monero_config.coinSymbol.toLowerCase()
) {
addParam("tx_amount_ccy", args.amountCcySymbol);
}
addParam("tx_description", args.description);
addParam("tx_payment_id", args.payment_id);
addParam("tx_message", args.message);
}
return mutable_uri;
}
exports.New_RequestFunds_URI = New_RequestFunds_URI;
//
function New_ParsedPayload_FromPossibleRequestURIString(string, nettype) {
// throws; -> {}
//
// detect no-scheme moneroAddr and possible OA addr - if has no monero: prefix
if (string.indexOf(monero_config.coinUriPrefix) !== 0) {
const stringHasQMark = string.indexOf("?") !== -1;
if (stringHasQMark) {
// 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
if (couldBeOAAddress) {
return {
address: string,
};
}
var address__decode_result;
try {
address__decode_result = monero_utils.decode_address(
string,
nettype,
);
} catch (e) {
throw "No Monero request info";
return;
}
// then it looks like a monero address
return {
address: string,
};
}
const uriString = string;
const url = new URL(uriString);
const protocol = url.protocol;
if (protocol !== monero_config.coinUriPrefix) {
throw "Request URI has non-Monero protocol";
}
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
if (
target_address === "" ||
typeof target_address === "undefined" ||
!target_address
) {
target_address = url.host || url.hostname;
}
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:
}
const searchParams = url.searchParams; // needs to be parsed it seems
//
const payload = {
address: target_address,
};
const keyPrefixToTrim = "tx_";
const lengthOf_keyPrefixToTrim = keyPrefixToTrim.length;
searchParams.forEach(function(value, key) {
var storeAt_key = key;
if (key.indexOf(keyPrefixToTrim) === 0) {
storeAt_key = key.slice(lengthOf_keyPrefixToTrim, key.length);
}
payload["" + storeAt_key] = value;
});
//
return payload;
}
exports.New_ParsedPayload_FromPossibleRequestURIString = New_ParsedPayload_FromPossibleRequestURIString;

@ -0,0 +1,172 @@
// Copyright (c) 2014-2018, 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.
import { config } from "./monero_config";
import monero_utils from "./monero_cryptonote_utils_instance";
import { NetType } from "cryptonote_utils/nettype";
import { possibleOAAddress } from "./sending_funds/internal_libs/open_alias_lite";
export enum URITypes {
addressAsFirstPathComponent = 1,
addressAsAuthority = 2,
}
// we can stricten this typing using
// a discriminate union later
// since the TURITypes determines the nullity of the value
type FundRequestPayload = {
address: string;
payment_id?: string | null;
amount?: string | null;
amountCcySymbol?: string | null;
description?: string | null;
message?: string | null;
uriType: URITypes;
};
export function encodeFundRequest(args: FundRequestPayload) {
const address = args.address;
if (!address) {
throw "missing address";
}
let mutable_uri = config.coinUriPrefix;
const uriType = args.uriType;
if (uriType === URITypes.addressAsAuthority) {
mutable_uri += "//"; // use for inserting a // so data detectors pick it up…
} else if (uriType === URITypes.addressAsFirstPathComponent) {
// nothing to do
} else {
throw "Illegal args.uriType";
}
mutable_uri += address;
let queryParamStart = true;
type ParamName =
| "tx_amount"
| "tx_amount_ccy"
| "tx_description"
| "tx_payment_id"
| "tx_message";
function addParam(name: ParamName, value?: string | null) {
if (!value) {
return;
}
if (queryParamStart) {
queryParamStart = false;
}
mutable_uri += queryParamStart ? "?" : "&";
mutable_uri += name + "=" + encodeURIComponent(value);
}
addParam("tx_amount", args.amount);
const shouldAddCcySym =
(args.amountCcySymbol || "").toLowerCase() !==
config.coinSymbol.toLowerCase();
if (shouldAddCcySym) {
addParam("tx_amount_ccy", args.amountCcySymbol);
}
addParam("tx_description", args.description);
addParam("tx_payment_id", args.payment_id);
addParam("tx_message", args.message);
return mutable_uri;
}
type DecodeFundRequestPayload = Pick<
FundRequestPayload,
Exclude<keyof FundRequestPayload, "uriType">
>;
export function decodeFundRequest(
str: string,
nettype: NetType,
): DecodeFundRequestPayload {
// detect no-scheme moneroAddr and possible OA addr - if has no monero: prefix
if (!str.startsWith(config.coinUriPrefix)) {
if (str.includes("?")) {
// fairly sure this is correct.. (just an extra failsafe/filter)
throw "Unrecognized URI format";
}
if (possibleOAAddress(str)) {
return {
address: str,
};
}
try {
monero_utils.decode_address(str, nettype);
} catch (e) {
throw "No Monero request info";
}
// then it looks like a monero address
return {
address: str,
};
}
const url = new window.URL(str);
const protocol = url.protocol;
if (protocol !== config.coinUriPrefix) {
throw "Request URI has non-Monero protocol";
}
// it seems that if the URL has // in it, pathname will be empty, but host will contain the address instead
let target_address = url.pathname || url.host || url.hostname;
if (target_address.startsWith("//")) {
target_address = target_address.slice("//".length); // strip prefixing "//" in case URL had protocol:// instead of protocol:
}
const searchParams = url.searchParams;
const payload: DecodeFundRequestPayload = {
address: target_address,
};
const keyPrefixToTrim = "tx_";
(searchParams as any).forEach((value: string, key: string) => {
const index = key.startsWith(keyPrefixToTrim)
? key.slice(keyPrefixToTrim.length, key.length)
: key;
payload[index as keyof DecodeFundRequestPayload] = value;
});
return payload;
}
Loading…
Cancel
Save