mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-20 11:45:50 +00:00
Merge pull request #1644 from ripci504/master
0062 Account-Based TOML Lookup Bounty
This commit is contained in:
File diff suppressed because one or more lines are too long
178
assets/js/xrp-ledger-toml-checker-test.js
Normal file
178
assets/js/xrp-ledger-toml-checker-test.js
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
// This code takes in a wallet address, checks the domain field, then gets the TOML info to verify the domains ownership.
|
||||||
|
// This is runnable in NODE JS for easier testing, and works the same as the code in xrp-ledger-toml-checker.js
|
||||||
|
const WebSocket = require('ws');
|
||||||
|
const https = require('https');
|
||||||
|
const TOML = require('../vendor/iarna-toml-parse');
|
||||||
|
|
||||||
|
const TOML_PATH = "/.well-known/xrp-ledger.toml"
|
||||||
|
|
||||||
|
const ACCOUNT_FIELDS = [
|
||||||
|
"address",
|
||||||
|
"network",
|
||||||
|
"desc"
|
||||||
|
]
|
||||||
|
|
||||||
|
// Test wallet addresses
|
||||||
|
const WORKS = 'rSTAYKxF2K77ZLZ8GoAwTqPGaphAqMyXV'
|
||||||
|
const NOTOML = 'rsoLo2S1kiGeCcn6hCUXVrCpGMWLrRrLZz'
|
||||||
|
const NODOMAIN = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
|
||||||
|
|
||||||
|
let socket;
|
||||||
|
|
||||||
|
function makeLogEntry(text) {
|
||||||
|
log = console.log(text + '\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchFile(domain) {
|
||||||
|
const url = "https://" + domain + TOML_PATH
|
||||||
|
makeLogEntry('CHECKING DOMAIN: ' + url)
|
||||||
|
https.get(url, (resp) => {
|
||||||
|
let data = '';
|
||||||
|
resp.on('data', (chunk) => {
|
||||||
|
data += chunk;
|
||||||
|
});
|
||||||
|
resp.on('end', () => {
|
||||||
|
if (data != '') {
|
||||||
|
makeLogEntry('TOML FILE: Found');
|
||||||
|
parseXrplToml(data)
|
||||||
|
} else {
|
||||||
|
makeLogEntry('TOML FILE: Not found')
|
||||||
|
makeLogEntry('ACCOUNT CAN NOT BE VERIFIED: TOML file was not found.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).on("error", (err) => {
|
||||||
|
if (err.code == 'ENOTFOUND') {
|
||||||
|
makeLogEntry('ACCOUNT CAN NOT BE VERIFIED: Network error while fetching TOML file.')
|
||||||
|
}
|
||||||
|
return
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchWallet() {
|
||||||
|
makeLogEntry('\nCHECKING DOMAIN OF ACCOUNT...')
|
||||||
|
const url = "wss://xrplcluster.com"
|
||||||
|
if (typeof socket !== "undefined" && socket.readyState < 2) {
|
||||||
|
socket.close()
|
||||||
|
}
|
||||||
|
const data = {
|
||||||
|
"command": "account_info",
|
||||||
|
"account": wallet,
|
||||||
|
}
|
||||||
|
socket = new WebSocket(url)
|
||||||
|
socket.addEventListener('message', (event) => {
|
||||||
|
let data;
|
||||||
|
try {
|
||||||
|
data = JSON.parse(event.data)
|
||||||
|
if (data.status === 'success') {
|
||||||
|
if (data.result.account_data.Domain) {
|
||||||
|
try {
|
||||||
|
makeLogEntry('ACCOUNT ADDRESS: Valid')
|
||||||
|
decodeHex(data.result.account_data.Domain)
|
||||||
|
} catch {
|
||||||
|
makeLogEntry('error decoding domain field: ' + data.result.account_data.Domain)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
makeLogEntry('ACCOUNT ADDRESS: Valid')
|
||||||
|
makeLogEntry('DOMAIN DECODED: Domain field not found')
|
||||||
|
makeLogEntry('CHECKING DOMAIN: Error')
|
||||||
|
makeLogEntry('TOML FILE: Not found')
|
||||||
|
makeLogEntry('ACCOUNT CAN NOT BE VERIFIED: Account has no domain field.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
makeLogEntry('ACCOUNT ADDRESS: Invalid')
|
||||||
|
makeLogEntry('DOMAIN DECODED: Domain field not found')
|
||||||
|
makeLogEntry('CHECKING DOMAIN: Error')
|
||||||
|
makeLogEntry('TOML FILE: Not found')
|
||||||
|
makeLogEntry('ACCOUNT CAN NOT BE VERIFIED: Account address is not valid.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
makeLogEntry(e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
socket.addEventListener('open', () => {
|
||||||
|
socket.send(JSON.stringify(data))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function parseXrplToml(data) {
|
||||||
|
let parsed
|
||||||
|
makeLogEntry("Parsing TOML data...")
|
||||||
|
try {
|
||||||
|
parsed = TOML(data)
|
||||||
|
} catch (e) {
|
||||||
|
makeLogEntry('ACCOUNT CAN NOT BE VERIFIED: TOML file can not be read.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
async function listEntries(list, fields) {
|
||||||
|
makeLogEntry('\nADDRESSES:')
|
||||||
|
let found = false;
|
||||||
|
for (i = 0; i < list.length; i++) {
|
||||||
|
let entry = list[i]
|
||||||
|
for (j = 0; j < fields.length; j++) {
|
||||||
|
let fieldname = fields[j]
|
||||||
|
if (fieldname == 'address' && entry[fieldname] !== undefined) {
|
||||||
|
if (entry[fieldname] === wallet) {
|
||||||
|
makeLogEntry('MATCH: ' + entry[fieldname] + ' *')
|
||||||
|
found = true;
|
||||||
|
} else {
|
||||||
|
makeLogEntry('NO_MATCH: ' + entry[fieldname])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
makeLogEntry('ACCOUNT IS PRESENT: Account domain verified')
|
||||||
|
} else {
|
||||||
|
makeLogEntry('ACCOUNT IS NOT PRESENT: Account domain can not be verified')
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (parsed.ACCOUNTS) {
|
||||||
|
if (!Array.isArray(parsed.ACCOUNTS)) {
|
||||||
|
makeLogEntry("Wrong type- should be table-array")
|
||||||
|
process.exit()
|
||||||
|
} else {
|
||||||
|
listEntries(parsed.ACCOUNTS, ACCOUNT_FIELDS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function decodeHex(hex) {
|
||||||
|
let str = '';
|
||||||
|
for (let i = 0; i < hex.length; i += 2) {
|
||||||
|
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16))
|
||||||
|
}
|
||||||
|
makeLogEntry('DOMAIN DECODED: ' + str)
|
||||||
|
fetchFile(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'wallet' must be a global func.
|
||||||
|
let wallet;
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
makeLogEntry('\n\n--------EXAMPLE OF FAIL: WEBSITE TOML ERROR--------')
|
||||||
|
wallet = NOTOML
|
||||||
|
fetchWallet()
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
makeLogEntry('\n\n--------EXAMPLE OF FAIL: NO DOMAIN FIELD--------')
|
||||||
|
wallet = NODOMAIN
|
||||||
|
fetchWallet()
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
makeLogEntry('\n\n--------EXAMPLE OF SUCCESS--------')
|
||||||
|
wallet = WORKS
|
||||||
|
fetchWallet()
|
||||||
|
|
||||||
|
setTimeout(function(){process.exit()},5000)
|
||||||
|
}, 5000)
|
||||||
|
}, 5000)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
const TOML_PATH = "/.well-known/xrp-ledger.toml"
|
const TOML_PATH = "/.well-known/xrp-ledger.toml"
|
||||||
const TIPS = '<p>Check if the file is actually hosted at the URL above, check your server\'s HTTPS settings and certificate, and make sure your server provides the required <a href="xrp-ledger-toml.html#cors-setup">CORS header.</a></p>'
|
const TIPS = '<p>Check if the file is actually hosted at the URL above, check your server\'s HTTPS settings and certificate, and make sure your server provides the required <a href="xrp-ledger-toml.html#cors-setup">CORS header.</a></p>'
|
||||||
|
const TIPS_1 = '<p>Make sure you are entering a valid XRP Ledger address.</p>'
|
||||||
|
const TIPS_2 = '<p>Make sure the account has the Domain field set.</p>'
|
||||||
const CLASS_GOOD = "badge badge-success"
|
const CLASS_GOOD = "badge badge-success"
|
||||||
const CLASS_BAD = "badge badge-danger"
|
const CLASS_BAD = "badge badge-danger"
|
||||||
|
|
||||||
@@ -53,17 +55,28 @@ function makeLogEntry(text, raw) {
|
|||||||
return log
|
return log
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetch_file() {
|
function fetchFile(walletDomain) {
|
||||||
|
var url;
|
||||||
|
var log;
|
||||||
const domain = $('#domain').val()
|
const domain = $('#domain').val()
|
||||||
const url = "https://" + domain + TOML_PATH
|
if (walletDomain !== undefined) {
|
||||||
|
url = "https://" + walletDomain + TOML_PATH
|
||||||
|
log = makeLogEntryWallet('Checking ' + url + '...')
|
||||||
|
} else {
|
||||||
|
url = "https://" + domain + TOML_PATH
|
||||||
|
log = makeLogEntry('Checking ' + url + '...')
|
||||||
|
}
|
||||||
|
|
||||||
const log = makeLogEntry('Checking ' + url + '...')
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: url,
|
url: url,
|
||||||
dataType: 'text',
|
dataType: 'text',
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
log.resolve('FOUND').addClass(CLASS_GOOD)
|
log.resolve('FOUND').addClass(CLASS_GOOD)
|
||||||
parse_xrpl_toml(data, domain)
|
if (typeof walletDomain !== 'undefined'){
|
||||||
|
parseXRPLTomlWallet(data)
|
||||||
|
} else{
|
||||||
|
parseXRPLToml(data, domain)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
error: function(jqxhr, status, error) {
|
error: function(jqxhr, status, error) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@@ -84,19 +97,17 @@ function fetch_file() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function parse_xrpl_toml(data, domain) {
|
async function parseXRPLToml(data, domain) {
|
||||||
let parsed
|
let parsed
|
||||||
let log1 = makeLogEntry("Parsing TOML data...")
|
let logTOML = makeLogEntry("Parsing TOML data...")
|
||||||
try {
|
try {
|
||||||
parsed = TOML(data)
|
parsed = TOML(data)
|
||||||
log1.resolve("SUCCESS").addClass(CLASS_GOOD)
|
logTOML.resolve("SUCCESS").addClass(CLASS_GOOD)
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
log1.resolve(e).addClass(CLASS_BAD)
|
logTOML.resolve(e).addClass(CLASS_BAD)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(parsed)
|
|
||||||
|
|
||||||
if (parsed.hasOwnProperty("METADATA")) {
|
if (parsed.hasOwnProperty("METADATA")) {
|
||||||
const metadata_type = makeLogEntry("Metadata section: ")
|
const metadata_type = makeLogEntry("Metadata section: ")
|
||||||
if (Array.isArray(parsed.METADATA)) {
|
if (Array.isArray(parsed.METADATA)) {
|
||||||
@@ -115,7 +126,7 @@ async function parse_xrpl_toml(data, domain) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function list_entries(name, list, fields, validate) {
|
async function listEntries(name, list, fields, validate) {
|
||||||
let list_wrap = $("<p>"+name+"</p>")
|
let list_wrap = $("<p>"+name+"</p>")
|
||||||
let list_ol = $("<ol>").appendTo(list_wrap)
|
let list_ol = $("<ol>").appendTo(list_wrap)
|
||||||
for (i=0; i<list.length; i++) {
|
for (i=0; i<list.length; i++) {
|
||||||
@@ -144,11 +155,11 @@ async function parse_xrpl_toml(data, domain) {
|
|||||||
if (!Array.isArray(parsed.ACCOUNTS)) {
|
if (!Array.isArray(parsed.ACCOUNTS)) {
|
||||||
makeLogEntry("Accounts:").resolve("Wrong type - should be table-array").addClass(CLASS_BAD)
|
makeLogEntry("Accounts:").resolve("Wrong type - should be table-array").addClass(CLASS_BAD)
|
||||||
} else {
|
} else {
|
||||||
list_entries("Accounts:", parsed.ACCOUNTS, ACCOUNT_FIELDS, async function(acct) {
|
listEntries("Accounts:", parsed.ACCOUNTS, ACCOUNT_FIELDS, async function(acct) {
|
||||||
if (acct.address === undefined) {return undefined}
|
if (acct.address === undefined) {return undefined}
|
||||||
let net
|
let net
|
||||||
if (acct.network === undefined) { net = "main" } else { net = acct.network }
|
if (acct.network === undefined) { net = "main" } else { net = acct.network }
|
||||||
return await validate_address_domain_on_net(acct.address, domain, net)
|
return await validateAddressDomainOnNet(acct.address, domain, net)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,28 +167,28 @@ async function parse_xrpl_toml(data, domain) {
|
|||||||
if (!Array.isArray(parsed.VALIDATORS)) {
|
if (!Array.isArray(parsed.VALIDATORS)) {
|
||||||
makeLogEntry("Validators:").resolve("Wrong type - should be table-array").addClass(CLASS_BAD)
|
makeLogEntry("Validators:").resolve("Wrong type - should be table-array").addClass(CLASS_BAD)
|
||||||
} else {
|
} else {
|
||||||
list_entries("Validators:", parsed.VALIDATORS, VALIDATOR_FIELDS)
|
listEntries("Validators:", parsed.VALIDATORS, VALIDATOR_FIELDS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (parsed.PRINCIPALS) {
|
if (parsed.PRINCIPALS) {
|
||||||
if (!Array.isArray(parsed.PRINCIPALS)) {
|
if (!Array.isArray(parsed.PRINCIPALS)) {
|
||||||
makeLogEntry("Principals:").resolve("Wrong type - should be table-array").addClass(CLASS_BAD)
|
makeLogEntry("Principals:").resolve("Wrong type - should be table-array").addClass(CLASS_BAD)
|
||||||
} else {
|
} else {
|
||||||
list_entries("Principals:", parsed.PRINCIPALS, PRINCIPAL_FIELDS)
|
listEntries("Principals:", parsed.PRINCIPALS, PRINCIPAL_FIELDS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (parsed.SERVERS) {
|
if (parsed.SERVERS) {
|
||||||
if (!Array.isArray(parsed.SERVERS)) {
|
if (!Array.isArray(parsed.SERVERS)) {
|
||||||
makeLogEntry("Servers:").resolve("Wrong type - should be table-array").addClass(CLASS_BAD)
|
makeLogEntry("Servers:").resolve("Wrong type - should be table-array").addClass(CLASS_BAD)
|
||||||
} else {
|
} else {
|
||||||
list_entries("Servers:", parsed.SERVERS, SERVER_FIELDS)
|
listEntries("Servers:", parsed.SERVERS, SERVER_FIELDS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (parsed.CURRENCIES) {
|
if (parsed.CURRENCIES) {
|
||||||
if (!Array.isArray(parsed.CURRENCIES)) {
|
if (!Array.isArray(parsed.CURRENCIES)) {
|
||||||
makeLogEntry("Currencies:").resolve("Wrong type - should be table-array").addClass(CLASS_BAD)
|
makeLogEntry("Currencies:").resolve("Wrong type - should be table-array").addClass(CLASS_BAD)
|
||||||
} else {
|
} else {
|
||||||
list_entries("Currencies:", parsed.CURRENCIES, CURRENCY_FIELDS)
|
listEntries("Currencies:", parsed.CURRENCIES, CURRENCY_FIELDS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +196,7 @@ async function parse_xrpl_toml(data, domain) {
|
|||||||
// Decode a hexadecimal string into a regular string, assuming 8-bit characters.
|
// Decode a hexadecimal string into a regular string, assuming 8-bit characters.
|
||||||
// Not proper unicode decoding, but it'll work for domains which are supposed
|
// Not proper unicode decoding, but it'll work for domains which are supposed
|
||||||
// to be a subset of ASCII anyway.
|
// to be a subset of ASCII anyway.
|
||||||
function decode_hex(hex) {
|
function decodeHex(hex) {
|
||||||
let str = '';
|
let str = '';
|
||||||
for (let i = 0; i < hex.length; i += 2) {
|
for (let i = 0; i < hex.length; i += 2) {
|
||||||
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16))
|
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16))
|
||||||
@@ -193,7 +204,7 @@ function decode_hex(hex) {
|
|||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
async function validate_address_domain_on_net(address, domain, net) {
|
async function validateAddressDomainOnNet(address, domain, net) {
|
||||||
if (!domain) { return undefined } // Can't validate an empty domain value
|
if (!domain) { return undefined } // Can't validate an empty domain value
|
||||||
let api
|
let api
|
||||||
if (net === "main") {
|
if (net === "main") {
|
||||||
@@ -223,7 +234,7 @@ async function validate_address_domain_on_net(address, domain, net) {
|
|||||||
|
|
||||||
let domain_decoded
|
let domain_decoded
|
||||||
try {
|
try {
|
||||||
domain_decoded = decode_hex(ai.result.account_data.Domain)
|
domain_decoded = decodeHex(ai.result.account_data.Domain)
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.warn("error decoding domain value", ai.result.account_data.Domain, e)
|
console.warn("error decoding domain value", ai.result.account_data.Domain, e)
|
||||||
api.disconnect()
|
api.disconnect()
|
||||||
@@ -244,16 +255,162 @@ async function validate_address_domain_on_net(address, domain, net) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handle_submit(event) {
|
function handleSubmitDomain(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
$('.result-title').show()
|
$('.result-title').show()
|
||||||
$('#result').show()
|
$('#result').show()
|
||||||
$('#log').empty()
|
$('#log').empty()
|
||||||
|
|
||||||
fetch_file()
|
fetchFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(() => {
|
// ------------------------------------------ DOMAIN VERIFICATION VIA ACCOUNT BELOW ------------------------------------------
|
||||||
$('#domain-entry').submit(handle_submit)
|
let wallet;
|
||||||
|
let socket;
|
||||||
|
|
||||||
|
function makeLogEntryWallet(text, raw) {
|
||||||
|
let log
|
||||||
|
if (raw) {
|
||||||
|
log = $('<li></li>').appendTo('#verify-domain-log').append(text)
|
||||||
|
} else {
|
||||||
|
log = $('<li></li>').text(text+" ").appendTo('#verify-domain-log')
|
||||||
|
}
|
||||||
|
log.resolve = function(text) {
|
||||||
|
return $('<span></span>').html(text).appendTo(log)
|
||||||
|
}
|
||||||
|
return log
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchWallet() {
|
||||||
|
wallet = $('#verify-domain').val()
|
||||||
|
const checkingLog = makeLogEntryWallet('Checking domain of account')
|
||||||
|
const url = "wss://xrplcluster.com"
|
||||||
|
if (typeof socket !== "undefined" && socket.readyState < 2) {
|
||||||
|
socket.close()
|
||||||
|
}
|
||||||
|
const data = {
|
||||||
|
"command": "account_info",
|
||||||
|
"account": wallet,
|
||||||
|
}
|
||||||
|
socket = new WebSocket(url)
|
||||||
|
socket.addEventListener('message', (event) => {
|
||||||
|
let data;
|
||||||
|
try {
|
||||||
|
data = JSON.parse(event.data)
|
||||||
|
if (data.status === 'success') {
|
||||||
|
if (data.result.account_data.Domain) {
|
||||||
|
try {
|
||||||
|
checkingLog.resolve('SUCCESS').addClass(CLASS_GOOD)
|
||||||
|
decodeHexWallet(data.result.account_data.Domain)
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
checkingLog.resolve('ERROR').addClass(CLASS_BAD).after('<p>Error decoding domain field: ' + data.result.account_data.Domain + '</p>')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
checkingLog.resolve('ERROR').addClass(CLASS_BAD).after(TIPS_2)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
checkingLog.resolve('ERROR').addClass(CLASS_BAD).after(TIPS_1)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
socket.addEventListener('open', () => {
|
||||||
|
socket.send(JSON.stringify(data))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function parseXRPLTomlWallet(data) {
|
||||||
|
let parsed
|
||||||
|
let logTOML = makeLogEntryWallet("Parsing TOML data...")
|
||||||
|
try {
|
||||||
|
parsed = TOML(data)
|
||||||
|
logTOML.resolve("SUCCESS").addClass(CLASS_GOOD)
|
||||||
|
} catch(e) {
|
||||||
|
logTOML.resolve(e).addClass(CLASS_BAD)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsed.hasOwnProperty("METADATA")) {
|
||||||
|
const metadata_type = makeLogEntryWallet("Metadata section: ")
|
||||||
|
if (Array.isArray(parsed.METADATA)) {
|
||||||
|
metadata_type.resolve("Wrong type - should be table").addClass(CLASS_BAD)
|
||||||
|
} else {
|
||||||
|
metadata_type.resolve("Found").addClass(CLASS_GOOD)
|
||||||
|
|
||||||
|
if (parsed.METADATA.modified) {
|
||||||
|
const mod_log = makeLogEntryWallet("Modified date: ")
|
||||||
|
try {
|
||||||
|
mod_log.resolve(parsed.METADATA.modified.toISOString()).addClass(CLASS_GOOD)
|
||||||
|
} catch(e) {
|
||||||
|
mod_log.resolve("INVALID").addClass(CLASS_BAD)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function listEntriesWallet(name, list, fields) {
|
||||||
|
let found = false;
|
||||||
|
let list_wrap = $("<p>"+name+"</p>")
|
||||||
|
let list_ol = $("<ol>").appendTo(list_wrap)
|
||||||
|
for (i=0; i<list.length; i++) {
|
||||||
|
let entry_def = $("<ul>").appendTo(list_ol)
|
||||||
|
let entry = list[i]
|
||||||
|
for (j=0; j<fields.length; j++) {
|
||||||
|
let fieldname = fields[j]
|
||||||
|
if (entry['address'] === wallet) {
|
||||||
|
let field_def = $("<li><strong>"+fieldname+": </strong>").appendTo(entry_def)
|
||||||
|
$(" <span class='"+fieldname+"'>").text(entry[fieldname]).appendTo(field_def)
|
||||||
|
found=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(found) {
|
||||||
|
makeLogEntryWallet(list_wrap, true)
|
||||||
|
makeLogEntryWallet('Account has been found in TOML file and validated.').resolve('DOMAIN VALIDATED <i class="fa fa-check-circle"></i>').addClass(CLASS_GOOD)
|
||||||
|
} else {
|
||||||
|
let entry_def = $("<ul>").appendTo(list_ol)
|
||||||
|
let field_def = $("<li><strong>address: </strong>").appendTo(entry_def)
|
||||||
|
$(" <span class='address'>").text('Not found ').appendTo(field_def).append(' <li class="badge badge-danger">ERROR</li>')
|
||||||
|
|
||||||
|
makeLogEntryWallet(list_wrap, true)
|
||||||
|
makeLogEntryWallet('Account not found in TOML file. Domain can not be verified.').resolve('VALIDATION FAILED').addClass(CLASS_BAD)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parsed.ACCOUNTS) {
|
||||||
|
if (!Array.isArray(parsed.ACCOUNTS)) {
|
||||||
|
makeLogEntryWallet("Account:").resolve("Wrong type - should be table-array").addClass(CLASS_BAD)
|
||||||
|
} else {
|
||||||
|
listEntriesWallet("Account:", parsed.ACCOUNTS, ACCOUNT_FIELDS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function decodeHexWallet(hex) {
|
||||||
|
let str = '';
|
||||||
|
for (let i = 0; i < hex.length; i += 2) {
|
||||||
|
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16))
|
||||||
|
}
|
||||||
|
const decodeLog = makeLogEntryWallet('Decoding domain hex')
|
||||||
|
decodeLog.resolve("SUCCESS").addClass(CLASS_GOOD)
|
||||||
|
fetchFile(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSubmitWallet(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
$('#verify-domain-result-title').show()
|
||||||
|
$('#verify-domain-result').show()
|
||||||
|
$('#verify-domain-log').empty()
|
||||||
|
|
||||||
|
fetchWallet()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$(document).ready(() => {
|
||||||
|
$('#domain-entry').submit(handleSubmitDomain)
|
||||||
|
$('#domain-verification').submit(handleSubmitWallet)
|
||||||
})
|
})
|
||||||
|
|||||||
8
styles/_toml-checker.scss
Normal file
8
styles/_toml-checker.scss
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
.toml-checker {
|
||||||
|
#result {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#verify-domain-result {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -68,6 +68,7 @@ $line-height-base: 1.5;
|
|||||||
@import "_feedback.scss";
|
@import "_feedback.scss";
|
||||||
@import "_video.scss";
|
@import "_video.scss";
|
||||||
@import "_top-banner.scss";
|
@import "_top-banner.scss";
|
||||||
|
@import "_toml-checker.scss";
|
||||||
|
|
||||||
// Light/Dark theme settings ---------------------------------------------------
|
// Light/Dark theme settings ---------------------------------------------------
|
||||||
// Option to only change theme on user system settings. No toggle.
|
// Option to only change theme on user system settings. No toggle.
|
||||||
|
|||||||
@@ -1,14 +1,21 @@
|
|||||||
{% extends "base.html.jinja" %}
|
{% extends "base.html.jinja" %}
|
||||||
|
|
||||||
|
{% block bodyclasses %}toml-checker{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<section class="container-fluid p-3">
|
<section class="container-fluid">
|
||||||
|
<div class="p-3">
|
||||||
<h1>xrp-ledger.toml Checker</h1>
|
<h1>xrp-ledger.toml Checker</h1>
|
||||||
|
|
||||||
<p>If you run an XRP Ledger validator or use the XRP Ledger for your business, you can provide information about your usage of the XRP Ledger to the world in a machine-readable <a href="https://developers.ripple.com/xrp-ledger-toml.html"><code>xrp-ledger.toml</code> file</a>.</p>
|
<p>If you run an XRP Ledger validator or use the XRP Ledger for your business, you can provide information about your usage of the XRP Ledger to the world in a machine-readable <a href="https://xrpl.org/xrp-ledger-toml.html"><code>xrp-ledger.toml</code> file</a>.</p>
|
||||||
|
|
||||||
<p>This tool allows you to verify that your <code>xrp-ledger.toml</code> file is syntactically
|
</div>
|
||||||
correct and deployed properly.</p><br/>
|
|
||||||
|
<div class="p-3 pb-5">
|
||||||
<form id="domain-entry">
|
<form id="domain-entry">
|
||||||
|
<h4>Look Up By Domain</h4>
|
||||||
|
<p>This tool allows you to verify that your <code>xrp-ledger.toml</code> file is syntactically
|
||||||
|
correct and deployed properly.</p>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="domain" type="text" class="form-control" required
|
<input id="domain" type="text" class="form-control" required
|
||||||
placeholder="example.com (Domain name to check)"
|
placeholder="example.com (Domain name to check)"
|
||||||
@@ -21,12 +28,32 @@
|
|||||||
<ul id="log">
|
<ul id="log">
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-3 pt-5">
|
||||||
|
<h4>Look Up By Account</h4>
|
||||||
|
<p>Enter an XRP Ledger address to see if that account is claimed by the domain it says owns it.</p>
|
||||||
|
<form id="domain-verification">
|
||||||
|
<div class="input-group">
|
||||||
|
<input id="verify-domain" type="text" class="form-control" required
|
||||||
|
placeholder="r... (Wallet Address to check)">
|
||||||
|
<br>
|
||||||
|
<button class="btn btn-primary form-control">Check account</button>
|
||||||
|
</div><!--/.input-group-->
|
||||||
|
</form>
|
||||||
|
<div id="verify-domain-result">
|
||||||
|
<h5 id="verify-domain-result-title" class='result-title'>Result</h5>
|
||||||
|
<ul id="verify-domain-log">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block endbody %}
|
{% block endbody %}
|
||||||
<script type="application/javascript" src="{{currentpage.prefix}}assets/vendor/iarna-toml-parse.js"></script>
|
|
||||||
<script type="application/javascript" src="{{currentpage.prefix}}assets/js/xrp-ledger-toml-checker.js"></script>
|
<script type="application/javascript" src="{{currentpage.prefix}}assets/js/xrp-ledger-toml-checker.js"></script>
|
||||||
|
|
||||||
|
<!-- TOML tool -->
|
||||||
|
<script type="application/javascript" src="{{currentpage.prefix}}assets/vendor/iarna-toml-parse.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block analytics %}
|
{% block analytics %}
|
||||||
|
|||||||
Reference in New Issue
Block a user