Tx sender improvements

- Stick to proper precision when forming partial payments
- Use growl-like notifs to report tx success/failure
This commit is contained in:
mDuo13
2019-04-23 18:50:19 -07:00
parent 032e2d28b4
commit 269d889fcf
3 changed files with 155 additions and 26 deletions

View File

@@ -1,10 +1,31 @@
const set_up_tx_sender = async function() {
//////////////////////////////////////////////////////////////////////////////
// Notification helpers
//////////////////////////////////////////////////////////////////////////////
function successNotif(msg) {
$.bootstrapGrowl(msg, {
delay: 7000,
offset: {from: 'bottom', amount: 68},
type: 'success',
width: 'auto'
})
}
function errorNotif(msg) {
$.bootstrapGrowl(msg, {
delay: 7000,
offset: {from: 'bottom', amount: 68},
type: 'danger',
width: 'auto'
})
}
//////////////////////////////////////////////////////////////////////////////
// Connection / Setup
//////////////////////////////////////////////////////////////////////////////
FAUCET_URL = "https://faucet.altnet.rippletest.net/accounts"
TESTNET_URL = "wss://s.altnet.rippletest.net:51233"
const FAUCET_URL = "https://faucet.altnet.rippletest.net/accounts"
const TESTNET_URL = "wss://s.altnet.rippletest.net:51233"
let connection_ready = false
@@ -12,6 +33,7 @@ const set_up_tx_sender = async function() {
let sending_secret
let xrp_balance
console.debug("Getting a sending address from the faucet...")
faucet_response = function(data) {
@@ -25,20 +47,15 @@ const set_up_tx_sender = async function() {
$(".sending-address-item").text(sending_address)
}
// TEMP: reuse same address for testing
faucet_response({account:{address:"r6f2viHtMjNSfERbZmXXkJnMmkBAN6d9X", secret:"spyTc4y4GAQwBfQHCxiJ1Xd2mmnM2"},balance:10000})
// POST-TEMP: Version that actually uses the faucet on every run:
// $.ajax({
// url: FAUCET_URL,
// type: 'POST',
// dataType: 'json',
// success: faucet_response,
// error: function() {
// alert("There was an error with the XRP Ledger Test Net Faucet. Reload this page to try again.");
// }
// })
//
$.ajax({
url: FAUCET_URL,
type: 'POST',
dataType: 'json',
success: faucet_response,
error: function() {
errorNotif("There was an error with the XRP Ledger Test Net Faucet. Reload this page to try again.")
}
})
api = new ripple.RippleAPI({server: TESTNET_URL})
api.on('connected', () => {
@@ -97,7 +114,9 @@ const set_up_tx_sender = async function() {
console.debug("Prepared:", prepared)
} catch(error) {
console.log(error)
if (!silent) { alert("Error preparing tx: "+error) }
if (!silent) {
errorNotif("Error preparing tx: "+error)
}
return
}
@@ -114,7 +133,9 @@ const set_up_tx_sender = async function() {
await api.submit(sign_response.signedTransaction)
} catch (error) {
console.log(error)
if (!silent) { alert("Error signing & submitting tx: "+error) }
if (!silent) {
errorNotif("Error signing & submitting "+tx_object.TransactionType+" tx: "+error)
}
return
}
@@ -122,18 +143,24 @@ const set_up_tx_sender = async function() {
try {
const data = await verify_transaction(sign_response.id, options)
const final_result = data.outcome.result
// TODO: more "notification-like" system
// TODO: output should link to a tx lookup/explainer
// Future feature: output should link to a TestNet tx lookup/explainer
if (final_result === "tesSUCCESS") {
if (!silent) { alert("Tx succeeded (hash:"+sign_response.id+")") }
if (!silent) {
successNotif(tx_object.TransactionType+" tx succeeded (hash: "+sign_response.id+")")
}
} else {
if (!silent) { alert("Tx failed w/ code "+final_result+" (hash: "+sign_response.id+")") }
if (!silent) {
errorNotif(tx_object.TransactionType+" tx failed w/ code "+final_result+
" (hash: "+sign_response.id+")")
}
}
update_xrp_balance()
return data
} catch(error) {
console.log(error)
if (!silent) { alert("Error submitting tx: "+error) }
if (!silent) {
errorNotif("Error submitting "+tx_object.TransactionType+" tx: "+error)
}
}
}
@@ -284,7 +311,7 @@ const set_up_tx_sender = async function() {
Destination: destination_address,
Amount: "1000000000000000", // 1 billion XRP
SendMax: {
value: String(Math.random()*.01), // random very small amount
value: (Math.random()*.01).toPrecision(15), // random very small amount
currency: pp_sending_currency,
issuer: pp_issuer_address
},
@@ -306,7 +333,7 @@ const set_up_tx_sender = async function() {
const duration_seconds = parseInt(duration_seconds_txt, 10)
if (duration_seconds === NaN || duration_seconds < 1) {
alert("Error: Escrow duration must be a positive number of seconds")
errorNotif("Error: Escrow duration must be a positive number of seconds")
return
}
const finish_after = api.iso8601ToRippleTime(Date()) + duration_seconds

101
assets/vendor/bootstrap-growl.jquery.js vendored Normal file
View File

@@ -0,0 +1,101 @@
/*
The MIT License
Copyright (c) Nick Larson, http://github.com/ifightcrime
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
(function() {
var $;
$ = jQuery;
$.bootstrapGrowl = function(message, options) {
var $alert, css, offsetAmount;
options = $.extend({}, $.bootstrapGrowl.default_options, options);
$alert = $("<div>");
$alert.attr("class", "bootstrap-growl alert");
if (options.type) {
$alert.addClass("alert-" + options.type);
}
if (options.allow_dismiss) {
$alert.addClass("alert-dismissible");
$alert.append("<button class=\"close\" data-dismiss=\"alert\" type=\"button\"><span aria-hidden=\"true\">&#215;</span><span class=\"sr-only\">Close</span></button>");
}
$alert.append(message);
if (options.top_offset) {
options.offset = {
from: "top",
amount: options.top_offset
};
}
offsetAmount = options.offset.amount;
$(".bootstrap-growl").each(function() {
return offsetAmount = Math.max(offsetAmount, parseInt($(this).css(options.offset.from)) + $(this).outerHeight() + options.stackup_spacing);
});
css = {
"position": (options.ele === "body" ? "fixed" : "absolute"),
"margin": 0,
"z-index": "9999",
"display": "none"
};
css[options.offset.from] = offsetAmount + "px";
$alert.css(css);
if (options.width !== "auto") {
$alert.css("width", options.width + "px");
}
$(options.ele).append($alert);
switch (options.align) {
case "center":
$alert.css({
"left": "50%",
"margin-left": "-" + ($alert.outerWidth() / 2) + "px"
});
break;
case "left":
$alert.css("left", "20px");
break;
default:
$alert.css("right", "20px");
}
$alert.fadeIn();
if (options.delay > 0) {
$alert.delay(options.delay).fadeOut(function() {
return $(this).alert("close");
});
}
return $alert;
};
$.bootstrapGrowl.default_options = {
ele: "body",
type: "info",
offset: {
from: "top",
amount: 20
},
align: "right",
width: 250,
delay: 4000,
allow_dismiss: true,
stackup_spacing: 10
};
}).call(this);

View File

@@ -150,5 +150,6 @@
{% block endbody %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
<script type="application/javascript" src="assets/js/ripple-lib-1.1.2-min.js"></script>
<script type='text/javascript' src='assets/js/tx-sender.js'></script>
<script type="application/javascript" src="assets/vendor/bootstrap-growl.jquery.js"></script>
<script type='application/javascript' src='assets/js/tx-sender.js'></script>
{% endblock %}