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

Fix: parseTransactionFlags unintentionally modifies transaction #2825

Merged
merged 32 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
863e048
remove setTransactions and any reference to modifying a transaction p…
achowdhry-ripple Nov 13, 2024
95f46ce
remove use of setter in autofill
achowdhry-ripple Nov 13, 2024
0f3e67d
changelog and test fixes
achowdhry-ripple Nov 13, 2024
bf4a4ab
add back deprecated function with warnings
achowdhry-ripple Nov 13, 2024
3611629
add new helper function to exported
achowdhry-ripple Nov 13, 2024
951ba19
update readme with deprecated
achowdhry-ripple Nov 13, 2024
803b27d
remove references to deprecated setter
achowdhry-ripple Nov 13, 2024
4078fb8
fix changelog syntax
achowdhry-ripple Nov 13, 2024
a1dcfe2
revert to test old functions
achowdhry-ripple Nov 13, 2024
1a2d37f
lint
achowdhry-ripple Nov 13, 2024
4b872ab
lint for deprecation
achowdhry-ripple Nov 13, 2024
c08214d
Merge branch 'main' into parse-transaction-flags-bug
achowdhry-ripple Nov 25, 2024
fa078fd
remove unsafe assertions
achowdhry-ripple Dec 20, 2024
73eda68
separate null check
achowdhry-ripple Dec 23, 2024
501b845
clean up tests
achowdhry-ripple Dec 23, 2024
89375a1
remove outdated logic
achowdhry-ripple Jan 3, 2025
30431b0
fix history md
achowdhry-ripple Jan 3, 2025
0f5c9d0
Merge branch 'main' into parse-transaction-flags-bug
achowdhry-ripple Jan 3, 2025
583413f
fix tests after merge conflicts
achowdhry-ripple Jan 3, 2025
517a034
Update packages/xrpl/HISTORY.md
achowdhry-ripple Jan 16, 2025
86138cc
Update packages/xrpl/src/models/utils/flags.ts
achowdhry-ripple Jan 16, 2025
fc3a79f
Update packages/xrpl/src/models/utils/flags.ts
achowdhry-ripple Jan 16, 2025
128dc20
Update packages/xrpl/src/models/utils/flags.ts
achowdhry-ripple Jan 16, 2025
904c5e0
Update packages/xrpl/src/models/utils/flags.ts
achowdhry-ripple Jan 16, 2025
642d313
Update packages/xrpl/src/models/utils/flags.ts
achowdhry-ripple Jan 16, 2025
37b99af
Update packages/xrpl/src/models/utils/flags.ts
achowdhry-ripple Jan 16, 2025
e501f0c
Update packages/xrpl/src/models/utils/flags.ts
achowdhry-ripple Jan 16, 2025
dad7c29
Update packages/xrpl/src/models/utils/flags.ts
achowdhry-ripple Jan 16, 2025
5a77c62
Update packages/xrpl/test/models/utils.test.ts
achowdhry-ripple Jan 16, 2025
127e216
rename a test per pr comment
achowdhry-ripple Jan 16, 2025
fb67a10
lint fixes
achowdhry-ripple Jan 16, 2025
eb98875
Update packages/xrpl/test/models/utils.test.ts
achowdhry-ripple Jan 16, 2025
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
8 changes: 7 additions & 1 deletion packages/xrpl/HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xrpl-announce) for release announcements. We recommend that xrpl.js (ripple-lib) users stay up-to-date with the latest stable release.

## Unreleased Changes
## Unreleased
ckeshava marked this conversation as resolved.
Show resolved Hide resolved

### Added
* `convertTxFlagsToNumber` as a utility function in xrpl to return the number conversion of a transaction's flags
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved

### Changed
* Deprecated `setTransactionFlagsToNumber`. Start using convertTxFlagsToNumber instead

## 4.1.0 (2024-12-23)

