diff --git a/src/types/ripple-binary-codec/index.d.ts b/@types/ripple-binary-codec/index.d.ts similarity index 100% rename from src/types/ripple-binary-codec/index.d.ts rename to @types/ripple-binary-codec/index.d.ts diff --git a/src/Common/utils.ts b/src/Common/utils.ts index fb80e76b..7b181e8e 100644 --- a/src/Common/utils.ts +++ b/src/Common/utils.ts @@ -24,7 +24,7 @@ export interface ClassicAddress { test: boolean } -abstract class Utils { +const utils = { /** * Validate that the given string is a valid address for the XRP Ledger. * @@ -34,12 +34,12 @@ abstract class Utils { * @param address - An address to check. * @returns True if the address is valid, otherwise false. */ - public static isValidAddress(address: string): boolean { + isValidAddress(address: string): boolean { return ( addressCodec.isValidClassicAddress(address) || addressCodec.isValidXAddress(address) ) - } + }, /** * Validate whether the given string is a valid X-address for the XRP Ledger. @@ -49,9 +49,9 @@ abstract class Utils { * @param address - An address to check. * @returns True if the address is a valid X-address, otherwise false. */ - public static isValidXAddress(address: string): boolean { + isValidXAddress(address: string): boolean { return addressCodec.isValidXAddress(address) - } + }, /** * Validate whether the given string is a valid classic address for the XRP Ledger. @@ -61,9 +61,9 @@ abstract class Utils { * @param address - An address to check. * @returns True if the address is a valid classic address, otherwise false. */ - public static isValidClassicAddress(address: string): boolean { + isValidClassicAddress(address: string): boolean { return addressCodec.isValidClassicAddress(address) - } + }, /** * Encode the given classic address and tag into an x-address. @@ -75,7 +75,7 @@ abstract class Utils { * @param test - Whether the address is for use on a test network, defaults to `false`. * @returns A new x-address if inputs were valid, otherwise undefined. */ - public static encodeXAddress( + encodeXAddress( classicAddress: string, tag: number | undefined, test = false, @@ -85,13 +85,13 @@ abstract class Utils { } // Xpring Common JS's API takes a string|undefined while the underlying address library wants string|false. - const shimTagParameter = tag !== undefined ? tag : false + const shimTagParameter = tag ?? false return addressCodec.classicAddressToXAddress( classicAddress, shimTagParameter, test, ) - } + }, /** * Decode a `ClassicAddress` from a given x-address. @@ -101,7 +101,7 @@ abstract class Utils { * @param xAddress - The xAddress to decode. * @returns A `ClassicAddress` */ - public static decodeXAddress(xAddress: string): ClassicAddress | undefined { + decodeXAddress(xAddress: string): ClassicAddress | undefined { if (!addressCodec.isValidXAddress(xAddress)) { return undefined } @@ -110,10 +110,10 @@ abstract class Utils { return { address: shimClassicAddress.classicAddress, tag: - shimClassicAddress.tag !== false ? shimClassicAddress.tag : undefined, + shimClassicAddress.tag === false ? undefined : shimClassicAddress.tag, test: shimClassicAddress.test, } - } + }, /** * Convert the given byte array to a hexadecimal string. @@ -121,9 +121,9 @@ abstract class Utils { * @param bytes - An array of bytes * @returns An encoded hexadecimal string. */ - public static toHex(bytes: Uint8Array): string { + toHex(bytes: Uint8Array): string { return Buffer.from(bytes).toString('hex').toUpperCase() - } + }, /** * Convert the given hexadecimal string to a byte array. @@ -131,9 +131,9 @@ abstract class Utils { * @param hex - A hexadecimal string. * @returns A decoded byte array. */ - public static toBytes(hex: string): Uint8Array { + toBytes(hex: string): Uint8Array { return Uint8Array.from(Buffer.from(hex, 'hex')) - } + }, /** * Convert the given transaction blob to a transaction hash. @@ -141,10 +141,10 @@ abstract class Utils { * @param transactionBlobHex - A hexadecimal encoded transaction blob. * @returns A hex encoded hash if the input was valid, otherwise undefined. */ - public static transactionBlobToTransactionHash( + transactionBlobToTransactionHash( transactionBlobHex: string, ): string | undefined { - if (!Utils.isHex(transactionBlobHex)) { + if (!this.isHex(transactionBlobHex)) { return undefined } @@ -153,7 +153,7 @@ abstract class Utils { ) const hash = this.sha512Half(prefixedTransactionBlob) return this.toHex(hash) - } + }, /** * Check if the given string is valid hex. @@ -161,10 +161,10 @@ abstract class Utils { * @param input - The input to check. * @returns true if the input is valid hex, otherwise false. */ - public static isHex(input: string): boolean { + isHex(input: string): boolean { const hexRegEx = /(?:[0-9]|[a-f])/gimu return (input.match(hexRegEx) ?? []).length === input.length - } + }, /** * Compute the SHA512 half hash of the given bytes. @@ -172,13 +172,13 @@ abstract class Utils { * @param input - The input to hash. * @returns The hash of the input. */ - private static sha512Half(bytes: Uint8Array): Uint8Array { + sha512Half(bytes: Uint8Array): Uint8Array { const sha512 = createHash('sha512') const hashHex = sha512.update(bytes).digest('hex').toUpperCase() const hash = this.toBytes(hashHex) return hash.slice(0, hash.length / 2) - } + }, } -export default Utils +export default utils diff --git a/src/PayID/pay-id-components.ts b/src/PayID/pay-id-components.ts index 575c3c85..cd457195 100644 --- a/src/PayID/pay-id-components.ts +++ b/src/PayID/pay-id-components.ts @@ -6,16 +6,19 @@ * A class which encapsulates components of a Pay ID. */ export default class PayIdComponents { + public readonly host: string + public readonly path: string + /** * Create a new PayIdComponents. * * @param host - The host of the payment pointer. * @param path - The path of the payment pointer, starting with a leading '/'. */ - public constructor( - public readonly host: string, - public readonly path: string, - ) {} + public constructor(host: string, path: string) { + this.host = host + this.path = path + } } /** @@ -24,14 +27,16 @@ export default class PayIdComponents { * @deprecated Please use the idiomatically named `PayIdComponents` class instead. */ export class PayIDComponents { + public readonly host: string + public readonly path: string /** * Create a new PayIDComponents. * * @param host - The host of the payment pointer. * @param path - The path of the payment pointer, starting with a leading '/'. */ - public constructor( - public readonly host: string, - public readonly path: string, - ) {} + public constructor(host: string, path: string) { + this.host = host + this.path = path + } } diff --git a/src/PayID/pay-id-utils.ts b/src/PayID/pay-id-utils.ts index f0123bf5..2b292301 100644 --- a/src/PayID/pay-id-utils.ts +++ b/src/PayID/pay-id-utils.ts @@ -1,39 +1,37 @@ // Disable multiple classes to accommodate the switch to idiomatic style naming. -// TODO(keefertaylor): Remove this when migration is complete. -/* eslint-disable max-classes-per-file */ - +/* eslint-disable import/no-deprecated */ import PayIdComponents, { PayIDComponents } from './pay-id-components' /** * A static utility class for Pay ID functionality. */ -export default class PayIdUtils { +const payIdUtils = { /** * Parse a PayID string to a set of PayIDComponents object * - * @param parsePayID - The input Pay ID. + * @param payID - The input Pay ID. * @returns A PayIDComponents object if the input was valid, otherwise undefined. */ - public static parsePayID(payID: string): PayIdComponents | undefined { - if (!PayIdUtils.isASCII(payID)) { - return + parsePayID(payID: string): PayIdComponents | undefined { + if (!this.isASCII(payID)) { + return undefined } // Validate there are two components of a payment pointer. const components = payID.split('$') if (components.length !== 2) { - return + return undefined } // Validate the host and path have values. const path = components[0] const host = components[1] if (host.length === 0 || path.length === 0) { - return + return undefined } return new PayIdComponents(host, `/${path}`) - } + }, /** * Validate if the input is ASCII based text. @@ -44,18 +42,20 @@ export default class PayIdUtils { * @param input - The input to check * @returns A boolean indicating the result. */ - private static isASCII(input: string): boolean { + isASCII(input: string): boolean { // eslint-disable-next-line no-control-regex return /^[\x00-\x7F]*$/u.test(input) - } + }, } +export default payIdUtils /** * A static utility class for PayID. * * @deprecated Please use the idiomatically named `PayIdUtils` class instead. */ -export class PayIDUtils { +// eslint-disable-next-line @typescript-eslint/no-extraneous-class +export abstract class PayIDUtils { /** * Parse a PayID string to a set of PayIDComponents object * @@ -63,13 +63,9 @@ export class PayIDUtils { * @returns A PayIDComponents object if the input was valid, otherwise undefined. */ public static parsePayID(payID: string): PayIDComponents | undefined { - const components = PayIdUtils.parsePayID(payID) - return components !== undefined - ? new PayIDComponents(components?.host, components?.path) + const components = payIdUtils.parsePayID(payID) + return components + ? new PayIDComponents(components.host, components.path) : undefined } - - /** Please do not instantiate this static utility class. */ - // eslint-disable-next-line @typescript-eslint/no-empty-function - private constructor() {} } diff --git a/src/XRP/serializer.ts b/src/XRP/serializer.ts index 92dfddaa..cdeeadc9 100644 --- a/src/XRP/serializer.ts +++ b/src/XRP/serializer.ts @@ -34,7 +34,7 @@ export type TransactionJSON = BaseTransactionJSON | PaymentTransactionJSON /** * Provides functionality to serialize from protocol buffers to JSON objects. */ -abstract class Serializer { +const serializer = { /** * Convert a Transaction to a JSON representation. * @@ -42,7 +42,7 @@ abstract class Serializer { * @param signature - An optional hex encoded signature to include in the transaction. * @returns The Transaction as JSON. */ - public static transactionToJSON( + transactionToJSON( transaction: Transaction, signature?: string, ): TransactionJSON | undefined { @@ -74,23 +74,23 @@ abstract class Serializer { // Convert account field, handling X-Addresses if needed. const accountAddress = transaction.getAccount() if (!accountAddress) { - return + return undefined } const account = accountAddress.getValue()?.getAddress() if (!account || !Utils.isValidAddress(account)) { - return + return undefined } let normalizedAccount = account if (Utils.isValidXAddress(account)) { const decodedClassicAddress = Utils.decodeXAddress(account) if (!decodedClassicAddress) { - return + return undefined } // Accounts cannot have a tag. if (decodedClassicAddress.tag !== undefined) { - return + return undefined } normalizedAccount = decodedClassicAddress.address @@ -100,7 +100,7 @@ abstract class Serializer { // Convert XRP denominated fee field. const txFee = transaction.getFee() if (txFee === undefined) { - return + return undefined } object.Fee = this.xrpAmountToJSON(txFee) @@ -110,7 +110,7 @@ abstract class Serializer { case Transaction.TransactionDataCase.PAYMENT: { const payment = transaction.getPayment() if (payment === undefined) { - return + return undefined } Object.assign(object, this.paymentToJSON(payment)) break @@ -124,7 +124,7 @@ abstract class Serializer { } return object - } + }, /** * Convert a Payment to a JSON representation. @@ -132,7 +132,7 @@ abstract class Serializer { * @param payment - The Payment to convert. * @returns The Payment as JSON. */ - private static paymentToJSON(payment: Payment): object | undefined { + paymentToJSON(payment: Payment): object | undefined { const json: PaymentJSON = { Amount: {}, Destination: '', @@ -142,36 +142,36 @@ abstract class Serializer { // If an x-address was able to be decoded, add the components to the json. const destinationAddress = payment.getDestination() if (!destinationAddress) { - return + return undefined } const destination = destinationAddress.getValue()?.getAddress() if (!destination) { - return + return undefined } const decodedXAddress = Utils.decodeXAddress(destination) - if (!decodedXAddress) { - json.Destination = destination - delete json.DestinationTag - } else { + if (decodedXAddress) { json.Destination = decodedXAddress.address if (decodedXAddress.tag !== undefined) { json.DestinationTag = decodedXAddress.tag } + } else { + json.Destination = destination + delete json.DestinationTag } const amount = payment.getAmount() if (!amount) { - return + return undefined } const xrpAmount = amount.getValue()?.getXrpAmount() if (!xrpAmount) { - return + return undefined } json.Amount = this.xrpAmountToJSON(xrpAmount) return json - } + }, /** * Convert an XRPDropsAmount to a JSON representation. @@ -179,9 +179,9 @@ abstract class Serializer { * @param xrpDropsAmount - The XRPAmount to convert. * @returns The XRPAmount as JSON. */ - private static xrpAmountToJSON(xrpDropsAmount: XRPDropsAmount): string { + xrpAmountToJSON(xrpDropsAmount: XRPDropsAmount): string { return `${xrpDropsAmount.getDrops()}` - } + }, } -export default Serializer +export default serializer diff --git a/src/XRP/signer.ts b/src/XRP/signer.ts index e5cdf032..75a47f2b 100644 --- a/src/XRP/signer.ts +++ b/src/XRP/signer.ts @@ -9,7 +9,7 @@ import Wallet from './wallet' /** * Abstracts the details of signing. */ -abstract class Signer { +const signer = { /** * Encode the given raw JSON transaction to hex and sign it. * @@ -17,7 +17,7 @@ abstract class Signer { * @param wallet - The wallet to sign the transaction with. * @returns A set of bytes representing the inputs and a signature. */ - public static signTransactionFromJSON( + signTransactionFromJSON( transactionJSON: TransactionJSON, wallet: Wallet, ): Uint8Array { @@ -34,7 +34,7 @@ abstract class Signer { } const signedTransactionHex = rippleCodec.encode(signedTransactionJSON) return Utils.toBytes(signedTransactionHex) - } + }, /** * Encode the given object to hex and sign it. @@ -43,7 +43,7 @@ abstract class Signer { * @param wallet - The wallet to sign the transaction with. * @returns A set of bytes representing the inputs and a signature. */ - public static signTransaction( + signTransaction( transaction: Transaction, wallet: Wallet, ): Uint8Array | undefined { @@ -55,8 +55,8 @@ abstract class Signer { if (transactionJSON === undefined) { return undefined } - return Signer.signTransactionFromJSON(transactionJSON, wallet) - } + return this.signTransactionFromJSON(transactionJSON, wallet) + }, } -export default Signer +export default signer diff --git a/src/XRP/wallet.ts b/src/XRP/wallet.ts index 9ea962bb..2fa44218 100644 --- a/src/XRP/wallet.ts +++ b/src/XRP/wallet.ts @@ -27,6 +27,23 @@ export interface WalletGenerationResult { * A wallet object that has an address and keypair. */ class Wallet { + private readonly publicKey: string + private readonly privateKey: string + private readonly test: boolean + + /** + * Create a new Wallet object. + * + * @param publicKey - The given public key for the wallet. + * @param privateKey - The given private key for the wallet. + * @param test - Whether the address is for use on a test network, defaults to `false`. + */ + public constructor(publicKey: string, privateKey: string, test = false) { + this.publicKey = publicKey + this.privateKey = privateKey + this.test = test + } + /** * @returns The default derivation path. */ @@ -88,6 +105,7 @@ class Wallet { return undefined } + /* eslint-disable-next-line no-sync */ const seed = bip39.mnemonicToSeedSync(mnemonic) return Wallet.generateHDWalletFromSeed(seed, derivationPath, test) } @@ -108,7 +126,7 @@ class Wallet { const masterNode = bip32.fromSeed(seed) const node = masterNode.derivePath(derivationPath) if (node.privateKey === undefined) { - return + return undefined } const publicKey = Wallet.hexFromBuffer(node.publicKey) @@ -135,18 +153,9 @@ class Wallet { } } - /** - * Create a new Wallet object. - * - * @param publicKey - The given public key for the wallet. - * @param privateKey - The given private key for the wallet. - * @param test - Whether the address is for use on a test network, defaults to `false`. - */ - public constructor( - private readonly publicKey: string, - private readonly privateKey: string, - private readonly test: boolean = false, - ) {} + private static hexFromBuffer(buffer: Buffer): string { + return buffer.toString('hex').toUpperCase() + } /** * @returns A string representing the public key for the wallet. @@ -207,10 +216,6 @@ class Wallet { return false } } - - private static hexFromBuffer(buffer: Buffer): string { - return buffer.toString('hex').toUpperCase() - } } export default Wallet diff --git a/test/Common/utils.test.ts b/test/Common/utils.test.ts index 54ba2e43..e4b4fa98 100644 --- a/test/Common/utils.test.ts +++ b/test/Common/utils.test.ts @@ -153,6 +153,7 @@ describe('utils', function (): void { it('decodeXAddress() - Valid Mainnet Address with Tag', function (): void { // GIVEN an x-address that encodes an address and a tag. const address = 'XVfC9CTCJh6GN2x8bnrw3LtdbqiVCUvtU3HnooQDgBnUpQT' + const tag = 12345 // WHEN it is decoded to an classic address const classicAddress = Utils.decodeXAddress(address) @@ -162,13 +163,14 @@ describe('utils', function (): void { classicAddress!.address, 'rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw1', ) - assert.strictEqual(classicAddress!.tag, 12345) + assert.strictEqual(classicAddress!.tag, tag) assert.strictEqual(classicAddress!.test, false) }) it('decodeXAddress() - Valid Testnet Address with Tag', function (): void { // GIVEN an x-address that encodes an address and a tag. const address = 'TVsBZmcewpEHgajPi1jApLeYnHPJw82v9JNYf7dkGmWphmh' + const tag = 12345 // WHEN it is decoded to an classic address const classicAddress = Utils.decodeXAddress(address) @@ -178,7 +180,7 @@ describe('utils', function (): void { classicAddress!.address, 'rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw1', ) - assert.strictEqual(classicAddress!.tag, 12345) + assert.strictEqual(classicAddress!.tag, tag) assert.strictEqual(classicAddress!.test, true) }) diff --git a/test/XRP/fakes/fake-wallet.ts b/test/XRP/fakes/fake-wallet.ts index 1407f6a6..67ae4a3d 100644 --- a/test/XRP/fakes/fake-wallet.ts +++ b/test/XRP/fakes/fake-wallet.ts @@ -16,17 +16,21 @@ const defaultPrivateKey = * A fake wallet which always produces the given signature. */ class FakeWallet extends Wallet { + private readonly signature: string + /** * Initialize a wallet which will always produce the same signature when asked to sign a string. * * @param signature - The signature this wallet will produce. */ public constructor( - private readonly signature: string, + signature: string, publicKey = defaultPublicKey, privateKey = defaultPrivateKey, ) { super(publicKey, privateKey) + + this.signature = signature } /** diff --git a/test/XRP/serializer.test.ts b/test/XRP/serializer.test.ts index 8e3f90cd..91096a0b 100644 --- a/test/XRP/serializer.test.ts +++ b/test/XRP/serializer.test.ts @@ -47,6 +47,7 @@ const accountXAddress = 'X7vjQVCddnQ7GCESYnYR3EdpzbcoAMbPw7s2xv8YQs94tv4' * @param senderAddress - The address of the sending account. * @param publicKey - The public key of the sending account, encoded as a hexadecimal string. */ +/* eslint-disable no-shadow */ function makeTransaction( value: string, destinationAddress: string, @@ -107,6 +108,7 @@ function makeTransaction( return transaction } +/* eslint-enable no-shadow */ describe('serializer', function (): void { it('serializes a payment in XRP from a classic address', function (): void { diff --git a/tsconfig.json b/tsconfig.json index 95f1ebb0..9eeec1ec 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,9 +26,7 @@ "allowJs": true, "forceConsistentCasingInFileNames": true, "esModuleInterop": true, - "typeRoots": ["./src/types", "./node_modules/@types"] + "typeRoots": ["@types", "./node_modules/@types"] }, - "include": [ - "src/**/*" - ] + "include": ["src/**/*"] }