wietsewind's notebooks

  • Order ID Encoder / Decoder - /wietsewind/order-id-encoder-decoder
    Last edited 3 months ago
    const chars = 'abcdehlkmrtwxyz'.toUpperCase() const to = (decimal) => { let out = '' while (true) { let remainder = (decimal - 1) % chars.length out = chars[remainder] + out; decimal = Math.floor((decimal - 1) / chars.length); if (decimal === 0) break } return out; } const from = (alpha) => { const crs = chars.split('') const letters = alpha.split('') let out = 0 for (let i = 0; i < letters.length; i++) { let indexPos = crs.indexOf(letters[letters.length - 1 - i]) out += (indexPos + 1) * Math.pow(crs.length, i) } return out } module.exports = { to, from }
  • Verify XRPL Signature (XUMM) - /wietsewind/verify-xrpl-signature-xumm
    Last edited 3 months ago
    const verifySignature = require('verify-xrpl-signature').verifySignature const someTx = '1200032280000000240000003241833237B8665D2F4E00135E8DE646589F68400000000000000C732103709723A5967EAAED571B71DB511D87FA44CC7CDDF827A37F457A25E14D862BCD74473045022100C6A6999BD33153C6A236D78438D1BFEEEC810CFE05D0E41339B577560C9143CA022074F07881F559F56593FF680049C12FC3BCBB0B73CE02338651522891D95886F981146078086881F39B191D63B528D914FEA7F8CA2293F9EA7C06636C69656E747D15426974686F6D7020746F6F6C20762E20302E302E337E0A706C61696E2F74657874E1F1' // { // "Flags": 2147483648, // "Sequence": 213, // "Fee": "12", // "SigningPubKey": "02C71103C10E706EFCBACDBC1A1F505D0421369CD625A9953990393E14202DC152", // "TxnSignature": "3044022035B6ABAC593979FBB745E8DB71B2CCDC255220EFE03ECC9037F7E0DA6356F0A302201119ED7F26D4131A2E24607B60911ED7E01571FD82F433640562C755135D3979", // "Account": "rwiEtsEY8YRxgHQgvWXsxyUBSZzTMqL2EX" // } console.log(verifySignature(someTx)) // In case of explicit MultiSign signer verification: // console.log(verifySignature(someTx, 'rwiETSee2wMz3SBnAG8hkMsCgvGy9LWbZ1'))
  • Get GH XRPL Tx Types - /wietsewind/get-gh-xrpl-tx-types
    Last edited 9 months ago
    const Fetch = require('node-fetch') const getTransactionTypes = async () => { const dirList = await Fetch('https://api.github.com/repos/ripple/xrpl-dev-portal/contents/content/references/protocol-reference/transactions/transaction-types').then(r => r.json()) const relevantFiles = dirList.filter(r => r.name.match(/^[a-zA-Z]+\.md$/)) return Promise.all(relevantFiles.map(async f => { const source = await Fetch(f.download_url).then(r => r.text()) return { transactionType: source.match(/^# ([a-zA-Z]+)/gm)[0].slice(2), docLink: 'https://xrpl.org/' + f.name.split('.')[0] + '.html', codeSamples: source.split(`\n`).join(' ').match(/```.+?```/gm) .map(s => s.split('```')[1].trim().replace(/^json[\n]*/gm, '')) .map(s => s.replace(/,[ \t\n\\t\\n]*}$/, '}')) .map(s => { try { return JSON.parse(s) } catch (e) { return s } }) } })) } const transactionTypes = await getTransactionTypes() console.log(transactionTypes)
  • List offline validators - /wietsewind/list-offline-validators
    Last edited 10 months ago
    const axios = require('axios') exports.endpoint = async (request, response) => { const d = await axios.get('https://api.xrpscan.com/api/v1/validatorregistry') const mapped = d.data.filter(r => r.chain === 'main' && r.unl && r.unl.length > 0).map(r => { return { domain: r.domain || r.domain_legacy, last_seen: Math.abs((Number(new Date(r.last_seen)) - Number(new Date())) / 1000) } }) const offlineValidators = mapped.filter(d => d.last_seen > 10).map(d => d.domain) if (request.url.match(/string/)) { return response.end(offlineValidators.join(', ')) } return response.end(JSON.stringify({ offlineValidators, onlineValidators: mapped.filter(m => offlineValidators.indexOf(m.domain) < 0).map(d => d.domain) })) }
  • Encode/Decode tagged XRPL addresses & destination tag - /wietsewind/encode-decode-tagged-xrpl-addresses-destination-tag
    Last edited 10 months ago
    const {Encode, Decode} = require('xrpl-tagged-address-codec') const tagged = Encode({ account: 'rPEPPER7kfTD9w2To4CQk6UCfuHM9c6GDY', tag: 495 }) console.log(tagged) const untagged = Decode(tagged) console.log(untagged)
  • Uppercase Memos - /wietsewind/uppercase-memos
    Last edited a year ago
    const tx = { TransactionType : 'Payment', Destination: 'rncjeoo4xeqKtrrqVHsxQjrV6CyZ93Wkvm', Amount: String(10000), Memos: [ { Memo: { MemoData: Buffer.from('Hi there! How are things?', 'utf8').toString('hex') } }, { Memo: { MemoData: Buffer.from('Anything else?', 'utf8').toString('hex'), MemoType: Buffer.from('something 123', 'utf8').toString('hex'), MemoFormat: Buffer.from('some/mimetype', 'utf8').toString('hex') } } ] } if (typeof tx.Memos !== 'undefined' && Array.isArray(tx.Memos)) { tx.Memos = tx.Memos .filter(m => typeof m.Memo === 'object' && m.Memo !== null) .map(m => { return { Memo: Object.keys(m.Memo).reduce((a, b) => { if (typeof m.Memo[b] === 'string') { Object.assign(a, { [b]: m.Memo[b].toUpperCase() }) } return a }, {}) } }) } console.log(tx.Memos)
  • XRPL JSON RPC - /wietsewind/xrpl-json-rpc
    Last edited a year ago
    const fetch = require('node-fetch') const testnet = true const endpoint = testnet ? 'https://testnet-rpc.xrpl-labs.com' : 'https://xrplcluster.com' const command = { "method": "account_tx", "params": [ { "account": "rXUMMaPpZqPutoRszR29jtC8amWq3APkx", "limit": 2 } ] } const call = await fetch(endpoint, { method: 'POST', body: JSON.stringify(command) }) const data = await call.json() console.log(data)
  • XRPL nodes to hostname - /wietsewind/xrpl-nodes-to-hostname
    Last edited a year ago
    const fetch = require('node-fetch') const nodeToDomain = async () => { const manifests = (await (await fetch('https://validations.zaphod.ee/manifests.json')).json()) .map(r => r.result.details) .filter(r => r.domain !== '') .reduce((a, b) => Object.assign(a, { [b.master_key]: b.domain }), {}) const unlmap = await (await fetch('https://validations.zaphod.ee/unlmap.json')).json() const list = { ...manifests, ...unlmap } console.log(list) return list } console.log(nodeToDomain())
  • Get MultiSigned pubkey - /wietsewind/get-multisigned-pubkey
    Last edited 2 years ago
    const bc = require('ripple-binary-codec') const ms = '1200002400000003201B00503A406140000000000000016840000000000000677300811461D46A8DE4DAE4F72196C87995D9390BA82BA9F18314F84E8A80D08854F3621F9214D58F04D41A07EE10F3E01073210217241703CBC4D52C04D59269DE634B388E57C1E72F9462EEF4B435E041ED88367446304402204789F8AA9625D65FD65F43A7AC9FBFAEF64026A4BD1421B0F87ADE24B15F477302207241FDC7B31E15FDB121CA64623B6AC84475A30992E092F56656A731743B9FF781146B07151AAEC3405E3D83CEE654456B621EBF0007E1F1F9EA7C08536F6D65547970657D08536F6D6544617461E1EA7C09446576656C6F7065727D0B4057696574736557696E64E1F1' console.log( bc.decode(ms) .Signers .map(s => s.Signer.SigningPubKey) )
  • Secret Numbers Rollover - /wietsewind/secret-numbers-rollover
    Last edited 2 years ago
    const {Account, Utils} = require('xrpl-secret-numbers') const tests = { 'uInt16': 34462, 'Rollover (uInt16)': 34462 + parseInt('10000', 16) } Object.keys(tests).map(k => { const secretNumbers = Array(8).fill(tests[k]).map((_, i) => { return String(_) + Utils.calculateChecksum(i, _) }) const familySeed = new Account(secretNumbers).getFamilySeed() console.log(`${k}: ${familySeed}`, secretNumbers.join(' ')) })