diff --git a/assets/css/devportal.css b/assets/css/devportal.css index b19394dc20..1cf2acee8d 100644 --- a/assets/css/devportal.css +++ b/assets/css/devportal.css @@ -95,7 +95,14 @@ .no-1st-head h4:first-child, .no-1st-head h5:first-child, .no-1st-head h6:first-child { - display: none; + visibility: hidden; + margin: 0; + padding: 0; + line-height: 0; +} +.no-1st-head h1:first-child:before { + margin-top: -167px; + height: 167px; } .content p { line-height: 1.8; @@ -246,6 +253,7 @@ pre code { z-index: 5; border-left: 1px solid #cccccc; padding-left: 40px; + min-height: 700px; } .content { padding-bottom: 50px; @@ -522,6 +530,7 @@ th { #sidenav_accordion .panel { padding: 0; border-radius: 0; + border-bottom: 1px solid #cccccc; } #sidenav_accordion .panel-heading h5 { @@ -670,7 +679,7 @@ th { } /* Responsive design for different viewscreens -------------------------------*/ -@media (min-width: 1200px) { +@media (min-width: 1201px) { #page-toc-wrapper { float: right; margin-left: 15px; diff --git a/assets/css/ripple-txt-validator.css b/assets/css/ripple-txt-validator.css new file mode 100644 index 0000000000..f598d95e66 --- /dev/null +++ b/assets/css/ripple-txt-validator.css @@ -0,0 +1,16 @@ +input#domain { + padding: 10px 20px; + width: 255px; +} + +.result-title { + display: none; +} + +span.red { + color: red; +} + +span.green { + color: green; +} diff --git a/assets/css/ripple.css b/assets/css/ripple.css index 1eb6bb1a77..84242ab3a8 100755 --- a/assets/css/ripple.css +++ b/assets/css/ripple.css @@ -4556,7 +4556,7 @@ a.list-group-item-danger.active:focus { background-color: #ffffff; border: 1px solid transparent; border-radius: 4px; - border-bottom: 1px solid #cccccc !important; + border-bottom: 1px solid #cccccc; } .panel-body { padding: 15px; diff --git a/assets/css/rpc-tool.css b/assets/css/rpc-tool.css new file mode 100644 index 0000000000..ded3348e58 --- /dev/null +++ b/assets/css/rpc-tool.css @@ -0,0 +1,119 @@ +.input-xxlarge { + width: 100%; + padding: 5px; +} + +.progress .bar { + width:0%; + height:100%; + color:#ffffff; + float:left; + font-size:12px; + text-align:center + ;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25); + background-color:#0e90d2; + background-image:-moz-linear-gradient(top, #149bdf, #0480be); + background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); + background-image:-webkit-linear-gradient(top, #149bdf, #0480be); + background-image:-o-linear-gradient(top, #149bdf, #0480be); + background-image:linear-gradient(to bottom, #149bdf, #0480be); + background-repeat:repeat-x; + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); + -webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-box-sizing:border-box; + -moz-box-sizing:border-box;box-sizing:border-box; + -webkit-transition:width 0.6s ease; + -moz-transition:width 0.6s ease; + -o-transition:width 0.6s ease; + transition:width 0.6s ease; +} + +#result { + display: none; +} + +#log { + font-weight: 700; +} + +.json .name { + color: #A513AC; +} + +.json ul { + margin: 0; + display: none; +} + +.json li { + padding: 0; + list-style-type: none; +} + +.json .type-string .val { + color: #CC2A41; +} + +.json .type-number .val { + color: #2973BA; +} + +.json a.toggle:hover { + text-decoration: none; +} + +.json > a.toggle { + display: none; +} + +.json a.toggle:after { + content: " +\0000a0"; + cursor: pointer; +} + +.json > ul, +.json .expanded > ul { + display: block; +} + +.json .ellipsis { + color: #ccc; +} + +.json > .ellipsis, +.json .expanded > .ellipsis { + display: none; +} + +.json .expanded > a.toggle:after { + content: " \2212\0000a0"; +} + +.json .indentafter { + display: none; +} + +.json .expanded > .indentafter { + display: inline; +} + +.tools { + background-color: #f5f5f5; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + font-size: 0.8em; + margin: 0 0 10px; +} + +.tools>li>a { + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + padding: 6px 9px; +} diff --git a/assets/css/test-net.css b/assets/css/test-net.css new file mode 100644 index 0000000000..dd3ad2ee21 --- /dev/null +++ b/assets/css/test-net.css @@ -0,0 +1,93 @@ +.cta_readmore { + background-color: #27a2db; + color: white; + border-radius: 5px; + padding: 10px 50px; + border: none; + outline: 0; +} +.cta_readmore:hover, +.cta_readmore:active, +.cta_readmore:focus { + background-color: #43bded; + color: white; + outline: 0; + border: none; +} + +#your-credentials { + display: none; + margin: 15px 0 30px; +} + +#loader { + display: none; +} + +#loader img { + margin: 0 10px 0 20px; + width: 25px; + height: auto; +} + +#test-net-servers { + font-size: 15px; + border-radius: 5px; + border: 1px solid #27a2db; + width: 350px; + float: right; + margin-left: 15px; +} + +#test-net-servers pre { + overflow-x: auto; +} + +.page-test-net .container { + margin-left: 15px; + margin-right: 15px; + width: auto; +} +@media (min-width: 1600px) { + .page-test-net .container { + margin-left: auto; + margin-right: auto; + width: 1500px; + } +} + +@media (max-width: 992px) { + #test-net-servers { + position: static; + float: none; + max-width: none; + width: auto; + margin: 0 0 30px 0; + } +} + +h2 { + font-size: 36px; + color: #066b98; + line-height: 1.2em; + margin-top: 0; +} + +#test-net-servers h5 { + letter-spacing: .04em; + font-family: 'open_sansbold', sans-serif; + text-transform: uppercase; + color: #344e5a; + clear: both; + margin-top: 20px !important; +} + +#test-net-servers .panel-heading { + margin-top: 0; + padding: 0; + font-size: 21px; + font-family: "open_sanslight", sans-serif; + color: #27a2db; + line-height: 1.2em; + margin-bottom: 20px; +} diff --git a/assets/js/ripple-txt-validator.js b/assets/js/ripple-txt-validator.js new file mode 100644 index 0000000000..088ae8da55 --- /dev/null +++ b/assets/js/ripple-txt-validator.js @@ -0,0 +1,117 @@ +function VerificationError(message, tips) { + this.name = "VerificationError"; + this.message = message || ""; + this.tips = tips || ""; +} +VerificationError.prototype = Error.prototype; + +function makeLogEntry(text) { + var log = $('
  • ').text(text).appendTo('#log'); + log.resolve = function(text) { + return $('').html(text).appendTo(log); + }; + return log; +} + +$('#domain-entry').submit(function(e) { + e.preventDefault(); + + var domain = $('#domain').val(), + txtdata; + + $('.result-title').show(); + $('#result').show(); + $('#log').empty(); + + async.waterfall([ + function(callback) { + var urls = [ + //'http://www.'+domain+'/ripple.txt', + 'https://www.' + domain + '/ripple.txt', + //'http://'+domain+'/ripple.txt', + 'https://' + domain + '/ripple.txt', + 'https://ripple.' + domain + '/ripple.txt' + ].reverse(); + + function next(xhr, status) { + if (this instanceof $) { + var err; + switch (status) { + case 'timeout': + err = 'TIMEOUT'; + break; + case 'abort': + err = 'ABORTED'; + break; + case 'error': + err = 'ERROR'; + break; + default: + err = 'UNKNOWN'; + } + $('').text(err).addClass('red').appendTo(this); + } + if (!urls.length) { + var tips = 'Check if the file is actually hosted at one of the URLs above and make sure your server provides the required CORS header.'; + callback(new VerificationError('No ripple.txt found!', tips)); + return; + } + var url = urls.pop(); + var log = makeLogEntry('Checking ' + url + '...'); + $.ajax({ + url: url, + dataType: 'text', + success: function(data) { + $('').text('FOUND').addClass('green').appendTo(log); + txtdata = data; + callback(); + }, + error: $.proxy(next, log) + }); + } + next(); + }, + function() { + txtdata = txtdata.replace('\r\n', '\n'); + txtdata = txtdata.replace('\r', '\n'); + txtdata = txtdata.split('\n'); + + var currentSection = "", + sections = {}; + for (var i = 0, l = txtdata.length; i < l; i++) { + var line = txtdata[i].replace(/^\s+|\s+$/g, ''); + if (!line.length || line[0] === '#') { + continue; + } else if (line[0] === '[' && line[line.length - 1] === ']') { + currentSection = line.slice(1, line.length - 1); + sections[currentSection] = []; + } else { + line = line.replace(/^\s+|\s+$/g, ''); + if (sections[currentSection]) { + sections[currentSection].push(line); + } + } + } + + var log; + + log = makeLogEntry('Domain should match [domain]...'); + if (sections.domain && sections.domain.length && sections.domain[0] === domain) { + log.resolve('VALID').addClass('green'); + } else if (sections.domain && sections.domain.length) { + log.resolve('MISMATCH').addClass('red'); + } else { + log.resolve('MISSING').addClass('red'); + } + } + ], function(err, result) { + if (err instanceof VerificationError) { + var log = makeLogEntry(""); + log.resolve(err.message).addClass('red'); + $('
    ').appendTo(log); + $('

    ').html(err.tips).appendTo(log); + } else if (err) { + makeLogEntry(err).addClass('red'); + } + }); +}); diff --git a/assets/js/rpc-tool.js b/assets/js/rpc-tool.js new file mode 100644 index 0000000000..d7f939a91e --- /dev/null +++ b/assets/js/rpc-tool.js @@ -0,0 +1,369 @@ +jQuery(function ($) { + var reTxId = /^[0-9A-Fa-f]{64}$/, + reLedgerSeq = /^[0-9]+$/; + + var txOffset = 0, + txCount = 0, + currentTarget = null; + + var remote = ripple.Remote.from_config({ + "trace" : true, + "websocket_ip" : "s2.ripple.com", + "websocket_port" : 443, + "websocket_ssl" : true + }); + remote.connect(); + + remote.once('connected', function () { + var target = location.hash.slice(1); + if (ripple.UInt160.from_json(target).is_valid() || + reTxId.exec(target) || + reLedgerSeq.exec(target)) { + $('#target').val(target); + fetchTarget(target); + } + }); + + $('#account-entry').submit(function (e) { + e.preventDefault(); + + var target = $('#target').val(); + + fetchTarget(target); + }); + + function fetchTarget(target) + { + if (!remote.state === "online") return; + + // Reset + $("#links").show(); + $("#result").show(); + $("#result > .group").hide(); + $("#error").hide(); + $("#progress").show(); + $(".json").html(""); + $("#datalink").parent().removeClass("disabled"); + $(".account-tx-more").parent().hide(); + $(".account-tx-back").parent().hide(); + txOffset = 0; + + currentTarget = target; + + var locationWithoutHash = location.protocol+'//'+location.hostname+(location.port?":"+location.port:"")+location.pathname+(location.search?location.search:""); + $("#permalink").attr("href", locationWithoutHash + "#" + target); + $("#graphlink").attr("href", "https://www.ripplecharts.com/#/graph/" + target); + + if (ripple.UInt160.from_json(target).is_valid()) { + // Account + var account = target; + + $("#result > .group-account").show(); + + $("#progress .bar").css("width", "10%"); + $("#datalink").attr("href", null).parent().addClass("disabled"); + + async.waterfall([ + function (callback) { + remote.request_account_info({account:account}) + .on('success', function (result) { + $("#progress .bar").css("width", "20%"); + console.log('account_info', result); + format(result, $("#account_info")); + callback(); + }) + .on('error', callback) + .request(); + }, + function (callback) { + remote.request_account_lines({account:account}) + .on('success', function (result) { + $("#progress .bar").css("width", "40%"); + console.log('account_lines', result); + format(result, $("#account_lines")); + callback(); + }) + .on('error', callback) + .request(); + }, + function (callback) { + requestTx(account, function (err) { + if (err) return callback(err); + $("#progress .bar").css("width", "60%"); + callback(); + }); + }, + function (callback) { + remote.request_account_offers({account:account}) + .on('success', function (result) { + $("#progress .bar").css("width", "80%"); + console.log('account_offers', result); + format(result, $("#account_offers")); + callback(); + }) + .on('error', callback) + .request(); + } + ], function (err) { + if (err) handleError(err); + $("#progress .bar").css("width", "100%"); + $("#progress").fadeOut(); + }); + } else if (reLedgerSeq.exec(target)) { + $("#result > .group-ledger").show(); + + // Ledger + $("#progress .bar").css("width", "10%"); + remote.request_ledger(undefined, { transactions: true, expand: true }) + .ledger_index(+target) + .on('success', function (result) { + $("#progress .bar").css("width", "100%"); + $("#progress").fadeOut(); + console.log('ledger', result.ledger); + format(result.ledger, $("#ledger_info")); + }) + .on('error', function (err) { + console.log(err); + handleError(err); + $("#progress .bar").css("width", "100%"); + $("#progress").fadeOut(); + }) + .request(); + } else if (reTxId.exec(target)) { + $("#result > .group-tx").show(); + + $("#datalink").attr("href", "https://ripple.com/client/#/tx/?id=" + target); + + // Transaction + $("#progress .bar").css("width", "10%"); + remote.requestTransaction({"hash": target, "binary": false}) + .on('success', function (result) { + $("#progress .bar").css("width", "100%"); + $("#progress").fadeOut(); + console.log('tx', result); + format(result, $("#tx_info")); + }) + .on('error', function (err) { + handleError(err); + $("#progress .bar").css("width", "100%"); + $("#progress").fadeOut(); + }) + .request(); + } else { + // Unknown/Invalid + $("#links").hide(); + $("#progress").hide(); + handleError("Input is not a valid address or transaction hash"); + } + } + + $('.tx-expand').click(function () { + $("#tx_info .expanded").removeClass("expanded"); + $("#tx_info").find("ul > li").addClass("expanded"); + }); + + $('.tx-collapse').click(function () { + $("#tx_info .expanded").removeClass("expanded"); + }); + + $('.account-lines-expand').click(function () { + $("#account_lines .expanded").removeClass("expanded"); + $("#account_lines").find("ul > li").addClass("expanded"); + }); + + $('.account-lines-collapse').click(function () { + $("#account_lines .expanded").removeClass("expanded"); + }); + + $('.account-tx-expand-tx').click(function () { + $("#account_tx .expanded").removeClass("expanded"); + $("#account_tx").find("> ul > li").addClass("expanded").find("> ul > li").addClass("expanded").find("> ul > li span.name:contains(tx)").parent().addClass("expanded"); + }); + + $('.account-tx-expand').click(function () { + $("#account_tx .expanded").removeClass("expanded"); + $("#account_tx").find("ul > li").addClass("expanded"); + }); + + $('.account-tx-collapse').click(function () { + $("#account_tx .expanded").removeClass("expanded"); + }); + + $('.account-tx-more').click(function () { + $(".account-tx-back").parent().show(); + txOffset += 20; + $("#account_tx").text("... loading ..."); + requestTx(currentTarget, function (err) {}); + updateTxOffsetNav(); + }); + + $('.account-tx-back').click(function () { + txOffset -= 20; + $("#account_tx").text("... loading ..."); + requestTx(currentTarget, function (err) {}); + updateTxOffsetNav(); + }); + + $('.account-offers-expand').click(function () { + $("#account_offers .expanded").removeClass("expanded"); + $("#account_offers").find("ul > li").addClass("expanded"); + }); + + $('.account-offers-collapse').click(function () { + $("#account_offers .expanded").removeClass("expanded"); + }); + + $('.ledger-expand-tx').click(function () { + $("#ledger_info .expanded").removeClass("expanded"); + $("#ledger_info").find("> ul > li").addClass("expanded").find("> ul > li").addClass("expanded").find("> ul > li span.name:contains(tx)").parent().addClass("expanded"); + }); + + $('.ledger-expand').click(function () { + $("#ledger_info .expanded").removeClass("expanded"); + $("#ledger_info").find("ul > li").addClass("expanded"); + }); + + $('.ledger-collapse').click(function () { + $("#ledger_info .expanded").removeClass("expanded"); + }); + + $('pre.json').delegate(".toggle", "click", function (evt) { + console.log(this); + $(this).parent().toggleClass("expanded"); + }); + + function handleError(err) { + console.error(err); + if ("string" === typeof err) { + $("#error").show().text(err); + } else if ("object" === typeof err) { + if (err.error === "remoteError" && + "object" === typeof err.remote) + { + err = err.remote; + } + + if (err.error_message) { + $("#error").show().text(err.error_message); + } else if (err.error) { + $("#error").show().text(err.error); + } else { + $("#error").show().text(err.toString()); + } + } + } + + function requestTx(account, callback) { + remote.request_account_tx({ + 'account': account, + 'ledger_index_min': -1, + 'descending': true, + 'limit': 20, + 'offset' : txOffset, + 'count': true, + 'binary': false + }) + .on('success', function (result) { + txCount = result.count; + console.log('account_tx', result); + format(result, $("#account_tx").empty()); + callback(); + updateTxOffsetNav(); + }) + .on('error', callback) + .request(); + } + + function updateTxOffsetNav() + { + $(".account-tx-back").parent().hide(); + $(".account-tx-more").parent().hide(); + + if (txOffset > 0) + $(".account-tx-back").parent().show(); + + if (txCount > (txOffset + 20)) + $(".account-tx-more").parent().show(); + } + + String.prototype.repeat = function(times) { + return (new Array(times + 1)).join(this); + }; + + function format(v, ct, depth) { + depth = depth || 0; + + switch (typeof v) { + case "object": + var el, sub = null, count; + if (Array.isArray(v)) { + ct.append("["); + count = v.length; + for (var i = 0; i < count; i++) { + if (!sub) { + $('').appendTo(ct); + $('') + .text(getEllipText(count)).appendTo(ct); + el = $(""); + } else sub.append(","); + sub = $("
  • ").addClass("type-" + typeof v[i]); + sub.append("\u00A0".repeat(2 + depth*2)); + format(v[i], sub, depth + 1); + sub.appendTo(el); + } + if (el) { + el.appendTo(ct); + $('').text("\u00A0".repeat(depth*2)).appendTo(ct); + } + ct.append("]"); + } else { + ct.append("{"); + count = Object.keys(v).length; + for (var i in v) { + if (!sub) { + $('').appendTo(ct); + $('') + .text(getEllipText(Object.keys(v))).appendTo(ct); + el = $(""); + } else sub.append(","); + sub = $("
  • ").addClass("type-" + typeof v[i]); + sub.append("\u00A0".repeat(2 + depth*2)); + $("").addClass('name').text(i).appendTo(sub); + $("").addClass('sep').text(" : ").appendTo(sub); + format(v[i], sub, depth + 1); + sub.appendTo(el); + } + if (el) { + el.appendTo(ct); + $('').text("\u00A0".repeat(depth*2)).appendTo(ct); + } + ct.append("}"); + } + break; + case "string": + $("").addClass('val').text('"'+v+'"').appendTo(ct); + break; + case "number": + $("").addClass('val').text(""+v).appendTo(ct); + break; + case "boolean": + $("").addClass('val').text(v ? "true" : "false").appendTo(ct); + break; + } + } + function getEllipText(count) { + var label = "..."; + if (Array.isArray(count)) { + label = ""; + while (label.length < 15) { + if (!count.length) break; + if (label.length) label += ", "; + label += count.shift(); + } + if (count.length) label += ", ..."; + } else if ("number" === typeof count) { + label = "" + count + " items"; + } + return "\u00A0/* "+label+" */\u00A0"; + } +}); diff --git a/assets/js/test-net.js b/assets/js/test-net.js new file mode 100644 index 0000000000..e05a1e70ba --- /dev/null +++ b/assets/js/test-net.js @@ -0,0 +1,39 @@ +function rippleTestNetCredentials() { + + var credentials = $('#your-credentials'); + var address = $('#address'); + var secret = $('#secret'); + var balance = $('#balance'); + var loader = $('#loader'); + + //reset the fields initially and for re-generation + credentials.hide(); + address.html(''); + secret.html(''); + balance.html(''); + loader.css('display', 'inline'); + + + //call the alt-net and get key generations + $.ajax({ + url: "https://faucet.altnet.rippletest.net/accounts", + type: 'POST', + dataType: 'json', + success: function(data) { + //hide the loader and show results + loader.hide(); + credentials.hide().html('

    Your Credentials

    ').fadeIn('fast'); + address.hide().html('

    Address

    ' + data.account.address).fadeIn('fast'); + secret.hide().html('

    Secret

    ' + data.account.secret).fadeIn('fast'); + balance.hide().html('

    Balance

    ' + Number(data.balance).toLocaleString('en') + ' XRP').fadeIn('fast'); + }, + error: function() { + loader.hide(); + alert("There was an error with the Ripple Test Net, please try again."); + } + }); +} + +$(document).ready(function() { + $('.cta_readmore').click(rippleTestNetCredentials); +}); diff --git a/assets/vendor/async.min.js b/assets/vendor/async.min.js new file mode 100644 index 0000000000..6ba3145708 --- /dev/null +++ b/assets/vendor/async.min.js @@ -0,0 +1 @@ +/*global setTimeout: false, console: false */(function(){var a={},b=this,c=b.async;typeof module!="undefined"&&module.exports?module.exports=a:b.async=a,a.noConflict=function(){return b.async=c,a};var d=function(a,b){if(a.forEach)return a.forEach(b);for(var c=0;cd?1:0};d(null,e(b.sort(c),function(a){return a.value}))})},a.auto=function(a,b){b=b||function(){};var c=g(a);if(!c.length)return b(null);var e={},h=[],i=function(a){h.unshift(a)},j=function(a){for(var b=0;b - +