Expand Down
4 changes: 2 additions & 2 deletions packages/xrpl/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import type {
OnEventToListenerMap,
} from '../models/methods/subscribe'
import type { SubmittableTransaction } from '../models/transactions'
import { setTransactionFlagsToNumber } from '../models/utils/flags'
import { convertTxFlagsToNumber } from '../models/utils/flags'
import {
ensureClassicAddress,
submitRequest,
Expand Down Expand Up @@ -665,7 +665,7 @@ class Client extends EventEmitter<EventTypes> {
const tx = { ...transaction }

setValidAddresses(tx)
setTransactionFlagsToNumber(tx)
tx.Flags = convertTxFlagsToNumber(tx)

const promises: Array<Promise<void>> = []
if (tx.NetworkID == null) {
Expand Down
3 changes: 2 additions & 1 deletion packages/xrpl/src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
*/
export * as LedgerEntry from './ledger'
export {
setTransactionFlagsToNumber,
parseAccountRootFlags,
setTransactionFlagsToNumber,
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
convertTxFlagsToNumber,
parseTransactionFlags,
} from './utils/flags'
export * from './methods'
Expand Down
4 changes: 2 additions & 2 deletions packages/xrpl/src/models/transactions/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { ValidationError } from '../../errors'
import { IssuedCurrencyAmount, Memo } from '../common'
import { isHex } from '../utils'
import { setTransactionFlagsToNumber } from '../utils/flags'
import { convertTxFlagsToNumber } from '../utils/flags'

import { AccountDelete, validateAccountDelete } from './accountDelete'
import { AccountSet, validateAccountSet } from './accountSet'
Expand Down Expand Up @@ -255,7 +255,7 @@ export function validate(transaction: Record<string, unknown>): void {
})

// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- okay here
setTransactionFlagsToNumber(tx as unknown as Transaction)
tx.Flags = convertTxFlagsToNumber(tx as unknown as Transaction)
switch (tx.TransactionType) {
case 'AMMBid':
validateAMMBid(tx)
Expand Down
94 changes: 59 additions & 35 deletions packages/xrpl/src/models/utils/flags.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable no-param-reassign -- param reassign is safe */
/* eslint-disable no-bitwise -- flags require bitwise operations */
import { ValidationError } from '../../errors'
import {
Expand All @@ -8,7 +7,6 @@ import {
import { AccountSetTfFlags } from '../transactions/accountSet'
import { AMMDepositFlags } from '../transactions/AMMDeposit'
import { AMMWithdrawFlags } from '../transactions/AMMWithdraw'
import { GlobalFlags } from '../transactions/common'
import { MPTokenAuthorizeFlags } from '../transactions/MPTokenAuthorize'
import { MPTokenIssuanceCreateFlags } from '../transactions/MPTokenIssuanceCreate'
import { MPTokenIssuanceSetFlags } from '../transactions/MPTokenIssuanceSet'
Expand Down Expand Up @@ -63,37 +61,61 @@ const txToFlag = {
XChainModifyBridge: XChainModifyBridgeFlags,
}

function istxToFlagKey(
transactionType: string,
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
): transactionType is keyof typeof txToFlag {
return transactionType in txToFlag
}

/**
* Sets a transaction's flags to its numeric representation.
*
* @deprecated
* This utility function is deprecated.
* Use convertTxFlagsToNumber() instead and use the returned value to modify the tx.Flags from the caller.
*
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
* @param tx - A transaction to set its flags to its numeric representation.
*/
export function setTransactionFlagsToNumber(tx: Transaction): void {
if (tx.Flags == null) {
tx.Flags = 0
return
// eslint-disable-next-line no-console -- intended deprecation warning
console.warn(
'This function is deprecated. Use convertTxFlagsToNumber() instead and use the returned value to modify the tx.Flags from the caller.',
)
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved

achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
if (tx.Flags) {
// eslint-disable-next-line no-param-reassign -- intended param reassign in setter, retain old functionality for compatibility
tx.Flags = convertTxFlagsToNumber(tx)
}
}

/**
* Returns a transaction's flags as its numeric representation.
*
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
* @param tx - A transaction to parse flags for
* @returns A numerical representation of a transaction's flags
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
*/
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
export function convertTxFlagsToNumber(tx: Transaction): number {
if (!tx.Flags) {
return 0
}
if (typeof tx.Flags === 'number') {
return
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
ckeshava marked this conversation as resolved.
Show resolved Hide resolved
return tx.Flags
}

tx.Flags = txToFlag[tx.TransactionType]
? convertFlagsToNumber(tx.Flags, txToFlag[tx.TransactionType])
: 0
}
if (istxToFlagKey(tx.TransactionType)) {
const flagEnum = txToFlag[tx.TransactionType]
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
return Object.keys(tx.Flags).reduce((resultFlags, flag) => {
if (flagEnum[flag] == null) {
throw new ValidationError(
`flag ${flag} doesn't exist in flagEnum: ${JSON.stringify(flagEnum)}`,
)
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any -- added ValidationError check for flagEnum
function convertFlagsToNumber(flags: GlobalFlags, flagEnum: any): number {
return Object.keys(flags).reduce((resultFlags, flag) => {
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- safe member access
if (flagEnum[flag] == null) {
throw new ValidationError(
`flag ${flag} doesn't exist in flagEnum: ${JSON.stringify(flagEnum)}`,
)
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- safe member access
return flags[flag] ? resultFlags | flagEnum[flag] : resultFlags
}, 0)
return tx.Flags?.[flag] ? resultFlags | flagEnum[flag] : resultFlags
}, 0)
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
}

return 0
}

/**
Expand All @@ -103,22 +125,24 @@ function convertFlagsToNumber(flags: GlobalFlags, flagEnum: any): number {
* @returns A map with all flags as booleans.
*/
export function parseTransactionFlags(tx: Transaction): object {
setTransactionFlagsToNumber(tx)
if (typeof tx.Flags !== 'number' || !tx.Flags || tx.Flags === 0) {
const flags = convertTxFlagsToNumber(tx)
if (flags === 0) {
return {}
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
}

const flags = tx.Flags
const flagsMap = {}
const booleanFlagMap = {}

// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- safe member access
const flagEnum = txToFlag[tx.TransactionType]
Object.values(flagEnum).forEach((flag) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- safe member access
if (typeof flag === 'string' && isFlagEnabled(flags, flagEnum[flag])) {
flagsMap[flag] = true
}
})
if (istxToFlagKey(tx.TransactionType)) {
const transactionTypeFlags = txToFlag[tx.TransactionType]
Object.values(transactionTypeFlags).forEach((flag) => {
if (
typeof flag === 'string' &&
isFlagEnabled(flags, transactionTypeFlags[flag])
) {
booleanFlagMap[flag] = true
}
achowdhry-ripple marked this conversation as resolved.
Show resolved Hide resolved
})
}

return flagsMap
return booleanFlagMap
}
Loading
Loading