Skip to content

Commit

Permalink
Maps all GQL AccessCondition(s) to raw AccessCondition(s)
Browse files Browse the repository at this point in the history
  • Loading branch information
cesarenaldi committed Sep 11, 2023
1 parent 89bbb8e commit ae9a83f
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 80 deletions.
4 changes: 2 additions & 2 deletions packages/gated-content/src/__helpers__/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { faker } from '@faker-js/faker';
import {
Amount,
Asset,
ChainId,
CollectCondition,
ConditionComparisonOperator,
ConditionType,
Expand All @@ -19,6 +18,7 @@ import {
PublicationMainFocus,
PublicationMetadata,
PublicationSchemaId,
toChainId,
toEvmAddress,
toLocale,
toMarkdown,
Expand Down Expand Up @@ -46,7 +46,7 @@ export function mockEvmAddress(): EvmAddress {
export function mockNetworkAddress(overrides?: Partial<NetworkAddress>): NetworkAddress {
return {
address: mockEvmAddress(),
chainId: 1 as ChainId,
chainId: toChainId(1),
...overrides,
};
}
Expand Down
156 changes: 99 additions & 57 deletions packages/gated-content/src/conditions/__tests__/conditions.spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { AccessCondition, andCondition, ConditionType, orCondition } from '@lens-protocol/metadata';
import {
AccessCondition,
andCondition,
ConditionType,
orCondition,
toChainId,
} from '@lens-protocol/metadata';
import { BigNumber } from 'ethers';

import { testing } from '../../__helpers__/env';
import {
mockEoaOwnershipCondition,
mockEvmAddress,
mockNetworkAddress,
mockNftOwnershipCondition,
mockProfileId,
mockProfileOwnershipCondition,
} from '../../__helpers__/mocks';
import { transformFromRaw } from '../index';
import * as raw from '../../__helpers__/mocks';
import * as gql from '../../graphql/__helpers__/mocks';
import { transformFromGql, transformFromRaw } from '../index';
import {
LitConditionType,
LitContractType,
Expand All @@ -21,17 +21,23 @@ import {
} from '../types';
import { InvalidAccessCriteriaError } from '../validators';

const ownerProfileId = mockProfileId();
const knownAddress = mockEvmAddress();
const ownerProfileId = raw.mockProfileId();
const knownAddress = raw.mockEvmAddress();

describe(`Given the "${transformFromRaw.name}" function`, () => {
describe(`Given the conditions helpers`, () => {
describe.each([
{
description: 'a simple condition',
condition: orCondition([
mockProfileOwnershipCondition({ profileId: ownerProfileId }),
mockEoaOwnershipCondition({ address: knownAddress }),
raw: orCondition([
raw.mockProfileOwnershipCondition({ profileId: ownerProfileId }),
raw.mockEoaOwnershipCondition({ address: knownAddress }),
]),
gql: gql.mockOrCondition({
criteria: [
gql.mockProfileOwnershipCondition({ profileId: ownerProfileId }),
gql.mockEoaOwnershipCondition({ address: knownAddress }),
],
}),
expectedLitAccessConditions: [
{
conditionType: LitConditionType.EVM_CONTRACT,
Expand Down Expand Up @@ -96,15 +102,28 @@ describe(`Given the "${transformFromRaw.name}" function`, () => {
},
{
description: 'a nested OR condition',
condition: orCondition([
mockProfileOwnershipCondition({ profileId: ownerProfileId }),
raw: orCondition([
raw.mockProfileOwnershipCondition({ profileId: ownerProfileId }),
orCondition([
mockEoaOwnershipCondition({ address: knownAddress }),
mockNftOwnershipCondition({
contract: mockNetworkAddress({ address: knownAddress }),
raw.mockEoaOwnershipCondition({ address: knownAddress }),
raw.mockNftOwnershipCondition({
contract: raw.mockNetworkAddress({ address: knownAddress, chainId: toChainId(1) }),
}),
]),
]),
gql: gql.mockOrCondition({
criteria: [
gql.mockProfileOwnershipCondition({ profileId: ownerProfileId }),
gql.mockOrCondition({
criteria: [
gql.mockEoaOwnershipCondition({ address: knownAddress }),
gql.mockNftOwnershipCondition({
contract: gql.mockNetworkAddress({ address: knownAddress, chainId: '1' }),
}),
],
}),
],
}),
expectedLitAccessConditions: [
{
conditionType: LitConditionType.EVM_CONTRACT,
Expand Down Expand Up @@ -184,15 +203,28 @@ describe(`Given the "${transformFromRaw.name}" function`, () => {
},
{
description: 'a nested AND condition',
condition: orCondition([
mockProfileOwnershipCondition({ profileId: ownerProfileId }),
raw: orCondition([
raw.mockProfileOwnershipCondition({ profileId: ownerProfileId }),
andCondition([
mockEoaOwnershipCondition({ address: knownAddress }),
mockNftOwnershipCondition({
contract: mockNetworkAddress({ address: knownAddress }),
raw.mockEoaOwnershipCondition({ address: knownAddress }),
raw.mockNftOwnershipCondition({
contract: raw.mockNetworkAddress({ address: knownAddress, chainId: toChainId(1) }),
}),
]),
]),
gql: gql.mockOrCondition({
criteria: [
gql.mockProfileOwnershipCondition({ profileId: ownerProfileId }),
gql.mockAndCondition({
criteria: [
gql.mockEoaOwnershipCondition({ address: knownAddress }),
gql.mockNftOwnershipCondition({
contract: gql.mockNetworkAddress({ address: knownAddress, chainId: '1' }),
}),
],
}),
],
}),
expectedLitAccessConditions: [
{
conditionType: LitConditionType.EVM_CONTRACT,
Expand Down Expand Up @@ -270,90 +302,100 @@ describe(`Given the "${transformFromRaw.name}" function`, () => {
],
],
},
])('when called with $description', ({ condition, expectedLitAccessConditions }) => {
it('should return the expected Lit AccessControlCondition', () => {
const actual = transformFromRaw(condition, testing);
])(`and $description`, ({ raw, gql, expectedLitAccessConditions }) => {
describe(`when calling "${transformFromRaw.name}"`, () => {
it('should return the expected Lit AccessControlCondition', () => {
const actual = transformFromRaw(raw, testing);

expect(actual).toMatchObject(expectedLitAccessConditions);
});
});

describe(`when calling "${transformFromGql.name}"`, () => {
it('should return the expected Lit AccessControlCondition', () => {
const actual = transformFromGql(gql, testing);

expect(actual).toMatchObject(expectedLitAccessConditions);
expect(actual).toMatchObject(expectedLitAccessConditions);
});
});
});

describe.each([
{
description: 'with a root condition that is not an OR condition',
condition: mockProfileOwnershipCondition(),
condition: raw.mockProfileOwnershipCondition(),
},
{
description: 'with an OR root condition that has more than 2 criteria',
condition: orCondition([
mockProfileOwnershipCondition(),
mockEoaOwnershipCondition(),
mockNftOwnershipCondition(),
raw.mockProfileOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
raw.mockNftOwnershipCondition(),
]),
},
{
description: 'with an OR root condition that does not include a profile ownership condition',
condition: orCondition([mockEoaOwnershipCondition(), mockNftOwnershipCondition()]),
condition: orCondition([raw.mockEoaOwnershipCondition(), raw.mockNftOwnershipCondition()]),
},
{
description: 'a nested AND condition with less than 2 criteria',
condition: orCondition([
mockProfileOwnershipCondition(),
raw.mockProfileOwnershipCondition(),
{
type: ConditionType.AND,
criteria: [mockEoaOwnershipCondition()],
criteria: [raw.mockEoaOwnershipCondition()],
},
]),
},
{
description: 'a nested AND condition with more than 5 criteria',
condition: orCondition([
mockProfileOwnershipCondition(),
raw.mockProfileOwnershipCondition(),
andCondition([
mockEoaOwnershipCondition(),
mockEoaOwnershipCondition(),
mockEoaOwnershipCondition(),
mockEoaOwnershipCondition(),
mockEoaOwnershipCondition(),
mockEoaOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
]),
]),
},
{
description: 'a nested OR condition with less than 2 criteria',
condition: orCondition([
mockProfileOwnershipCondition(),
raw.mockProfileOwnershipCondition(),
{
type: ConditionType.OR,
criteria: [mockEoaOwnershipCondition()],
criteria: [raw.mockEoaOwnershipCondition()],
},
]),
},
{
description: 'a nested OR condition with more than 5 criteria',
condition: orCondition([
mockProfileOwnershipCondition(),
raw.mockProfileOwnershipCondition(),
orCondition([
mockEoaOwnershipCondition(),
mockEoaOwnershipCondition(),
mockEoaOwnershipCondition(),
mockEoaOwnershipCondition(),
mockEoaOwnershipCondition(),
mockEoaOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
raw.mockEoaOwnershipCondition(),
]),
]),
},
{
description: 'with more than 2 nested levels AND and OR conditions ',
condition: orCondition([
mockProfileOwnershipCondition(),
raw.mockProfileOwnershipCondition(),
andCondition([
mockEoaOwnershipCondition(),
orCondition([mockEoaOwnershipCondition(), mockEoaOwnershipCondition()]),
raw.mockEoaOwnershipCondition(),
orCondition([raw.mockEoaOwnershipCondition(), raw.mockEoaOwnershipCondition()]),
]),
]),
},
])('when called with $description', ({ condition }) => {
])(`when calling "${transformFromRaw.name}" with $description`, ({ condition }) => {
it(`should throw a ${InvalidAccessCriteriaError.name}`, () => {
expect(() => transformFromRaw(condition as AccessCondition, testing)).toThrow(
InvalidAccessCriteriaError,
Expand Down
61 changes: 53 additions & 8 deletions packages/gated-content/src/conditions/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as raw from '@lens-protocol/metadata';
import { invariant, InvariantError, never } from '@lens-protocol/shared-kernel';
import { assertNever, invariant, InvariantError, never } from '@lens-protocol/shared-kernel';
import type { UnifiedAccessControlConditions } from '@lit-protocol/types';

import { EnvironmentConfig } from '../environments';
Expand Down Expand Up @@ -135,7 +135,14 @@ const AccessConditionTypenameToConditionType: Record<
FollowCondition: raw.ConditionType.FOLLOW,
};

function toSimpleCondition(
function toRawNetworkAddress({ address, chainId }: gql.NetworkAddress): raw.NetworkAddress {
return {
address: raw.toEvmAddress(address),
chainId: raw.toChainId(parseInt(chainId)),
};
}

function toRawSimpleCondition(
gqlCondition: Exclude<gql.AccessCondition, gql.OrCondition | gql.AndCondition>,
): raw.SimpleCondition {
switch (gqlCondition.__typename) {
Expand All @@ -144,18 +151,56 @@ function toSimpleCondition(
type: raw.ConditionType.EOA_OWNERSHIP,
address: raw.toEvmAddress(gqlCondition.address),
};

case 'ProfileOwnershipCondition':
return {
type: raw.ConditionType.PROFILE_OWNERSHIP,
profileId: raw.toProfileId(gqlCondition.profileId),
};

case 'Erc20OwnershipCondition':
return {
type: raw.ConditionType.ERC20_OWNERSHIP,
amount: {
asset: {
contract: toRawNetworkAddress(gqlCondition.amount.asset.contract),
decimals: gqlCondition.amount.asset.decimals,
},
value: gqlCondition.amount.value,
},
condition:
raw.ConditionComparisonOperator[gqlCondition.condition] ??
never(`Not supported condition: ${gqlCondition.condition}`),
};

case 'NftOwnershipCondition':
return {
type: raw.ConditionType.NFT_OWNERSHIP,
contract: toRawNetworkAddress(gqlCondition.contract),
contractType:
raw.NftContractType[gqlCondition.contractType] ??
never(`Not supported contract type: ${gqlCondition.contractType}`),
tokenIds: gqlCondition.tokenIds?.map(raw.toTokenId),
};

case 'CollectCondition':
return {
type: raw.ConditionType.COLLECT,
publicationId: raw.toPublicationId(gqlCondition.publicationId),
thisPublication: gqlCondition.thisPublication,
};

case 'FollowCondition':
return {
type: raw.ConditionType.FOLLOW,
follow: raw.toProfileId(gqlCondition.follow),
};
}

// TODO finish and test
never(gqlCondition.__typename);
assertNever(gqlCondition, 'Unknown access condition type');
}

function toAnyCondition(gqlCondition: gql.AccessCondition): raw.AnyCondition {
function toAnyRawCondition(gqlCondition: gql.AccessCondition): raw.AnyCondition {
switch (gqlCondition.__typename) {
case 'OrCondition':
case 'AndCondition':
Expand All @@ -164,11 +209,11 @@ function toAnyCondition(gqlCondition: gql.AccessCondition): raw.AnyCondition {
| raw.ConditionType.AND
| raw.ConditionType.OR,
criteria: gqlCondition.criteria.map(
toAnyCondition,
toAnyRawCondition,
) as raw.TwoAtLeastArray<raw.SimpleCondition>,
};
default:
return toSimpleCondition(gqlCondition);
return toRawSimpleCondition(gqlCondition);
}
}

Expand All @@ -179,7 +224,7 @@ function toRawAccessCondition(gqlCondition: gql.AccessCondition): raw.AccessCond
return {
type: raw.ConditionType.OR,
criteria: gqlCondition.criteria.map((c) =>
toAnyCondition(c),
toAnyRawCondition(c),
) as raw.TwoAtLeastArray<raw.AnyCondition>,
};
}
Expand Down
Loading

0 comments on commit ae9a83f

Please sign in to comment.