mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-21 04:05:49 +00:00
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:
@@ -1,10 +1,31 @@
|
|||||||
const set_up_tx_sender = async function() {
|
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
|
// Connection / Setup
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FAUCET_URL = "https://faucet.altnet.rippletest.net/accounts"
|
const FAUCET_URL = "https://faucet.altnet.rippletest.net/accounts"
|
||||||
TESTNET_URL = "wss://s.altnet.rippletest.net:51233"
|
const TESTNET_URL = "wss://s.altnet.rippletest.net:51233"
|
||||||
|
|
||||||
let connection_ready = false
|
let connection_ready = false
|
||||||
|
|
||||||
@@ -12,6 +33,7 @@ const set_up_tx_sender = async function() {
|
|||||||
let sending_secret
|
let sending_secret
|
||||||
let xrp_balance
|
let xrp_balance
|
||||||
|
|
||||||
|
|
||||||
console.debug("Getting a sending address from the faucet...")
|
console.debug("Getting a sending address from the faucet...")
|
||||||
|
|
||||||
faucet_response = function(data) {
|
faucet_response = function(data) {
|
||||||
@@ -25,20 +47,15 @@ const set_up_tx_sender = async function() {
|
|||||||
$(".sending-address-item").text(sending_address)
|
$(".sending-address-item").text(sending_address)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEMP: reuse same address for testing
|
$.ajax({
|
||||||
faucet_response({account:{address:"r6f2viHtMjNSfERbZmXXkJnMmkBAN6d9X", secret:"spyTc4y4GAQwBfQHCxiJ1Xd2mmnM2"},balance:10000})
|
url: FAUCET_URL,
|
||||||
|
type: 'POST',
|
||||||
// POST-TEMP: Version that actually uses the faucet on every run:
|
dataType: 'json',
|
||||||
// $.ajax({
|
success: faucet_response,
|
||||||
// url: FAUCET_URL,
|
error: function() {
|
||||||
// type: 'POST',
|
errorNotif("There was an error with the XRP Ledger Test Net Faucet. Reload this page to try again.")
|
||||||
// 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.");
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
|
|
||||||
api = new ripple.RippleAPI({server: TESTNET_URL})
|
api = new ripple.RippleAPI({server: TESTNET_URL})
|
||||||
api.on('connected', () => {
|
api.on('connected', () => {
|
||||||
@@ -97,7 +114,9 @@ const set_up_tx_sender = async function() {
|
|||||||
console.debug("Prepared:", prepared)
|
console.debug("Prepared:", prepared)
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
if (!silent) { alert("Error preparing tx: "+error) }
|
if (!silent) {
|
||||||
|
errorNotif("Error preparing tx: "+error)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +133,9 @@ const set_up_tx_sender = async function() {
|
|||||||
await api.submit(sign_response.signedTransaction)
|
await api.submit(sign_response.signedTransaction)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
if (!silent) { alert("Error signing & submitting tx: "+error) }
|
if (!silent) {
|
||||||
|
errorNotif("Error signing & submitting "+tx_object.TransactionType+" tx: "+error)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,18 +143,24 @@ const set_up_tx_sender = async function() {
|
|||||||
try {
|
try {
|
||||||
const data = await verify_transaction(sign_response.id, options)
|
const data = await verify_transaction(sign_response.id, options)
|
||||||
const final_result = data.outcome.result
|
const final_result = data.outcome.result
|
||||||
// TODO: more "notification-like" system
|
// Future feature: output should link to a TestNet tx lookup/explainer
|
||||||
// TODO: output should link to a tx lookup/explainer
|
|
||||||
if (final_result === "tesSUCCESS") {
|
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 {
|
} 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()
|
update_xrp_balance()
|
||||||
return data
|
return data
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
console.log(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,
|
Destination: destination_address,
|
||||||
Amount: "1000000000000000", // 1 billion XRP
|
Amount: "1000000000000000", // 1 billion XRP
|
||||||
SendMax: {
|
SendMax: {
|
||||||
value: String(Math.random()*.01), // random very small amount
|
value: (Math.random()*.01).toPrecision(15), // random very small amount
|
||||||
currency: pp_sending_currency,
|
currency: pp_sending_currency,
|
||||||
issuer: pp_issuer_address
|
issuer: pp_issuer_address
|
||||||
},
|
},
|
||||||
@@ -306,7 +333,7 @@ const set_up_tx_sender = async function() {
|
|||||||
|
|
||||||
const duration_seconds = parseInt(duration_seconds_txt, 10)
|
const duration_seconds = parseInt(duration_seconds_txt, 10)
|
||||||
if (duration_seconds === NaN || duration_seconds < 1) {
|
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
|
return
|
||||||
}
|
}
|
||||||
const finish_after = api.iso8601ToRippleTime(Date()) + duration_seconds
|
const finish_after = api.iso8601ToRippleTime(Date()) + duration_seconds
|
||||||
|
|||||||
101
assets/vendor/bootstrap-growl.jquery.js
vendored
Normal file
101
assets/vendor/bootstrap-growl.jquery.js
vendored
Normal 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\">×</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);
|
||||||
@@ -150,5 +150,6 @@
|
|||||||
{% block endbody %}
|
{% block endbody %}
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
|
<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="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 %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user