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

feat: remove lodash as a dependency #2378

Merged
merged 9 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
509 changes: 262 additions & 247 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"jest": "^29.3.1",
"jest-mock": "^29.3.1",
"lerna": "^4.0.0",
"lodash": "^4.17.21",
"npm-run-all": "^4.1.5",
"path-browserify": "1.0.1",
"prettier": "^2.3.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/xrpl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"bip32": "^2.0.6",
"bip39": "^3.0.4",
"https-proxy-agent": "^5.0.0",
"lodash": "^4.17.4",
"ripple-address-codec": "^4.3.0",
"ripple-binary-codec": "^1.7.1",
"ripple-keypairs": "^1.3.0",
Expand All @@ -43,6 +42,7 @@
"karma-chrome-launcher": "^3.1.1",
"karma-jasmine": "^5.1.0",
"karma-webpack": "^5.0.0",
"lodash": "^4.17.4",
"node-polyfill-webpack-plugin": "^2.0.1",
"react": "^18.2.0",
"typedoc": "^0.24.8"
Expand All @@ -56,7 +56,7 @@
"build:lib": "tsc --build tsconfig.build.json",
"build:web": "webpack",
"build:browserTests": "webpack --config ./test/webpack.config.js",
"analyze": "run-s build:web --analyze",
"analyze": "webpack --analyze",
"watch": "run-s build:lib --watch",
"clean": "rm -rf dist build coverage",
"docgen": "tsc --build tsconfig.docs.json && typedoc && echo js.xrpl.org >> ../../docs/CNAME",
Expand Down
2 changes: 1 addition & 1 deletion packages/xrpl/src/Wallet/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import BigNumber from 'bignumber.js'
import { fromSeed } from 'bip32'
import { mnemonicToSeedSync, validateMnemonic } from 'bip39'
import omitBy from 'lodash/omitBy'
import {
classicAddressToXAddress,
isValidXAddress,
Expand All @@ -26,6 +25,7 @@ import ECDSA from '../ECDSA'
import { ValidationError } from '../errors'
import { Transaction, validate } from '../models/transactions'
import { ensureClassicAddress } from '../sugar/utils'
import { omitBy } from '../utils/collections'
import { hashSignedTx } from '../utils/hashes/hashLedger'

import { rfc1751MnemonicToKey } from './rfc1751'
Expand Down
8 changes: 3 additions & 5 deletions packages/xrpl/src/Wallet/signer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { BigNumber } from 'bignumber.js'
import { flatMap } from 'lodash'
import { decodeAccountID } from 'ripple-address-codec'
import {
decode,
Expand Down Expand Up @@ -128,10 +127,9 @@ function getTransactionWithAllSigners(
transactions: Transaction[],
): Transaction {
// Signers must be sorted in the combined transaction - See compareSigners' documentation for more details
const sortedSigners: Signer[] = flatMap(
transactions,
(tx) => tx.Signers ?? [],
).sort(compareSigners)
const sortedSigners: Signer[] = transactions
.flatMap((tx) => tx.Signers ?? [])
.sort(compareSigners)

return { ...transactions[0], Signers: sortedSigners }
}
Expand Down
2 changes: 1 addition & 1 deletion packages/xrpl/src/client/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { EventEmitter } from 'events'
import { Agent } from 'http'

import omitBy from 'lodash/omitBy'
import WebSocket from 'ws'

import {
Expand All @@ -12,6 +11,7 @@ import {
XrplError,
} from '../errors'
import { BaseRequest } from '../models/methods/baseMethod'
import { omitBy } from '../utils/collections'

import ConnectionManager from './ConnectionManager'
import ExponentialBackoff from './ExponentialBackoff'
Expand Down
4 changes: 1 addition & 3 deletions packages/xrpl/src/sugar/balances.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import flatMap from 'lodash/flatMap'

import type { Balance, Client } from '..'
import {
AccountLinesRequest,
Expand Down Expand Up @@ -108,7 +106,7 @@ async function getBalances(
// combine results
await Promise.all([xrpPromise, linesPromise]).then(
([xrpBalance, linesResponses]) => {
const accountLinesBalance = flatMap(linesResponses, (response) =>
const accountLinesBalance = linesResponses.flatMap((response) =>
formatBalances(response.result.lines),
)
if (xrpBalance !== '') {
Expand Down
15 changes: 8 additions & 7 deletions packages/xrpl/src/sugar/getOrderbook.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable max-lines-per-function -- Needs to process orderbooks. */
import BigNumber from 'bignumber.js'
import flatMap from 'lodash/flatMap'

import type { Client } from '../client'
import { ValidationError } from '../errors'
Expand All @@ -10,6 +9,7 @@ import {
BookOffer,
BookOfferCurrency,
BookOffersRequest,
BookOffersResponse,
} from '../models/methods/bookOffers'

const DEFAULT_LIMIT = 20
Expand Down Expand Up @@ -112,17 +112,18 @@ async function getOrderbook(
taker: options.taker ? options.taker : undefined,
}
// 2. Make Request
const directOfferResults = await this.requestAll(request)
const directOfferResults: BookOffersResponse[] = await this.requestAll(
request,
)
request.taker_gets = currency1
request.taker_pays = currency2
const reverseOfferResults = await this.requestAll(request)
// 3. Return Formatted Response
const directOffers = flatMap(
directOfferResults,
(directOfferResult) => directOfferResult.result.offers,

const directOffers = directOfferResults.flatMap(
(directOfferResult: BookOffersResponse) => directOfferResult.result.offers,
)
const reverseOffers = flatMap(
reverseOfferResults,
const reverseOffers = reverseOfferResults.flatMap(
(reverseOfferResult) => reverseOfferResult.result.offers,
)

Expand Down
52 changes: 52 additions & 0 deletions packages/xrpl/src/utils/collections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
type ValueOf<T> = T[keyof T]

/**
* Creates an object composed of keys generated from the results of running each element of collection thru iteratee.
* The order of grouped values is determined by the order they occur in collection.
* The corresponding value of each key is an array of elements responsible for generating the key.
*
* Similar to lodash's groupBy
*
* @param array - array to iterate over
* @param iteratee - function that returns key of the group to place the item
*
* @returns a map of arrays
*/
export function groupBy<T>(
array: T[],
iteratee: (value: T, index: number, array: T[]) => string,
): { [p: string]: T[] } {
// eslint-disable-next-line max-params -- need all the params for the fallback
return array.reduce<{ [key: string]: T[] }>(function predicate(
acc,
value,
index,
arrayReference,
) {
;(acc[iteratee(value, index, arrayReference)] ||= []).push(value)
return acc
},
{})
}

/**
* Creates an object composed of the own and inherited enumerable string keyed properties of object that
* predicate doesn't return truthy for.
*
* @param obj - Object to have properties removed.
* @param predicate - function that returns whether the property should be removed from the obj.
*
* @returns object
*/
export function omitBy<T extends object>(
obj: T,
predicate: (objElement: ValueOf<T>, k: string | number | symbol) => boolean,
): Partial<T> {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- We know the keys are properties of T
const keys: Array<keyof T> = Object.keys(obj) as Array<keyof T>
const keysToKeep = keys.filter((kb) => !predicate(obj[kb], kb))
return keysToKeep.reduce((acc: Partial<T>, key: keyof T) => {
acc[key] = obj[key]
return acc
}, {})
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add unit tests for these helper functions?

5 changes: 2 additions & 3 deletions packages/xrpl/src/utils/getBalanceChanges.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import BigNumber from 'bignumber.js'
import flatten from 'lodash/flatten'
import groupBy from 'lodash/groupBy'

import {
Amount,
Expand All @@ -10,6 +8,7 @@ import {
Node,
} from '../models'

import { groupBy } from './collections'
import { dropsToXrp } from './xrpConversion'

interface BalanceChange {
Expand Down Expand Up @@ -182,5 +181,5 @@ export default function getBalanceChanges(
}
return []
})
return groupByAccount(flatten(quantities))
return groupByAccount(quantities.flat())
}
34 changes: 18 additions & 16 deletions packages/xrpl/src/utils/getNFTokenID.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import flatMap from 'lodash/flatMap'
import { decode } from 'ripple-binary-codec'

import { NFToken } from '../models/ledger/NFTokenPage'
Expand Down Expand Up @@ -33,6 +32,7 @@ function ensureDecodedMeta(
* @returns The NFTokenID for the minted NFT.
* @throws if meta is not TransactionMetadata.
*/
// eslint-disable-next-line max-lines-per-function -- This function has a lot of documentation
export default function getNFTokenID(
meta: TransactionMetadata | string | undefined,
): string | undefined {
Expand All @@ -57,7 +57,6 @@ export default function getNFTokenID(
* not changed. Thus why we add the additional condition to check
* if the PreviousFields contains NFTokens
*/

const affectedNodes = decodedMeta.AffectedNodes.filter((node) => {
if (isCreatedNode(node)) {
return node.CreatedNode.LedgerEntryType === 'NFTokenPage'
Expand All @@ -72,25 +71,28 @@ export default function getNFTokenID(
})
/* eslint-disable @typescript-eslint/consistent-type-assertions -- Necessary for parsing metadata */
const previousTokenIDSet = new Set(
flatMap(affectedNodes, (node) => {
const nftokens = isModifiedNode(node)
? (node.ModifiedNode.PreviousFields?.NFTokens as NFToken[])
: []
return nftokens.map((token) => token.NFToken.NFTokenID)
}).filter((id) => Boolean(id)),
affectedNodes
.flatMap((node) => {
const nftokens = isModifiedNode(node)
? (node.ModifiedNode.PreviousFields?.NFTokens as NFToken[])
: []
return nftokens.map((token) => token.NFToken.NFTokenID)
})
.filter((id) => Boolean(id)),
)

/* eslint-disable @typescript-eslint/no-unnecessary-condition -- Cleaner to read */
const finalTokenIDs = flatMap(affectedNodes, (node) =>
(
(((node as ModifiedNode).ModifiedNode?.FinalFields?.NFTokens ??
(node as CreatedNode).CreatedNode?.NewFields?.NFTokens) as NFToken[]) ??
[]
).map((token) => token.NFToken.NFTokenID),
).filter((nftokenID) => Boolean(nftokenID))
const finalTokenIDs = affectedNodes
.flatMap((node) =>
(
(((node as ModifiedNode).ModifiedNode?.FinalFields?.NFTokens ??
(node as CreatedNode).CreatedNode?.NewFields
?.NFTokens) as NFToken[]) ?? []
).map((token) => token.NFToken.NFTokenID),
)
.filter((nftokenID) => Boolean(nftokenID))
/* eslint-enable @typescript-eslint/consistent-type-assertions -- Necessary for parsing metadata */
/* eslint-enable @typescript-eslint/no-unnecessary-condition -- Cleaner to read */

const nftokenID = finalTokenIDs.find((id) => !previousTokenIDSet.has(id))

return nftokenID
Expand Down
1 change: 1 addition & 0 deletions packages/xrpl/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"compilerOptions": {
"pretty": true,
"target": "es6",
"lib": ["es2019", "dom"],
"outDir": "./dist/npm",
"declaration": true,
"declarationMap": true,
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"compilerOptions": {
"composite": true,
"module": "commonjs",
"lib": ["es2019", "dom"],
"moduleResolution": "node",
"esModuleInterop": true,
"sourceMap": true,
Expand Down