Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate the faucet page to Redocly #2243

Merged
merged 29 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ecf58df
Get basic HTML loading for faucet page
JST5000 Oct 30, 2023
0913f19
Add xrpl.js implementation
JST5000 Nov 2, 2023
a144c81
Add sidebar and fix throbber
JST5000 Nov 2, 2023
a218d2f
Add translates
JST5000 Nov 2, 2023
e2e5988
Try to format sidebar
JST5000 Nov 2, 2023
851f10d
Fix formatting
JST5000 Nov 3, 2023
30f6555
Support xrpl.js
JST5000 Nov 7, 2023
602bd8b
Fix links
JST5000 Nov 7, 2023
d4c0cff
Comment out XRPLGuard for now
JST5000 Nov 8, 2023
3455f49
Make AMM Devnet faucet work
JST5000 Nov 9, 2023
751596c
Improve readability
JST5000 Nov 9, 2023
0171913
Update all instances of link + fix topnav
JST5000 Nov 21, 2023
9e18205
Remove unnecessary file
JST5000 Nov 21, 2023
25745c6
Use a more current version of xrpl
JST5000 Nov 21, 2023
04652de
Add missing loader while keys are generating
JST5000 Nov 21, 2023
2b9b4a5
Type with xrpl and remove unnecessary script
JST5000 Nov 21, 2023
625e551
Use string interpolation instead of multiple trans
JST5000 Nov 21, 2023
55f17ec
Move faucets into a json file
JST5000 Nov 21, 2023
61fa7a8
Remove the old faucet code
JST5000 Dec 6, 2023
b353dad
Use xrpl-beta directly
JST5000 Dec 6, 2023
078c0b3
Use dropsToXRP
JST5000 Dec 6, 2023
6fc1b26
Support hooks natively
JST5000 Dec 6, 2023
0a5eb7a
Remove AMM-Devnet
JST5000 Dec 6, 2023
a2bbc38
Revert changes to link path
JST5000 Dec 6, 2023
9e15ada
Revert link changes pt 2
JST5000 Dec 6, 2023
a90e965
Revert pt 3
JST5000 Dec 6, 2023
adda4a9
Use XRPLoader for loading icon
JST5000 Dec 6, 2023
6ccbb94
Fix small mistakes
JST5000 Dec 8, 2023
94513ff
Remove unnecessary changes
JST5000 Dec 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion content/_code-samples/get-started/py/prepare-payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


# Create a wallet using the testnet faucet:
# https://xrpl.org/xrp-testnet-faucet.html
# https://xrpl.org/dev-tools/xrp-faucets.html
from xrpl.wallet import generate_faucet_wallet
test_wallet = generate_faucet_wallet(client, debug=True)

Expand Down
17 changes: 17 additions & 0 deletions content/dev-tools/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import xrpl from "xrpl"
JST5000 marked this conversation as resolved.
Show resolved Hide resolved

const client = new xrpl.Client('wss://amm.devnet.rippletest.net:51233/')

// The snippet walks us through creating and finishing escrows.
async function sendTx(){
await client.connect()

// creating wallets as prerequisite
const wallet = xrpl.Wallet.generate()
const response = await client.fundWallet(wallet, { usageContext: "xrpl.org-faucet" })
console.log(response)

await client.disconnect()
}

void sendTx()
228 changes: 228 additions & 0 deletions content/dev-tools/xrp-faucets.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import * as React from 'react';
import { useTranslate } from '@portal/hooks';
import { useState } from 'react';
import { XRPLGuard } from 'content/static/js/xrpl-guard';

// TODO: Directly import xrpl when xrpl.js 3.0 is released.
// xrpl is imported via <script> tag below to avoid webpack issues.
// import { Client, Wallet } from 'xrpl';

interface FaucetInfo {
id: string,
wsUrl: string,
jsonRpcUrl: string,
faucetUrl: string,
shortName: string,
desc: string,
}

async function waitForSequence(client, address: string): Promise<{ sequence: string, balance: string }> {
let response;
while (true) {
try {
response = await client.request({
command: "account_info",
account: address,
ledger_index: "validated"
})
break
} catch(e) {
await new Promise(resolve => setTimeout(resolve, 1000))
}
}
console.log(response)

return { sequence: response.result.account_data.Sequence, balance: response.result.account_data.Balance}
}

function FaucetEndpoints({ faucet, givenKey } : { faucet: FaucetInfo, givenKey: string}) {
const { translate } = useTranslate();

return (<div key={givenKey}>
<h4>{translate(faucet.shortName)} {translate("Servers")}</h4>
<pre>
<code>
// WebSocket<br/>
{faucet.wsUrl}<br/>
<br/>
// JSON-RPC<br/>
{faucet.jsonRpcUrl}
</code>
</pre>
</div>)
}

