feat: remove 3 http related polyfills (#2375)

Switch to using fetch for browser and `node-fetch` for node for the faucet calls.  This reduces the webpack bundle by 3.2% or 16.5kb gzipped.

The fundWallet code has been refactored to be much more straight forward due to not having to do such low level operations.

This improves the frontend setup process by no longer requiring several polyfills such as `url`, `stream-http`, and `https-browserify`.
This commit is contained in:
Caleb Kniffen
2023-07-26 13:18:46 -05:00
parent 3b7dd4ea87
commit 0050b2f75e
10 changed files with 163 additions and 204 deletions

View File

@@ -22,12 +22,8 @@ To use `xrpl.js` with React, you need to install shims for core NodeJS modules.
assert \
buffer \
crypto-browserify \
https-browserify \
os-browserify \
process \
stream-browserify \
stream-http \
url
stream-browserify
```
2. Modify your webpack configuration
@@ -48,11 +44,7 @@ To use `xrpl.js` with React, you need to install shims for core NodeJS modules.
Object.assign(fallback, {
assert: require.resolve("assert"),
crypto: require.resolve("crypto-browserify"),
http: require.resolve("stream-http"),
https: require.resolve("https-browserify"),
os: require.resolve("os-browserify"),
stream: require.resolve("stream-browserify"),
url: require.resolve("url"),
ws: require.resolve("xrpl/dist/npm/client/WSWrapper"),
});
config.resolve.fallback = fallback;
@@ -141,7 +133,6 @@ export default defineConfig({
},
optimizeDeps: {
esbuildOptions: {
define: {
global: 'globalThis',
},
@@ -165,8 +156,6 @@ resolve: {
events: 'events',
crypto: 'crypto-browserify',
stream: 'stream-browserify',
http: 'stream-http',
https: 'https-browserify',
ws: 'xrpl/dist/npm/client/WSWrapper',
},
}})
@@ -181,8 +170,6 @@ npm install --save-dev @esbuild-plugins/node-globals-polyfill \
events \
crypto-browserify \
stream-browserify \
stream-http \
https-browserify \
xrpl
```

77
package-lock.json generated
View File

@@ -43,7 +43,6 @@
"eslint-plugin-tsdoc": "^0.2.16",
"eventemitter2": "^6.0.0",
"expect": "^29.3.1",
"https-browserify": "^1.0.0",
"jest": "^29.3.1",
"jest-mock": "^29.3.1",
"lerna": "^4.0.0",
@@ -55,12 +54,10 @@
"source-map-loader": "^5.0.0",
"source-map-support": "^0.5.16",
"stream-browserify": "^3.0.0",
"stream-http": "3.2.0",
"ts-jest": "^29.0.3",
"ts-loader": "^9.2.5",
"ts-node": "^10.2.1",
"typescript": "^5.1.6",
"url": "^0.11.0",
"webpack": "^5.81.0",
"webpack-bundle-analyzer": "^4.1.0",
"webpack-cli": "^5.0.1"
@@ -5491,6 +5488,33 @@
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"node_modules/cross-fetch": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
"integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==",
"dependencies": {
"node-fetch": "^2.6.12"
}
},
"node_modules/cross-fetch/node_modules/node-fetch": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
"integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -6041,7 +6065,6 @@
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
"dev": true,
"optional": true,
"dependencies": {
"iconv-lite": "^0.6.2"
@@ -6051,7 +6074,6 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"optional": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
@@ -10743,8 +10765,7 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash._reinterpolate": {
"version": "3.0.0",
@@ -13119,7 +13140,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
"dev": true,
"engines": {
"node": ">=6"
}
@@ -13961,7 +13981,7 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
"devOptional": true
},
"node_modules/schema-utils": {
"version": "3.3.0",
@@ -15169,7 +15189,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz",
"integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==",
"dev": true,
"dependencies": {
"punycode": "^2.1.1"
},
@@ -15884,7 +15903,6 @@
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
"integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==",
"dev": true,
"engines": {
"node": ">=10.4"
}
@@ -16073,7 +16091,6 @@
"version": "8.7.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz",
"integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==",
"dev": true,
"dependencies": {
"lodash": "^4.7.0",
"tr46": "^2.1.0",
@@ -16518,7 +16535,7 @@
"bignumber.js": "^9.0.0",
"bip32": "^2.0.6",
"bip39": "^3.0.4",
"https-proxy-agent": "^5.0.0",
"cross-fetch": "^4.0.0",
"ripple-address-codec": "^4.3.1",
"ripple-binary-codec": "^1.11.0",
"ripple-keypairs": "^1.3.1",
@@ -20957,6 +20974,24 @@
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"cross-fetch": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
"integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==",
"requires": {
"node-fetch": "^2.6.12"
},
"dependencies": {
"node-fetch": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
"integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
"requires": {
"whatwg-url": "^5.0.0"
}
}
}
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -21393,7 +21428,6 @@
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
"dev": true,
"optional": true,
"requires": {
"iconv-lite": "^0.6.2"
@@ -21403,7 +21437,6 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"optional": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
@@ -25062,8 +25095,7 @@
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash._reinterpolate": {
"version": "3.0.0",
@@ -26953,8 +26985,7 @@
"punycode": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
"dev": true
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="
},
"pure-rand": {
"version": "6.0.4",
@@ -27589,7 +27620,7 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
"devOptional": true
},
"schema-utils": {
"version": "3.3.0",
@@ -28526,7 +28557,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz",
"integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==",
"dev": true,
"requires": {
"punycode": "^2.1.1"
}
@@ -29043,8 +29073,7 @@
"webidl-conversions": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
"integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==",
"dev": true
"integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w=="
},
"webpack": {
"version": "5.90.0",
@@ -29163,7 +29192,6 @@
"version": "8.7.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz",
"integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==",
"dev": true,
"requires": {
"lodash": "^4.7.0",
"tr46": "^2.1.0",
@@ -29405,6 +29433,7 @@
"bip39": "^3.0.4",
"browserify-fs": "^1.0.0",
"constants-browserify": "^1.0.0",
"cross-fetch": "^4.0.0",
"https-browserify": "^1.0.0",
"https-proxy-agent": "^7.0.1",
"karma": "^6.4.1",

View File

@@ -48,7 +48,6 @@
"eslint-plugin-tsdoc": "^0.2.16",
"eventemitter2": "^6.0.0",
"expect": "^29.3.1",
"https-browserify": "^1.0.0",
"jest": "^29.3.1",
"jest-mock": "^29.3.1",
"lerna": "^4.0.0",
@@ -60,12 +59,10 @@
"source-map-loader": "^5.0.0",
"source-map-support": "^0.5.16",
"stream-browserify": "^3.0.0",
"stream-http": "3.2.0",
"ts-jest": "^29.0.3",
"ts-loader": "^9.2.5",
"ts-node": "^10.2.1",
"typescript": "^5.1.6",
"url": "^0.11.0",
"webpack": "^5.81.0",
"webpack-bundle-analyzer": "^4.1.0",
"webpack-cli": "^5.0.1"

View File

@@ -25,7 +25,7 @@
"bignumber.js": "^9.0.0",
"bip32": "^2.0.6",
"bip39": "^3.0.4",
"https-proxy-agent": "^5.0.0",
"cross-fetch": "^4.0.0",
"ripple-address-codec": "^4.3.1",
"ripple-binary-codec": "^1.11.0",
"ripple-keypairs": "^1.3.1",

View File

@@ -1,6 +1,4 @@
import { IncomingMessage } from 'http'
import { request as httpsRequest, RequestOptions } from 'https'
import fetch from 'cross-fetch'
import { isValidClassicAddress } from 'ripple-address-codec'
import type { Client } from '../client'
@@ -19,6 +17,40 @@ const INTERVAL_SECONDS = 1
// Maximum attempts to retrieve a balance
const MAX_ATTEMPTS = 20
export interface FundingOptions {
/**
* A custom amount to fund, if undefined or null, the default amount will be 1000.
*/
amount?: string
/**
* A custom host for a faucet server. On devnet, testnet, AMM devnet, and HooksV3 testnet, `fundWallet` will
* attempt to determine the correct server automatically. In other environments, or if you would like to customize
* the faucet host in devnet or testnet, you should provide the host using this option.
*/
faucetHost?: string
/**
* A custom path for a faucet server. On devnet,
* testnet, AMM devnet, and HooksV3 testnet, `fundWallet` will
* attempt to determine the correct path automatically. In other environments,
* or if you would like to customize the faucet path in devnet or testnet,
* you should provide the path using this option.
* Ex: client.fundWallet(null,{'faucet.altnet.rippletest.net', '/accounts'})
* specifies a request to 'faucet.altnet.rippletest.net/accounts' to fund a new wallet.
*/
faucetPath?: string
/**
* An optional field to indicate the use case context of the faucet transaction
* Ex: integration test, code snippets.
*/
usageContext?: string
}
interface FaucetRequestBody {
destination?: string
xrpAmount?: string
usageContext?: string
userAgent: string
}
/**
* The fundWallet() method is used to send an amount of XRP (usually 1000) to a new (randomly generated)
* or existing XRP Ledger wallet.
@@ -65,36 +97,16 @@ const MAX_ATTEMPTS = 20
*
* @param this - Client.
* @param wallet - An existing XRPL Wallet to fund. If undefined or null, a new Wallet will be created.
* @param options - See below.
* @param options.faucetHost - A custom host for a faucet server. On devnet,
* testnet, devnet, and HooksV3 testnet, `fundWallet` will
* attempt to determine the correct server automatically. In other environments,
* or if you would like to customize the faucet host in devnet or testnet,
* you should provide the host using this option.
* @param options.faucetPath - A custom path for a faucet server. On devnet,
* testnet, AMM devnet, and HooksV3 testnet, `fundWallet` will
* attempt to determine the correct path automatically. In other environments,
* or if you would like to customize the faucet path in devnet or testnet,
* you should provide the path using this option.
* Ex: client.fundWallet(null,{'faucet.altnet.rippletest.net', '/accounts'})
* specifies a request to 'faucet.altnet.rippletest.net/accounts' to fund a new wallet.
* @param options.amount - A custom amount to fund, if undefined or null, the default amount will be 1000.
* @param options.usageContext - An optional field to indicate the use case context of the faucet transaction
* Ex: integration test, code snippets.
* @param options - FundingOptions
* @returns A Wallet on the Testnet or Devnet that contains some amount of XRP,
* and that wallet's balance in XRP.
* @throws When either Client isn't connected or unable to fund wallet address.
*/
// eslint-disable-next-line max-lines-per-function -- All lines necessary
async function fundWallet(
this: Client,
wallet?: Wallet | null,
options?: {
faucetHost?: string
faucetPath?: string
amount?: string
usageContext?: string
},
options: FundingOptions = {},
): Promise<{
wallet: Wallet
balance: number
@@ -102,6 +114,7 @@ async function fundWallet(
if (!this.isConnected()) {
throw new RippledError('Client not connected, cannot call faucet')
}
const existingWallet = Boolean(wallet)
// Generate a new Wallet if no existing Wallet is provided or its address is invalid to fund
const walletToFund =
@@ -110,151 +123,83 @@ async function fundWallet(
: Wallet.generate()
// Create the POST request body
const postBody = Buffer.from(
new TextEncoder().encode(
JSON.stringify({
destination: walletToFund.classicAddress,
xrpAmount: options?.amount,
userAgent: 'xrpl.js',
usageContext: options?.usageContext,
}),
),
)
const postBody: FaucetRequestBody = {
destination: walletToFund.classicAddress,
xrpAmount: options.amount,
usageContext: options.usageContext,
userAgent: 'xrpl.js',
}
let startingBalance = 0
try {
startingBalance = Number(
await this.getXrpBalance(walletToFund.classicAddress),
)
} catch {
/* startingBalance remains '0' */
if (existingWallet) {
try {
startingBalance = Number(
await this.getXrpBalance(walletToFund.classicAddress),
)
} catch {
/* startingBalance remains what it was previously */
}
}
// Options to pass to https.request
const httpOptions = getHTTPOptions(this, postBody, {
hostname: options?.faucetHost,
pathname: options?.faucetPath,
})
return returnPromise(
httpOptions,
this,
startingBalance,
walletToFund,
postBody,
)
return requestFunding(options, this, startingBalance, walletToFund, postBody)
}
// eslint-disable-next-line max-params -- Helper function created for organizational purposes
async function returnPromise(
options: RequestOptions,
async function requestFunding(
options: FundingOptions,
client: Client,
startingBalance: number,
walletToFund: Wallet,
postBody: Buffer,
postBody: FaucetRequestBody,
): Promise<{
wallet: Wallet
balance: number
}> {
return new Promise((resolve, reject) => {
const request = httpsRequest(options, (response) => {
const chunks: Uint8Array[] = []
response.on('data', (data) => chunks.push(data))
// eslint-disable-next-line @typescript-eslint/no-misused-promises -- not actually misused, different resolve/reject
response.on('end', async () =>
onEnd(
response,
chunks,
client,
startingBalance,
walletToFund,
resolve,
reject,
),
)
})
// POST the body
request.write(postBody)
request.on('error', (error) => {
reject(error)
})
request.end()
})
}
function getHTTPOptions(
client: Client,
postBody: Uint8Array,
options?: {
hostname?: string
pathname?: string
},
): RequestOptions {
const finalHostname = options?.hostname ?? getFaucetHost(client)
const finalPathname = options?.pathname ?? getDefaultFaucetPath(finalHostname)
return {
hostname: finalHostname,
port: 443,
path: finalPathname,
const hostname = options.faucetHost ?? getFaucetHost(client)
if (!hostname) {
throw new XRPLFaucetError('No faucet hostname could be derived')
}
const pathname = options.faucetPath ?? getDefaultFaucetPath(hostname)
const response = await fetch(`https://${hostname}${pathname}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': postBody.length,
},
}
}
// eslint-disable-next-line max-params -- Helper function created for organizational purposes
async function onEnd(
response: IncomingMessage,
chunks: Uint8Array[],
client: Client,
startingBalance: number,
walletToFund: Wallet,
resolve: (response: { wallet: Wallet; balance: number }) => void,
reject: (err: ErrorConstructor | Error | unknown) => void,
): Promise<void> {
const body = Buffer.concat(chunks).toString()
body: JSON.stringify(postBody),
})
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- It's a FaucetWallet
const body = (await response.json()) as FaucetWallet
// "application/json; charset=utf-8"
if (response.headers['content-type']?.startsWith('application/json')) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- We know this is safe and correct
const faucetWallet: FaucetWallet = JSON.parse(body)
const classicAddress = faucetWallet.account.classicAddress
await processSuccessfulResponse(
if (
response.ok &&
response.headers.get('Content-Type')?.startsWith('application/json')
) {
const classicAddress = body.account.classicAddress
return processSuccessfulResponse(
client,
classicAddress,
walletToFund,
startingBalance,
resolve,
reject,
)
} else {
reject(
new XRPLFaucetError(
`Content type is not \`application/json\`: ${JSON.stringify({
statusCode: response.statusCode,
contentType: response.headers['content-type'],
body,
})}`,
),
)
}
return processError(response)
}
// eslint-disable-next-line max-params, max-lines-per-function -- Only used as a helper function, lines inc due to added balance.
// eslint-disable-next-line max-params -- Only used as a helper function, lines inc due to added balance.
async function processSuccessfulResponse(
client: Client,
classicAddress: string | undefined,
walletToFund: Wallet,
startingBalance: number,
resolve: (response: { wallet: Wallet; balance: number }) => void,
reject: (err: ErrorConstructor | Error | unknown) => void,
): Promise<void> {
): Promise<{
wallet: Wallet
balance: number
}> {
if (!classicAddress) {
reject(new XRPLFaucetError(`The faucet account is undefined`))
return
return Promise.reject(
new XRPLFaucetError(`The faucet account is undefined`),
)
}
try {
// Check at regular interval if the address is enabled on the XRPL and funded
@@ -265,31 +210,37 @@ async function processSuccessfulResponse(
)
if (updatedBalance > startingBalance) {
resolve({
return {
wallet: walletToFund,
balance: await getUpdatedBalance(
client,
walletToFund.classicAddress,
startingBalance,
),
})
} else {
reject(
new XRPLFaucetError(
`Unable to fund address with faucet after waiting ${
INTERVAL_SECONDS * MAX_ATTEMPTS
} seconds`,
),
)
balance: updatedBalance,
}
}
throw new XRPLFaucetError(
`Unable to fund address with faucet after waiting ${
INTERVAL_SECONDS * MAX_ATTEMPTS
} seconds`,
)
} catch (err) {
if (err instanceof Error) {
reject(new XRPLFaucetError(err.message))
throw new XRPLFaucetError(err.message)
}
reject(err)
throw err
}
}
async function processError(response: Response): Promise<never> {
return Promise.reject(
new XRPLFaucetError(
`Request failed: ${JSON.stringify({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- json response could be anything
body: (await response.json()) || {},
contentType: response.headers.get('Content-Type'),
statusCode: response.status,
})}`,
),
)
}
/**
* Check at regular interval if the address is enabled on the XRPL and funded.
*

View File

@@ -6,7 +6,7 @@ import { Client, ClientOptions } from '.'
* @deprecated since version 2.2.0.
* Will be deleted in version 3.0.0.
*
* Currently this implementation does not provide better reliability.
* Currently, this implementation does not provide better reliability.
* To get better reliability, implement reconnect/error handling logic
* and choose a reliable endpoint.
*

View File

@@ -11,6 +11,7 @@ export { default as ECDSA } from './ECDSA'
export * from './errors'
export { default as fundWallet, FundingOptions } from './Wallet/fundWallet'
export { Wallet } from './Wallet'
export { walletFromSecretNumbers } from './Wallet/walletFromSecretNumbers'

View File

@@ -43,8 +43,8 @@ async function generate_faucet_wallet_and_fund_again(
account: wallet.classicAddress,
})
assert.equal(dropsToXrp(afterSent.result.account_data.Balance), newBalance)
assert(newBalance > balance)
assert.equal(dropsToXrp(afterSent.result.account_data.Balance), newBalance)
await api.disconnect()
}

View File

@@ -104,12 +104,9 @@ function webpackForTest(testFileName) {
fs: require.resolve('browserify-fs'),
buffer: require.resolve('buffer/'),
assert: require.resolve('assert/'),
url: require.resolve('url/'),
stream: require.resolve('stream-browserify'),
crypto: require.resolve('crypto-browserify'),
path: require.resolve('path-browserify'),
http: require.resolve('stream-http'),
https: require.resolve('https-browserify'),
},
},
}

View File

@@ -65,11 +65,8 @@ function getDefaultConfiguration() {
fallback: {
buffer: require.resolve('buffer/'),
assert: require.resolve('assert/'),
url: require.resolve('url/'),
stream: require.resolve('stream-browserify'),
crypto: require.resolve('crypto-browserify'),
https: require.resolve('https-browserify'),
http: require.resolve('stream-http'),
},
},
}