diff --git a/packages/core/src/subjects/mingo-ops.spec.ts b/packages/core/src/subjects/mingo-ops.spec.ts index a9fd0f1..f1876af 100644 --- a/packages/core/src/subjects/mingo-ops.spec.ts +++ b/packages/core/src/subjects/mingo-ops.spec.ts @@ -178,6 +178,70 @@ describe('mingo query ops', () => { }).toThrow() }) + it('should compare eq addresses', () => { + const q = new Query({ + 'args.dest.id': { $address_eq: '14NEHDwc5PPQfEjzLVDbVbi4djQLQZ9u7mMU3BPhTFJf4cD6' }, + }) + + expect(q.test(data)).toBeTruthy() + }) + + it('should compare eq addresses with different ss58 formats', () => { + const q = new Query({ + 'args.dest.id': { $address_eq: 'dfZvF6iz8qvsdGEWTHBoo2daJWq386QYfDXwfsycTJhicxLcc' }, + }) + + expect(q.test(data)).toBeTruthy() + }) + + it('should compare eq addresses falsy case', () => { + const q = new Query({ + 'args.dest.id': { $address_eq: '12Dw5aURKmAG8fCRtBa28tEvBVDChnaoKsjpewv53d6e6766' }, + }) + + expect(q.test(data)).toBeFalsy() + }) + + it('should compare neq addresses', () => { + const q = new Query({ + 'args.dest.id': { $address_neq: '12Dw5aURKmAG8fCRtBa28tEvBVDChnaoKsjpewv53d6e6766' }, + }) + + expect(q.test(data)).toBeTruthy() + }) + + it('should compare neq addresses with different ss58 formats', () => { + const q = new Query({ + 'args.dest.id': { $address_neq: '7LxmCfshfK8TeiJWUmwZr6NqCWbGeyeAoEi61SvKX4Ea3UNn' }, + }) + + expect(q.test(data)).toBeTruthy() + }) + + it('should compare neq addresses with different ss58 falsy case', () => { + const q = new Query({ + 'args.dest.id': { $address_neq: 'dfZvF6iz8qvsdGEWTHBoo2daJWq386QYfDXwfsycTJhicxLcc' }, + }) + + expect(q.test(data)).toBeFalsy() + }) + + it('should return neq if is not valid address', () => { + const q = new Query({ + 'args.dest.id': { $address_neq: 'foobar' }, + }) + + expect(q.test(data)).toBeFalsy() + }) + + it('should return neq if value is not string', () => { + const q = new Query({ + 'args.dest.id': { $address_neq: 111 }, + }) + + expect(q.test(data)).toBeFalsy() + }) + it('should be idempotent on ops registration', () => { expect(() => { installOperators() diff --git a/packages/core/src/subjects/mingo-ops.ts b/packages/core/src/subjects/mingo-ops.ts index 3dce60f..6ab8dd6 100644 --- a/packages/core/src/subjects/mingo-ops.ts +++ b/packages/core/src/subjects/mingo-ops.ts @@ -1,7 +1,8 @@ // Copyright 2023-2024 SO/DA zone // SPDX-License-Identifier: Apache-2.0 -import { bnToBn, logger } from '@polkadot/util' +import { bnToBn, isU8a, logger } from '@polkadot/util' +import { addressEq } from '@polkadot/util-crypto' import { OperatorType, Options, QueryOperator, getOperator, useOperators } from 'mingo/core' import { BASIC_CONTEXT } from 'mingo/init/basic' @@ -49,6 +50,28 @@ function $bn_neq(a: AnyVal, b: AnyVal): boolean { return compare(a, b, (x: AnyVal, y: AnyVal) => !bn(x).eq(bn(y))) } +function $address_eq(a: AnyVal, b: AnyVal): boolean { + if ((typeof a === 'string' || isU8a(a)) && (typeof b === 'string' || isU8a(b))) { + try { + return addressEq(a, b) + } catch (_) { + return false + } + } + return false +} + +function $address_neq(a: AnyVal, b: AnyVal): boolean { + if ((typeof a === 'string' || isU8a(a)) && (typeof b === 'string' || isU8a(b))) { + try { + return !addressEq(a, b) + } catch (_) { + return false + } + } + return false +} + function createQueryOperator(predicate: Predicate): QueryOperator { const f = (selector: string, value: AnyVal, options: Options) => { const opts = { unwrapArray: true } @@ -80,6 +103,8 @@ export function installOperators() { $bn_gte: createQueryOperator($bn_gte), $bn_eq: createQueryOperator($bn_eq), $bn_neq: createQueryOperator($bn_neq), + $address_eq: createQueryOperator($address_eq), + $address_neq: createQueryOperator($address_neq), }) } }