From 197264ddb0d700502392658dae5bcaef4b84af9f Mon Sep 17 00:00:00 2001 From: Jackson Mills Date: Mon, 23 May 2022 12:12:30 -0700 Subject: [PATCH] Add alias for fundWallet, add error, and update doc --- packages/xrpl/src/Wallet/fundWallet.ts | 28 +++++++++---- packages/xrpl/src/Wallet/index.ts | 29 ++++++++++++++ packages/xrpl/test/integration/fundWallet.ts | 41 ++++++++++++++++++++ 3 files changed, 90 insertions(+), 8 deletions(-) diff --git a/packages/xrpl/src/Wallet/fundWallet.ts b/packages/xrpl/src/Wallet/fundWallet.ts index 10c24cc1..842d6a3f 100644 --- a/packages/xrpl/src/Wallet/fundWallet.ts +++ b/packages/xrpl/src/Wallet/fundWallet.ts @@ -29,7 +29,8 @@ const INTERVAL_SECONDS = 1 const MAX_ATTEMPTS = 20 /** - * Generates a random wallet with some amount of XRP (usually 1000 XRP). + * Only usable on test networks. + * Fills this wallet with some amount of XRP (usually 1000 XRP). * * @example * ```typescript @@ -41,14 +42,14 @@ 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 and - * 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. - * @returns A Wallet on the Testnet or Devnet that contains some amount of XRP, + * @param options.faucetHost - A custom host for a faucet server. `fundWallet` will automatically + * determine the correct server for devnet and testnet as long as `faucetHost` is null or undefined. + * In other environments, you should provide the host using this option. + * Here's an example of how to format `faucetHost`: `faucet.devnet.rippletest.net` + * @returns A Wallet on a test network 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. + * @throws When the Client isn't connected, when it is unable to fund the wallet address, + * or if `faucetHost` is incorrectly formatted. */ async function fundWallet( this: Client, @@ -88,6 +89,17 @@ async function fundWallet( /* startingBalance remains '0' */ } + if ( + options?.faucetHost != null && + (options.faucetHost.startsWith('ws://') || + options.faucetHost.startsWith('wss://') || + options.faucetHost.startsWith('http://') || + options.faucetHost.startsWith('https://')) + ) { + throw new XRPLFaucetError( + `Invalid format for faucetHost. Should not include ws(s)/http(s) prefix. Received '${options.faucetHost}'.`, + ) + } // Options to pass to https.request const httpOptions = getHTTPOptions(this, postBody, options?.faucetHost) diff --git a/packages/xrpl/src/Wallet/index.ts b/packages/xrpl/src/Wallet/index.ts index 189aeaad..30118288 100644 --- a/packages/xrpl/src/Wallet/index.ts +++ b/packages/xrpl/src/Wallet/index.ts @@ -23,6 +23,7 @@ import { sign, } from 'ripple-keypairs' +import { Client } from '../client' import ECDSA from '../ECDSA' import { ValidationError } from '../errors' import { Transaction } from '../models/transactions' @@ -382,6 +383,34 @@ class Wallet { return classicAddressToXAddress(this.classicAddress, tag, isTestnet) } + /** + * Only usable on test networks. + * Funds an existing wallet using a faucet. + * This is an alias for Client.fundWallet() + * + * @param this - An existing XRPL Wallet to fund. + * @param client - An XRPL client. + * @param options - See below. + * @param options.faucetHost - A custom host for a faucet server. `fundWallet` will automatically + * determine the correct server for devnet and testnet as long as `faucetHost` is null or undefined. + * In other environments, you should provide the host using this option. + * Here's an example of how to format `faucetHost`: `faucet.devnet.rippletest.net` + * @returns This wallet and that its new balance in XRP. + * @throws When either Client isn't connected or unable to fund wallet address. + */ + public async fundWallet( + this: Wallet, + client: Client, + options?: { + faucetHost?: string + }, + ): Promise<{ + wallet: Wallet + balance: number + }> { + return client.fundWallet(this, options) + } + /** * Decode a serialized transaction, remove the fields that are added during the signing process, * and verify that it matches the transaction prior to signing. This gives the user a sanity check diff --git a/packages/xrpl/test/integration/fundWallet.ts b/packages/xrpl/test/integration/fundWallet.ts index 05282c1d..d9829a77 100644 --- a/packages/xrpl/test/integration/fundWallet.ts +++ b/packages/xrpl/test/integration/fundWallet.ts @@ -69,6 +69,47 @@ describe('fundWallet', function () { await api.disconnect() }) + it('can fund an existing Wallet using the Wallet alias', async function () { + const api = new Client('wss://s.devnet.rippletest.net:51233') + + await api.connect() + const { wallet, balance } = await api.fundWallet() + + assert.notEqual(wallet, undefined) + assert(isValidClassicAddress(wallet.classicAddress)) + assert(isValidXAddress(wallet.getXAddress())) + + const info = await api.request({ + command: 'account_info', + account: wallet.classicAddress, + }) + + assert.equal(dropsToXrp(info.result.account_data.Balance), balance) + + const { balance: newBalance } = await wallet.fundWallet(api) + + const afterSent = await api.request({ + command: 'account_info', + account: wallet.classicAddress, + }) + assert.equal(dropsToXrp(afterSent.result.account_data.Balance), newBalance) + + await api.disconnect() + }) + + it('throws when given an incorrectly formatted faucetHost', async function () { + const api = new Client('ws://xls20-sandbox.rippletest.net:51233') + + await api.connect() + assert.throws(async () => + api.fundWallet(null, { + faucetHost: 'https://faucet-nft.ripple.com/', + }), + ) + + await api.disconnect() + }) + it('can generate and fund wallets using a custom host', async function () { const api = new Client('ws://xls20-sandbox.rippletest.net:51233')