Skip to content

Commit

Permalink
fix: update the containsDuplicates method to handle nested objects
Browse files Browse the repository at this point in the history
  • Loading branch information
ckeshava committed Jan 16, 2025
1 parent 98d9513 commit da655b2
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 3 deletions.
32 changes: 29 additions & 3 deletions packages/xrpl/src/models/transactions/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
MPTAmount,
} from '../common'
import { onlyHasFields } from '../utils'
import { assert } from 'chai'

const MEMO_SIZE = 3
const MAX_CREDENTIALS_LIST_LENGTH = 8
Expand Down Expand Up @@ -511,7 +512,32 @@ export function validateCredentialsList(
* @param objectList - Array of objects to check for duplicates
* @returns True if duplicates exist, false otherwise
*/
export function containsDuplicates(objectList: object[]): boolean {
const objSet = new Set(objectList.map((obj) => JSON.stringify(obj)))
return objSet.size !== objectList.length
export function containsDuplicates(
objectList: AuthorizeCredential[] | string[],
): boolean {
let objSet: Set<string | object>
// Case-1: Process a list of string-IDs
if (typeof objectList[0] === 'string') {
objSet = new Set(objectList.map((obj) => JSON.stringify(obj)))
return objSet.size !== objectList.length
} else {
// Case-2: Process a list of nested objects
const seen = new Set<string>();
for (const item of objectList) {
let key: string;
assert(typeof item === 'object')
assert('Credential' in item)
assert('Issuer' in item.Credential && 'CredentialType' in item.Credential)
key = `${item.Credential.Issuer}-${item.Credential.CredentialType}`;

if (seen.has(key)) {
// Found a duplicate
return true;
}

seen.add(key);
}

return false
}
}
36 changes: 36 additions & 0 deletions packages/xrpl/test/models/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import {
TrustSet,
TrustSetFlags,
} from '../../src'
import { AuthorizeCredential } from '../../src/models/common'
import { AccountRootFlags } from '../../src/models/ledger'
import { containsDuplicates } from '../../src/models/transactions/common'
import { isFlagEnabled } from '../../src/models/utils'
import {
setTransactionFlagsToNumber,
Expand All @@ -26,6 +28,40 @@ import {
* Provides tests for utils used in models.
*/
describe('Models Utils', function () {
describe('validate containsDuplicates utility method', function () {
it(`use nested-objects for input parameters`, function () {
const list_without_dups: AuthorizeCredential[] = [
{ Credential: { Issuer: 'alice', CredentialType: 'Passport' } },
{ Credential: { CredentialType: 'DMV_license', Issuer: 'bob' } },
]

// changing the order of the inner-objects in the list
const list_with_duplicates: AuthorizeCredential[] = [
{ Credential: { Issuer: 'alice', CredentialType: 'Passport' } },
{ Credential: { CredentialType: 'Passport', Issuer: 'alice' } },
]

assert.isFalse(containsDuplicates(list_without_dups))
assert.isTrue(containsDuplicates(list_with_duplicates))
})

it(`use string-IDs for input parameters`, function () {
const list_without_dups: string[] = [
'EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A',
'F9F89FBB1426210D58D6A06E5EEF1783D6A90EE403B79AEDF0FED36A6DE238D2',
'5328F2D1D6EBBC6093DC10F1EA3DD630666F5B2491EB9BDD7DF9A6C45AC12C46',
]

const list_with_duplicates: string[] = [
'EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A',
'EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A',
]

assert.isFalse(containsDuplicates(list_without_dups))
assert.isTrue(containsDuplicates(list_with_duplicates))
})
})

describe('isFlagEnabled', function () {
let flags: number
const flag1 = 0x00010000
Expand Down

0 comments on commit da655b2

Please sign in to comment.