function FaucetSidebar({ faucets }: { faucets: FaucetInfo[]}) {
return (<aside className="right-sidebar col-lg-6 order-lg-4" role="complementary">
{faucets.map(
(faucet) => <FaucetEndpoints faucet={faucet} key={faucet.shortName + " Endpoints"} givenKey={faucet.shortName + " Endpoints"}/>
)}
</aside>)
}

export default function XRPFaucets() {
const { translate } = useTranslate();

const faucets: FaucetInfo[] = [
{
id: "faucet-select-testnet",
wsUrl: "wss://s.altnet.rippletest.net:51233/",
jsonRpcUrl: "https://s.altnet.rippletest.net:51234/",
faucetUrl: "faucet.altnet.rippletest.net",
shortName: "Testnet",
desc: "Mainnet-like network for testing applications."
},
{
id: "faucet-select-devnet",
wsUrl: "wss://s.devnet.rippletest.net:51233/",
jsonRpcUrl: "https://s.devnet.rippletest.net:51234/",
faucetUrl: "faucet.devnet.rippletest.net",
shortName: "Devnet",
desc: "Preview of upcoming amendments."
},
{
id: "faucet-select-ammdevnet",
wsUrl: "wss://amm.devnet.rippletest.net:51233/",
jsonRpcUrl: "https://amm.devnet.rippletest.net:51234/",
faucetUrl: "ammfaucet.devnet.rippletest.net",
shortName: "AMM-Devnet",
desc: "XLS-30d Automated Market Makers preview network."
},
]

const [selectedFaucet, setSelectedFaucet] = useState(faucets[0])

return (
<div className="container-fluid" role="document" id="main_content_wrapper">
<div className="row">
<FaucetSidebar faucets={faucets}/>
<main className="main col-md-7 col-lg-6 order-md-3" role="main" id="main_content_body">
<section className="container-fluid pt-3 p-md-3">
<h1>{translate("XRP Faucets")}</h1>
<div className="content">
<p>{translate("These ")}<a href="parallel-networks.html">{translate("parallel XRP Ledger test networks")}</a> {translate("provide platforms for testing changes to the XRP Ledger and software built on it, without using real funds.")}</p>
<p>{translate("These funds are intended for")} <strong>{translate("testing")}</strong> {translate("only. Test networks' ledger history and balances are reset as necessary. Devnets may be reset without warning.")}</p>
<p>{translate("All balances and XRP on these networks are separate from Mainnet. As a precaution, do not use the Testnet or Devnet credentials on the Mainnet.")}</p>

<h3>{translate("Choose Network:")}</h3>
{ faucets.map((net) => (
<div className="form-check" key={"network-" + net.shortName}>
<input onChange={() => setSelectedFaucet(net)} className="form-check-input" type="radio"
name="faucet-selector" id={net.id} checked={selectedFaucet.shortName == net.shortName} />
<label className="form-check-label" htmlFor={net.id}>
<strong>{translate(net.shortName)}</strong>: {translate(net.desc)}
</label>
</div>
)) }

<p className="mb-3"><b>{translate("Hooks Testnet")}</b>: <a href="https://hooks-testnet-v3.xrpl-labs.com/" className="external-link">{translate("See the Hooks Faucet")}</a></p>
<TestCredentials selectedFaucet={selectedFaucet}/>
</div>
</section>
</main>
</div>
</div>
)
}

async function generateFaucetCredentialsAndUpdateUI(
selectedFaucet: FaucetInfo,
setGeneratedCredentialsFaucet: React.Dispatch<React.SetStateAction<string>>,
setAddress: React.Dispatch<React.SetStateAction<string>>,
setSecret: React.Dispatch<React.SetStateAction<string>>,
setBalance: React.Dispatch<React.SetStateAction<string>>,
setSequence: React.Dispatch<React.SetStateAction<string>>): Promise<void> {

// Clear existing credentials
setGeneratedCredentialsFaucet(selectedFaucet.shortName)
setAddress("")
setSecret("")
setBalance("")
setSequence("")
const { translate } = useTranslate();


// @ts-expect-error - xrpl is added via a script tag
const wallet = xrpl.Wallet.generate()

// @ts-expect-error - xrpl is added via a script tag
const client = new xrpl.Client(selectedFaucet.wsUrl)
await client.connect()

try {

setAddress(wallet.address)
setSecret(wallet.seed)

await client.fundWallet(wallet, { faucetHost: selectedFaucet.faucetUrl, usageContext: "xrpl.org-faucet" })

const response = await waitForSequence(client, wallet.address)

setSequence(response.sequence)
setBalance(response.balance)

} catch (e) {
alert(translate("There was an error with the " + selectedFaucet.shortName + " faucet. Please try again."))
}
}

function TestCredentials({selectedFaucet}) {
const { translate } = useTranslate();

const [generatedCredentialsFaucet, setGeneratedCredentialsFaucet] = useState("")
const [address, setAddress] = useState("")
const [secret, setSecret] = useState("")
const [balance, setBalance] = useState("")
const [sequence, setSequence] = useState("")

return (<div>
{/* TODO: Once xrpl.js 3.0 is released, replace this with a direct xrpl.js import */}
<script src="https://unpkg.com/xrpl@2.5.0-beta.0/build/xrpl-latest-min.js" async />
JST5000 marked this conversation as resolved.
Show resolved Hide resolved

{/* <XRPLGuard> TODO: Re-add this once we find a good way to avoid browser/server mismatch errors */}
<div className="btn-toolbar" role="toolbar" aria-label="Button">
<button id="generate-creds-button" onClick={
() => generateFaucetCredentialsAndUpdateUI(
selectedFaucet,
setGeneratedCredentialsFaucet,
setAddress,
setSecret,
setBalance,
setSequence)
} className="btn btn-primary mr-2 mb-2">
Generate {selectedFaucet.shortName} credentials
JST5000 marked this conversation as resolved.
Show resolved Hide resolved
</button>
</div>
{/* </XRPLGuard> */}

{generatedCredentialsFaucet && <div id="your-credentials">
<h2>{translate("Your")} {generatedCredentialsFaucet} {translate("Credentials")}</h2>
JST5000 marked this conversation as resolved.
Show resolved Hide resolved
</div>}

{address && <div id="address"><h3>{translate("Address")}</h3>{address}</div>}

{secret && <div id="secret"><h3>{translate("Secret")}</h3>{secret}</div>}
{(address && !balance) && (<div><br/>
<div id="loader" style={{display: (address && !balance) ? "inline" : "none"}}>
<img alt="(loading)" className="throbber" src="/img/xrp-loader-96.png" /> {translate("Funding account...")}
</div>
</div>)}

{balance && <div id="balance">
<h3>{translate("Balance")}</h3>
{(Number(balance) * 0.000001).toLocaleString("en")} {translate("XRP")}
JST5000 marked this conversation as resolved.
Show resolved Hide resolved
</div>}

{sequence && <div id="sequence">
<h3>{translate("Sequence Number")}</h3>
{sequence}
</div>}

{(secret && !sequence) &&
(<div id="loader" style={{display: sequence ? "inline" : "none"}}>
<img alt="(loading)" className="throbber" src="/img/xrp-loader-96.png" />{translate("Waiting...")}
</div>)}

</div>
)
}
6 changes: 3 additions & 3 deletions content/docs.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const recommendedPages = [
},
{
description: 'XRP Faucet',
link: './xrp-testnet-faucet.html',
link: '../dev-tools/xrp-faucets',
},
{
description: 'Getting Started with Python',
Expand Down Expand Up @@ -123,7 +123,7 @@ const getStartedVideos = [
const devTools = [
{
title: 'Faucets',
link: './xrp-testnet-faucet.html',
link: '../dev-tools/xrp-faucets',
description: 'Get credentials and test-XRP for XRP Ledger Testnet or Devnet.',
},
{
Expand Down Expand Up @@ -407,7 +407,7 @@ export default function Docs() {
'Connect to the XRP Ledger Testnet network to develop and test your apps built on the XRP Ledger, without risking real money or impacting production XRP Ledger users.'
)}
</p>
<a className="btn btn-primary btn-arrow" href="xrp-testnet-faucet.html">
<a className="btn btn-primary btn-arrow" href="../dev-tools/xrp-faucets">
JST5000 marked this conversation as resolved.
Show resolved Hide resolved
{translate('Generate Testnet Credentials')}
</a>
</div>
Expand Down
2 changes: 1 addition & 1 deletion content/sidebars.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@
- label: ripple.txt Validator
- label: xrp-ledger.toml Checker
- label: Domain Verification Checker
- label: XRP Faucets
- page: /dev-tools/xrp-faucets.page.tsx
- label: Transaction Sender
- label: XRPL Learning Portal
href: https://learn.xrpl.org/
Expand Down
27 changes: 27 additions & 0 deletions content/static/js/type-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
type TypeofType =
| 'bigint'
| 'boolean'
| 'function'
| 'number'
| 'object'
| 'string'
| 'undefined'

type TypeCheckFn = (thing: unknown) => boolean


/**
* Curried function for creating typeof checker functions.
* @param {string} type The type to check against (eg 'string', 'number')
* @param {function} [secondaryTest] Optional additional test function to run in cases where a type match isn't always a sure indicator.
* @returns {boolean} Whether the value matches the type
*/
const isTypeof =
<T>(type: TypeofType, secondaryTest?: TypeCheckFn) =>
(thing: unknown): thing is T => {
const matches = typeof thing === type
if (matches && secondaryTest) return secondaryTest(thing)
return matches
}

export const isFunction = isTypeof<(...args: unknown[]) => unknown>('function')
Loading