From 05a2461603e57908a86ec82fa983fe8a9ba320ac Mon Sep 17 00:00:00 2001 From: Benoit Devos Date: Fri, 14 Jun 2024 11:36:05 +0200 Subject: [PATCH 1/2] feat: connect to decentralized directory. logion-network/logion-internal#1292 --- packages/client-node/docker-compose.yml | 77 +------------------ .../client-node/integration/LegalOfficer.ts | 31 ++++++++ packages/client-node/integration/Main.spec.ts | 6 +- packages/client-node/integration/Utils.ts | 25 +++--- ...tory_data.sql => directory_data_node1.sql} | 3 - .../scripts/directory_data_node2.sql | 4 + .../scripts/integration_test_db_setup.sh | 3 +- packages/client/package.json | 2 +- packages/client/src/AuthenticationClient.ts | 21 +---- packages/client/src/ComponentFactory.ts | 12 +-- packages/client/src/DirectoryClient.ts | 67 ++++++++++++---- packages/client/src/Environment.ts | 9 --- packages/client/src/LogionClient.ts | 10 +-- packages/client/src/SharedClient.ts | 1 - packages/client/test/AccountRecovery.spec.ts | 14 ++-- .../client/test/AuthenticationClient.spec.ts | 11 +-- packages/client/test/Balance.spec.ts | 10 +-- packages/client/test/DirectoryClient.spec.ts | 70 +++++++++-------- packages/client/test/Environment.spec.ts | 2 - packages/client/test/Loc.spec.ts | 2 +- packages/client/test/LogionClient.spec.ts | 31 ++++---- packages/client/test/Public.spec.ts | 2 +- packages/client/test/RecoveryReview.spec.ts | 2 +- packages/client/test/SecretRecovery.spec.ts | 2 +- packages/client/test/TestConfigFactory.ts | 13 ++-- packages/client/test/Utils.ts | 5 +- packages/client/test/Vault.spec.ts | 8 +- packages/client/test/Voter.spec.ts | 2 +- 28 files changed, 201 insertions(+), 244 deletions(-) rename packages/client-node/scripts/{directory_data.sql => directory_data_node1.sql} (68%) create mode 100644 packages/client-node/scripts/directory_data_node2.sql diff --git a/packages/client-node/docker-compose.yml b/packages/client-node/docker-compose.yml index da0e5adb..ebf13067 100644 --- a/packages/client-node/docker-compose.yml +++ b/packages/client-node/docker-compose.yml @@ -7,6 +7,8 @@ services: # ----------------------------------------- Logion node 1 -------------------------------------------------------------- private-database1: image: logionnetwork/logion-postgres:${PG_TAG:-latest} + ports: + - 127.0.0.1:5432:5432 environment: - POSTGRES_PASSWORD=secret backend1: @@ -17,7 +19,6 @@ services: - TYPEORM_HOST=private-database1 - WS_PROVIDER_URL=ws://$RPC_WS - OWNER=5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY - - DIRECTORY_URL=http://directory:8080 - SMTP_ENABLED=false - IPFS_CLUSTER_HOST=/dns4/ipfs-cluster1/tcp/9094 - IPFS_HOST=/dns4/ipfs1/tcp/5001 @@ -61,6 +62,8 @@ services: # ----------------------------------------- Logion node 2 -------------------------------------------------------------- private-database2: image: logionnetwork/logion-postgres:${PG_TAG:-latest} + ports: + - 127.0.0.1:5433:5432 environment: - POSTGRES_PASSWORD=secret backend2: @@ -71,7 +74,6 @@ services: - TYPEORM_HOST=private-database2 - WS_PROVIDER_URL=ws://$RPC_WS - OWNER=5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty - - DIRECTORY_URL=http://directory:8080 - SMTP_ENABLED=false - IPFS_CLUSTER_HOST=/dns4/ipfs-cluster2/tcp/9094 - IPFS_HOST=/dns4/ipfs2/tcp/5001 @@ -111,74 +113,3 @@ services: volumes: - ./config/ipfs-cluster2/identity.json:/data/ipfs-cluster/identity.json:ro - ./config/ipfs-cluster2/service.json:/data/ipfs-cluster/service.json:ro -# ----------------------------------------- Logion node 3 -------------------------------------------------------------- - private-database3: - image: logionnetwork/logion-postgres:${PG_TAG:-latest} - environment: - - POSTGRES_PASSWORD=secret - backend3: - image: logionnetwork/logion-backend:${BACKEND_TAG:-latest} - environment: - - JWT_SECRET=3a9d5b35b9fb4c42aafadeca046f6bf56107bd2579687f069b42646684b94d9e - - JWT_ISSUER=12D3KooWJvyP3VJYymTqG7eH4PM5rN4T2agk5cdNCfNymAqwqcvZ - - TYPEORM_HOST=private-database3 - - WS_PROVIDER_URL=ws://$RPC_WS - - OWNER=5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y - - DIRECTORY_URL=http://directory:8080 - - SMTP_ENABLED=false - - IPFS_CLUSTER_HOST=/dns4/ipfs-cluster3/tcp/9094 - - IPFS_HOST=/dns4/ipfs3/tcp/5001 - - IPFS_MIN_REPLICA=1 - - IPFS_MAX_REPLICA=2 - - ENC_PASSWORD=test - depends_on: - - private-database3 - - ipfs-cluster3 - frontend3: - image: logionnetwork/logion-frontend:${FRONTEND_TAG:-latest} - ports: - - 127.0.0.1:8082:80 - volumes: - - ./front_config.js:/usr/share/nginx/html/config.js - - ./front_web3.conf:/etc/nginx/conf.d/default.conf - depends_on: - - backend3 - environment: - - CERTBOT_EMAIL=user3@invalid.domain - - BACKEND_HOST_PORT=backend3:8080 - - NODE_HOST_PORT=$RPC_WS - ipfs3: - image: ipfs/go-ipfs:v0.12.0 - volumes: - - ./config/ipfs3/config:/data/ipfs/config:ro - - ./config/ipfs3/datastore_spec:/data/ipfs/datastore_spec:ro - - ./config/ipfs3/swarm.key:/data/ipfs/swarm.key:ro - - ./config/ipfs3/version:/data/ipfs/version:ro - depends_on: - - ipfs1 - ipfs-cluster3: - image: ipfs/ipfs-cluster:v0.14.5 - depends_on: - - ipfs-cluster1 - - ipfs3 - volumes: - - ./config/ipfs-cluster3/identity.json:/data/ipfs-cluster/identity.json:ro - - ./config/ipfs-cluster3/service.json:/data/ipfs-cluster/service.json:ro -# ----------------------------------------- Logion directory -------------------------------------------------------------- - directory-database: - image: postgres:12 - ports: - - 127.0.0.1:5432:5432 - environment: - - POSTGRES_PASSWORD=secret - directory: - image: logionnetwork/logion-directory:${DIRECTORY_TAG:-latest} - ports: - - 127.0.0.1:8090:8080 - environment: - - JWT_SECRET=c12b6d18942f5ee8528c8e2baf4e147b5c5c18710926ea492d09cbd9f6c9f82a - - JWT_ISSUER=12D3KooWBmAwcd4PJNJvfV89HwE48nwkRmAgo8Vy3uQEyNNHBox2 - - WS_PROVIDER_URL=ws://$RPC_WS - - TYPEORM_HOST=directory-database - depends_on: - - directory-database diff --git a/packages/client-node/integration/LegalOfficer.ts b/packages/client-node/integration/LegalOfficer.ts index 4a26d13a..f34eec20 100644 --- a/packages/client-node/integration/LegalOfficer.ts +++ b/packages/client-node/integration/LegalOfficer.ts @@ -1,4 +1,5 @@ import { State } from "./Utils.js"; +import { LegalOfficer } from "@logion/client/dist/Types.js"; export async function backendConfig(state: State) { const { client, requesterAccount, alice } = state; @@ -19,3 +20,33 @@ export async function workload(state: State) { expect(workload).toBe(0); } } + +export async function updateLegalOfficer(state: State) { + const { client, alice } = state; + const updatedAlice: LegalOfficer = { + node: alice.node, + userIdentity: { + firstName: "Alice", + lastName: "updated-last-name", + email: "updated-email-address@logion.network", + phoneNumber: "updated-phone-number", + }, + postalAddress: { + company: "updated-company", + line1: "updated-line1", + line2: "updated-line2", + postalCode: "updated-postal-code", + city: "updated-city", + country: "updated-country", + }, + account: alice.account, + additionalDetails: "Some new details", + } as LegalOfficer; + const aliceClient = client.withCurrentAccount(alice.account); + await aliceClient.directoryClient.createOrUpdate(updatedAlice); + const legalOfficers = await client.directoryClient.getLegalOfficers(); + const legalOfficer = legalOfficers.find(legalOfficer => legalOfficer.account.equals(alice.account)) + expect(legalOfficer?.userIdentity).toEqual(updatedAlice.userIdentity); + expect(legalOfficer?.postalAddress).toEqual(updatedAlice.postalAddress); + expect(legalOfficer?.additionalDetails).toEqual(updatedAlice.additionalDetails); +} diff --git a/packages/client-node/integration/Main.spec.ts b/packages/client-node/integration/Main.spec.ts index 30fe64de..57992a1f 100644 --- a/packages/client-node/integration/Main.spec.ts +++ b/packages/client-node/integration/Main.spec.ts @@ -15,7 +15,7 @@ import { import { verifiedIssuer } from "./VerifiedIssuer.js"; import { tokensRecords } from "./TokensRecord.js"; import { fees } from "./Fees.js"; -import { backendConfig, workload } from "./LegalOfficer.js"; +import { backendConfig, workload, updateLegalOfficer } from "./LegalOfficer.js"; import { voidTransactionLoc } from "./Void.js"; import { votingProcess } from "./Vote.js"; import { openIdentityLoc, openTransactionLoc, openCollectionLoc } from "./DirectLocOpen.js"; @@ -40,6 +40,10 @@ describe("Logion SDK", () => { await workload(state); }); + it("updates legal officer details", async () => { + await updateLegalOfficer(state); + }); + it("estimates fees", async () => { await fees(state); }); diff --git a/packages/client-node/integration/Utils.ts b/packages/client-node/integration/Utils.ts index 7002bd80..1981b0f6 100644 --- a/packages/client-node/integration/Utils.ts +++ b/packages/client-node/integration/Utils.ts @@ -36,7 +36,6 @@ export function buildSigner(seeds: string []): FullSigner { } export const TEST_LOGION_CLIENT_CONFIG: LogionClientConfig = { - directoryEndpoint: "http://localhost:8090", rpcEndpoints: [ 'ws://localhost:9944' ], buildFileUploader: () => new NodeAxiosFileUploader(), }; @@ -170,20 +169,20 @@ async function updateLegalOfficers(params: { api: ApiPromise, aliceAccount: Vali } ), }); + await Promise.all([llo1, llo2]); + + const extrinsic = api.tx.loAuthorityList.updateLegalOfficer( + charlieAccount.address, + { + Guest: aliceAccount.address + } + ); + const sudoExtrinsic = api.tx.sudo.sudo(extrinsic); const llo3 = signer.signAndSend({ - signerId: charlieAccount, - submittable: api.tx.loAuthorityList.updateLegalOfficer( - charlieAccount.address, - { - Host: { - nodeId: "0x002408011220876a7b4984f98006dc8d666e28b60de307309835d775e7755cc770328cdacf2e", - baseUrl: "http://localhost:8082", - region: "Europe", - } - } - ), + signerId: aliceAccount, + submittable: sudoExtrinsic, }); - await Promise.all([llo1, llo2, llo3]); + await llo3; } export async function updateConfig(config: Partial): Promise { diff --git a/packages/client-node/scripts/directory_data.sql b/packages/client-node/scripts/directory_data_node1.sql similarity index 68% rename from packages/client-node/scripts/directory_data.sql rename to packages/client-node/scripts/directory_data_node1.sql index 566f664c..a7ba8d2c 100644 --- a/packages/client-node/scripts/directory_data.sql +++ b/packages/client-node/scripts/directory_data_node1.sql @@ -3,8 +3,5 @@ TRUNCATE TABLE public.legal_officer; INSERT INTO public.legal_officer (address, first_name, last_name, email, phone_number, company, line1, line2, postal_code, city, country, additional_details) VALUES ('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', 'Alice', '', 'alice@logion.network', '+1234', 'Alice''s Company', 'Line 1', 'Line 2', '1000', 'City', 'Country', null); -INSERT INTO public.legal_officer (address, first_name, last_name, email, phone_number, company, line1, line2, postal_code, city, country, additional_details) -VALUES ('5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty', 'Bob', '', 'bob@logion.network', '+1234', 'Bob''s Company', 'Line 1', 'Line 2', '1000', 'City', 'Country', null); - INSERT INTO public.legal_officer (address, first_name, last_name, email, phone_number, company, line1, line2, postal_code, city, country, additional_details) VALUES ('5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y', 'Charlie', '', 'charlie@logion.network', '+1234', 'Charlie''s Company', 'Line 1', 'Line 2', '1000', 'City', 'Country', null); diff --git a/packages/client-node/scripts/directory_data_node2.sql b/packages/client-node/scripts/directory_data_node2.sql new file mode 100644 index 00000000..e628690c --- /dev/null +++ b/packages/client-node/scripts/directory_data_node2.sql @@ -0,0 +1,4 @@ +TRUNCATE TABLE public.legal_officer; + +INSERT INTO public.legal_officer (address, first_name, last_name, email, phone_number, company, line1, line2, postal_code, city, country, additional_details) +VALUES ('5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty', 'Bob', '', 'bob@logion.network', '+1234', 'Bob''s Company', 'Line 1', 'Line 2', '1000', 'City', 'Country', null); diff --git a/packages/client-node/scripts/integration_test_db_setup.sh b/packages/client-node/scripts/integration_test_db_setup.sh index e19421c0..b34426f2 100755 --- a/packages/client-node/scripts/integration_test_db_setup.sh +++ b/packages/client-node/scripts/integration_test_db_setup.sh @@ -5,5 +5,6 @@ set -e sleep 5 export PGPASSWORD=secret -psql -h 127.0.0.1 -U postgres postgres < scripts/directory_data.sql +psql -h 127.0.0.1 -p 5432 -U postgres postgres < scripts/directory_data_node1.sql +psql -h 127.0.0.1 -p 5433 -U postgres postgres < scripts/directory_data_node2.sql unset PGPASSWORD diff --git a/packages/client/package.json b/packages/client/package.json index de737ef8..ca4cfd5a 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@logion/client", - "version": "0.46.0-1", + "version": "0.46.0-2", "description": "logion SDK for client applications", "main": "dist/index.js", "packageManager": "yarn@3.2.0", diff --git a/packages/client/src/AuthenticationClient.ts b/packages/client/src/AuthenticationClient.ts index 8d08d33f..fc96dbe3 100644 --- a/packages/client/src/AuthenticationClient.ts +++ b/packages/client/src/AuthenticationClient.ts @@ -1,7 +1,6 @@ import { LogionNodeApiClass, ValidAccountId } from "@logion/node-api"; import { AxiosInstance } from "axios"; import { DateTime } from "luxon"; -import { AxiosFactory } from "./AxiosFactory"; import { fromIsoString, toIsoString } from "./DateTimeUtil.js"; import { Token } from "./Http"; @@ -18,31 +17,17 @@ type AuthenticationResponse = Record { - return this.doWithDirectoryOrFirstAvailableNode(axios => this.authenticateWithAxios(axios, addresses, signer)); - } - - private doWithDirectoryOrFirstAvailableNode(axiosConsumer: (axios: AxiosInstance) => Promise): Promise { - if(this.legalOfficers.length === 0) { - return axiosConsumer(this.axiosFactory.buildAxiosInstance(this.directoryEndpoint)); - } else { - return this.doWithFirstAvailableNode(axiosConsumer); - } + return this.doWithFirstAvailableNode(axios => this.authenticateWithAxios(axios, addresses, signer)); } private doWithFirstAvailableNode(axiosConsumer: (axios: AxiosInstance) => Promise): Promise { @@ -115,7 +100,7 @@ export class AuthenticationClient { } } - const authenticateResponse = await this.doWithDirectoryOrFirstAvailableNode(axios => + const authenticateResponse = await this.doWithFirstAvailableNode(axios => axios.put(`/api/auth/refresh`, { tokens }) diff --git a/packages/client/src/ComponentFactory.ts b/packages/client/src/ComponentFactory.ts index 94393d29..84afcaea 100644 --- a/packages/client/src/ComponentFactory.ts +++ b/packages/client/src/ComponentFactory.ts @@ -1,4 +1,4 @@ -import { LogionNodeApiClass, buildApiClass, Hash } from "@logion/node-api"; +import { LogionNodeApiClass, Hash } from "@logion/node-api"; import { AuthenticationClient } from "./AuthenticationClient.js"; import { AxiosFactory } from "./AxiosFactory.js"; import { DirectoryClient } from "./DirectoryClient.js"; @@ -83,18 +83,18 @@ export abstract class AxiosFileUploader implements FileUploader { export interface CoreComponentFactory { buildAxiosFactory: () => AxiosFactory; - buildDirectoryClient: (api: LogionNodeApiClass, directoryEndpoint: string, axiosFactory: AxiosFactory, token?: string) => DirectoryClient; - buildAuthenticationClient: (api: LogionNodeApiClass, directoryEndpoint: string, legalOfficers: LegalOfficerClass[], axiosFactory: AxiosFactory) => AuthenticationClient; + buildDirectoryClient: (api: LogionNodeApiClass, axiosFactory: AxiosFactory, token?: string) => DirectoryClient; + buildAuthenticationClient: (api: LogionNodeApiClass, legalOfficers: LegalOfficerClass[]) => AuthenticationClient; buildNetworkState(nodesUp: LegalOfficerEndpoint[], nodesDown: LegalOfficerEndpoint[]): NetworkState; buildNodeApi(rpcEndpoints: string[]): Promise; } export const CoreComponentFactoryInstance: CoreComponentFactory = { buildAxiosFactory: () => new AxiosFactory(), - buildDirectoryClient: (api: LogionNodeApiClass, directoryEndpoint: string, axiosFactory: AxiosFactory, token?: string) => new DirectoryClient(api, directoryEndpoint, axiosFactory, token), - buildAuthenticationClient: (api: LogionNodeApiClass, directoryEndpoint: string, legalOfficers: LegalOfficerClass[], axiosFactory: AxiosFactory) => new AuthenticationClient(api, directoryEndpoint, legalOfficers, axiosFactory), + buildDirectoryClient: (api: LogionNodeApiClass, axiosFactory: AxiosFactory, token?: string) => new DirectoryClient(api, axiosFactory, token), + buildAuthenticationClient: (api: LogionNodeApiClass, legalOfficers: LegalOfficerClass[]) => new AuthenticationClient(api, legalOfficers), buildNetworkState: (nodesUp: LegalOfficerEndpoint[], nodesDown: LegalOfficerEndpoint[]) => new NetworkState(nodesUp, nodesDown), - buildNodeApi: (rpcEndpoints: string[]) => buildApiClass(rpcEndpoints), + buildNodeApi: (rpcEndpoints: string[]) => LogionNodeApiClass.connect(rpcEndpoints), }; export interface ComponentFactory extends CoreComponentFactory { diff --git a/packages/client/src/DirectoryClient.ts b/packages/client/src/DirectoryClient.ts index 333439ea..b8dbd1eb 100644 --- a/packages/client/src/DirectoryClient.ts +++ b/packages/client/src/DirectoryClient.ts @@ -6,6 +6,8 @@ import { PalletLoAuthorityListLegalOfficerData } from "@polkadot/types/lookup"; import { AxiosInstance } from "axios"; import { AxiosFactory } from "./AxiosFactory.js"; import { LegalOfficer, LegalOfficerClass, LegalOfficerPostalAddress, UserIdentity } from "./Types.js"; +import { MultiSourceHttpClient, aggregateArrays, Endpoint, MultiSourceHttpClientState } from "./Http.js"; +import { newBackendError } from "./Error.js"; export interface DirectoryLegalOfficer { userIdentity: UserIdentity; @@ -14,38 +16,53 @@ export interface DirectoryLegalOfficer { additionalDetails: string; } +export interface CreateOrUpdateLegalOfficer { + node: string; + userIdentity: UserIdentity; + postalAddress: LegalOfficerPostalAddress; + additionalDetails: string; +} + export class DirectoryClient { - constructor(api: LogionNodeApiClass, directoryEndpoint: string, axiosFactory: AxiosFactory, token?: string) { + constructor(api: LogionNodeApiClass, axiosFactory: AxiosFactory, token?: string) { this.authenticated = token !== undefined; this.axiosFactory = axiosFactory; this.token = token; this.api = api; - - this.axios = axiosFactory.buildAxiosInstance(directoryEndpoint, token); } - private authenticated: boolean; - - private axiosFactory: AxiosFactory; + private readonly authenticated: boolean; - private token: string | undefined; + private readonly axiosFactory: AxiosFactory; - private axios: AxiosInstance; + private readonly token: string | undefined; private api: LogionNodeApiClass; async getLegalOfficers(): Promise { - const offchain = (await this.axios.get("/api/legal-officer") - .then(response => response.data.legalOfficers)) as DirectoryLegalOfficer[]; - const offchainMap = this.toOffchainMap(offchain); const onchain = await this.api.polkadot.query.loAuthorityList.legalOfficerSet.entries(); const onchainMap = this.toOnchainMap(onchain); + const httpClient = new MultiSourceHttpClient( + this.getInitialState(onchainMap), + this.axiosFactory, + ); + const multiResponse = await httpClient.fetch(async axios => this.getLegalOfficersFromNode(axios, onchainMap)); + return aggregateArrays(multiResponse); + } + + async getLegalOfficersFromNode( + axios: AxiosInstance, + onchainMap: Record + ): Promise { + const offchain = (await axios.get("/api/legal-officer") + .then(response => response.data.legalOfficers)) as DirectoryLegalOfficer[]; + const offchainMap = this.toOffchainMap(offchain); const legalOfficers = []; - for(const address in onchainMap) { + for(const address in offchainMap) { const offchainData = offchainMap[address]; - if(offchainData) { - const hostData = this.getHostData(address, onchainMap); + const hostData = this.getHostData(address, onchainMap); + if(hostData) { const legalOfficer: LegalOfficer = { ...offchainData, name: `${offchainData.userIdentity.firstName} ${offchainData.userIdentity.lastName}`, @@ -55,7 +72,6 @@ export class DirectoryClient { legalOfficers.push(new LegalOfficerClass({ legalOfficer, axiosFactory: this.axiosFactory, - token: this.token, })); } } @@ -111,10 +127,27 @@ export class DirectoryClient { } } - async createOrUpdate(legalOfficer: LegalOfficer) { + private getInitialState(onchainMap: Record): MultiSourceHttpClientState { + const nodes = new Set(); + for(const address in onchainMap) { + const hostData = this.getHostData(address, onchainMap); + nodes.add(hostData.node); + } + return { + nodesUp: Array.from(nodes).map(node => ({ url: node })), + nodesDown: [], + }; + } + + async createOrUpdate(legalOfficer: CreateOrUpdateLegalOfficer) { if(!this.authenticated) { throw new Error("Authentication is required"); } - await this.axios.put('/api/legal-officer', legalOfficer); + try { + const backend = this.axiosFactory.buildAxiosInstance(legalOfficer.node, this.token); + await backend.put('/api/legal-officer', legalOfficer); + } catch(e) { + throw newBackendError(e); + } } } diff --git a/packages/client/src/Environment.ts b/packages/client/src/Environment.ts index 39cc783f..a93ff252 100644 --- a/packages/client/src/Environment.ts +++ b/packages/client/src/Environment.ts @@ -3,21 +3,13 @@ import { FileUploader } from "./ComponentFactory.js"; import { UUID } from "@logion/node-api"; export enum Environment { - DEV = 'DEV', TEST = 'TEST', MVP = 'MVP', } const configs: Record> = { - DEV: { - rpcEndpoints: [ "wss://dev-para-rpc01.logion.network" ], - directoryEndpoint: "https://dev-directory.logion.network", - logionClassificationLoc: UUID.fromDecimalStringOrThrow("229858905135790300364920790577257842944"), - creativeCommonsLoc: UUID.fromDecimalStringOrThrow("238252136510269500314784833180701623867"), - }, TEST: { rpcEndpoints: [ "wss://test-para-rpc01.logion.network" ], - directoryEndpoint: "https://test-directory.logion.network", logionClassificationLoc: UUID.fromDecimalStringOrThrow("116468287775993067124760331735250695835"), }, MVP: { @@ -25,7 +17,6 @@ const configs: Record "wss://para-rpc01.logion.network", "wss://para-rpc02.logion.network", ], - directoryEndpoint: "https://directory.logion.network", logionClassificationLoc: UUID.fromDecimalStringOrThrow("85815882149698756717105061322008904805"), } } diff --git a/packages/client/src/LogionClient.ts b/packages/client/src/LogionClient.ts index 133874dc..bbd09721 100644 --- a/packages/client/src/LogionClient.ts +++ b/packages/client/src/LogionClient.ts @@ -47,8 +47,7 @@ export class LogionClient { const nodeApi = await componentFactory.buildNodeApi(config.rpcEndpoints); const directoryClient = componentFactory.buildDirectoryClient( nodeApi, - config.directoryEndpoint, - axiosFactory + axiosFactory, ); const allLegalOfficers = await directoryClient.getLegalOfficers(); const legalOfficers = allLegalOfficers.filter(legalOfficer => legalOfficer.node); @@ -193,9 +192,7 @@ export class LogionClient { } const client = this.sharedState.componentFactory.buildAuthenticationClient( this.sharedState.nodeApi, - this.sharedState.config.directoryEndpoint, this.sharedState.legalOfficers, - this.sharedState.axiosFactory ); const tokens = await client.refresh(this.sharedState.tokens); return this.useTokens(tokens); @@ -223,14 +220,12 @@ export class LogionClient { if(currentAccount !== undefined) { directoryClient = this.sharedState.componentFactory.buildDirectoryClient( this.sharedState.nodeApi, - this.sharedState.config.directoryEndpoint, this.sharedState.axiosFactory, this.sharedState.tokens.get(currentAccount)?.value, ); } else { directoryClient = this.sharedState.componentFactory.buildDirectoryClient( this.sharedState.nodeApi, - this.sharedState.config.directoryEndpoint, this.sharedState.axiosFactory, ); } @@ -251,7 +246,6 @@ export class LogionClient { this.ensureConnected(); const directoryClient = this.sharedState.componentFactory.buildDirectoryClient( this.sharedState.nodeApi, - this.sharedState.config.directoryEndpoint, this.sharedState.axiosFactory ); return new LogionClient({ @@ -315,9 +309,7 @@ export class LogionClient { this.ensureConnected(); const client = this.sharedState.componentFactory.buildAuthenticationClient( this.sharedState.nodeApi, - this.sharedState.config.directoryEndpoint, this.sharedState.legalOfficers, - this.sharedState.axiosFactory ); const newTokens = await client.authenticate(accounts, signer); const tokens = this.tokens.merge(newTokens); diff --git a/packages/client/src/SharedClient.ts b/packages/client/src/SharedClient.ts index cbdb3e6a..38e4baa9 100644 --- a/packages/client/src/SharedClient.ts +++ b/packages/client/src/SharedClient.ts @@ -12,7 +12,6 @@ import { UUID } from "@logion/node-api"; export interface LogionClientConfig { rpcEndpoints: string[]; - directoryEndpoint: string; buildFileUploader: () => FileUploader; creativeCommonsLoc?: UUID; logionClassificationLoc?: UUID; diff --git a/packages/client/test/AccountRecovery.spec.ts b/packages/client/test/AccountRecovery.spec.ts index b8e045b6..d24c4c8d 100644 --- a/packages/client/test/AccountRecovery.spec.ts +++ b/packages/client/test/AccountRecovery.spec.ts @@ -168,7 +168,7 @@ async function buildSharedState(): Promise { (factory: TestConfigFactory) => { factory.setupDefaultAxiosInstanceFactory(); factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, token); + factory.setupAuthenticatedDirectoryClientMock(token); factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); }, currentAccount, @@ -284,7 +284,7 @@ describe("NoProtection", () => { setupFetchProtectionRequests(bobAxios, [], [], []); factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, token); + factory.setupAuthenticatedDirectoryClientMock(token); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); nodeApi.setup(instance => instance.queries.getRecoveryConfig(currentAccount)) @@ -339,7 +339,7 @@ describe("NoProtection", () => { const sharedState = await buildTestAuthenticatedSharedSate( (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, token); + factory.setupAuthenticatedDirectoryClientMock(token); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); nodeApi.setup(instance => instance.queries.getActiveRecovery(RECOVERED_ADDRESS, currentAccount)) @@ -453,7 +453,7 @@ describe("PendingRecovery", () => { setupFetchProtectionRequests(bobAxios, [ bobRequest ], [], []); factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, token); + factory.setupAuthenticatedDirectoryClientMock(token); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); nodeApi.setup(instance => instance.queries.getRecoveryConfig(currentAccount)) @@ -506,7 +506,7 @@ describe("PendingRecovery", () => { setupFetchProtectionRequests(bobAxios, [], [ bobRequest ], []); factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, token); + factory.setupAuthenticatedDirectoryClientMock(token); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); nodeApi.setup(instance => instance.queries.getRecoveryConfig(currentAccount)) @@ -594,7 +594,7 @@ describe("AcceptedProtection", () => { setupFetchProtectionRequests(bobAxios, [], [ bobRequest ], []); factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, token); + factory.setupAuthenticatedDirectoryClientMock(token); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); nodeApi.setup(instance => instance.queries.getRecoveryConfig(currentAccount)) @@ -662,7 +662,7 @@ describe("PendingRecovery", () => { setupFetchProtectionRequests(bobAxios, [], [ bobRequest ], []); factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, token); + factory.setupAuthenticatedDirectoryClientMock(token); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); const recoveryConfig = { diff --git a/packages/client/test/AuthenticationClient.spec.ts b/packages/client/test/AuthenticationClient.spec.ts index 4bddbbf9..d63fadef 100644 --- a/packages/client/test/AuthenticationClient.spec.ts +++ b/packages/client/test/AuthenticationClient.spec.ts @@ -16,16 +16,11 @@ import { ALICE, buildAliceTokens, buildSimpleNodeApi, - DIRECTORY_ENDPOINT } from "./Utils.js"; import { ValidAccountId } from "@logion/node-api"; describe("AuthenticationClient", () => { - it("authenticates with directory if no legal officer", async () => { - await testAuthentication([], DIRECTORY_ENDPOINT); - }); - it("authenticates with first legal officer if given", async () => { const legalOfficers = [ ALICE ]; await testAuthentication(legalOfficers, ALICE.node); @@ -56,7 +51,7 @@ describe("AuthenticationClient", () => { body.tokens[alice.toKey()] === token ))).returns(Promise.resolve(refreshResponse.object())); - const client = new AuthenticationClient(api, DIRECTORY_ENDPOINT, legalOfficers, axiosFactory.object()); + const client = new AuthenticationClient(api, legalOfficers); const refreshedTokens = await client.refresh(tokens); @@ -82,10 +77,10 @@ async function testAuthentication(legalOfficers: LegalOfficer[], expectedEndpoin setupSignIn(axiosInstance, addresses, sessionId); const api = buildSimpleNodeApi(); - const client = new AuthenticationClient(api, DIRECTORY_ENDPOINT, legalOfficers.map(legalOfficer => new LegalOfficerClass({ + const client = new AuthenticationClient(api, legalOfficers.map(legalOfficer => new LegalOfficerClass({ legalOfficer, axiosFactory: axiosFactory.object(), - })), axiosFactory.object()); + }))); const signer = new Mock(); const signature = "signature"; const signatures = [ signature ]; diff --git a/packages/client/test/Balance.spec.ts b/packages/client/test/Balance.spec.ts index b58f3aa7..2b364be6 100644 --- a/packages/client/test/Balance.spec.ts +++ b/packages/client/test/Balance.spec.ts @@ -22,7 +22,7 @@ describe("Balance", () => { testConfigFactory.setupDefaultAxiosInstanceFactory(); testConfigFactory.setupDefaultNetworkState(); const nodeApi = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + const directoryClient = testConfigFactory.setupDirectoryClientMock(); directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([])); @@ -73,7 +73,7 @@ describe("Balance", () => { const axiosFactory = testConfigFactory.setupAxiosFactoryMock(); testConfigFactory.setupDefaultNetworkState(); const nodeApi = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + const directoryClient = testConfigFactory.setupDirectoryClientMock(); setupFetchTransactions(axiosFactory, transactions, REQUESTER_ADDRESS.address) @@ -132,7 +132,7 @@ describe("Balance", () => { const axiosFactory = testConfigFactory.setupAxiosFactoryMock(); testConfigFactory.setupDefaultNetworkState(); const nodeApi = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + const directoryClient = testConfigFactory.setupDirectoryClientMock(); directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([])); @@ -201,7 +201,7 @@ describe("Balance", () => { const axiosFactory = testConfigFactory.setupAxiosFactoryMock(); testConfigFactory.setupDefaultNetworkState(); const nodeApi = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + const directoryClient = testConfigFactory.setupDirectoryClientMock(); directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([])); @@ -279,7 +279,7 @@ describe("Balance", () => { const axiosFactory = testConfigFactory.setupAxiosFactoryMock(); testConfigFactory.setupDefaultNetworkState(); const nodeApi = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + const directoryClient = testConfigFactory.setupDirectoryClientMock(); directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([])); diff --git a/packages/client/test/DirectoryClient.spec.ts b/packages/client/test/DirectoryClient.spec.ts index 6644e14e..e9201ed9 100644 --- a/packages/client/test/DirectoryClient.spec.ts +++ b/packages/client/test/DirectoryClient.spec.ts @@ -12,98 +12,100 @@ describe("DirectoryClient", () => { it("handles guest LLOs", async () => { const api = mockApi(); const axiosFactory = mockAxiosFactory(); - const client = new DirectoryClient(api, ENDPOINT, axiosFactory); + const client = new DirectoryClient(api, axiosFactory); const legalOfficers = await client.getLegalOfficers(); - expect(legalOfficers.length).toBe(2); + expect(legalOfficers.length).toBe(3); - expect(legalOfficers[0].node).toBe(BASE_URL); - expect(legalOfficers[0].account).toEqual(ValidAccountId.polkadot(HOST_ADDRESS)); + expect(legalOfficers[0].node).toBe(BASE_URLS[0]); + expect(legalOfficers[0].account).toEqual(ValidAccountId.polkadot(HOST_ADDRESSES[0])); expect(legalOfficers[0].region).toBe(REGION_TYPE); - expect(legalOfficers[0].nodeId).toBe(PEER_ID); + expect(legalOfficers[0].nodeId).toBe(PEER_IDS[0]); - expect(legalOfficers[1].node).toBe(BASE_URL); + expect(legalOfficers[1].node).toBe(BASE_URLS[0]); expect(legalOfficers[1].account).toEqual(ValidAccountId.polkadot(GUEST_ADDRESS)); expect(legalOfficers[1].region).toBe(REGION_TYPE); - expect(legalOfficers[1].nodeId).toBe(PEER_ID); + expect(legalOfficers[1].nodeId).toBe(PEER_IDS[0]); + + expect(legalOfficers[2].node).toBe(BASE_URLS[1]); + expect(legalOfficers[2].account).toEqual(ValidAccountId.polkadot(HOST_ADDRESSES[1])); + expect(legalOfficers[2].region).toBe(REGION_TYPE); + expect(legalOfficers[2].nodeId).toBe(PEER_IDS[1]); }); }); -const ENDPOINT = "https://test-directory.logion.network"; - function mockApi(): LogionNodeApiClass { const api = new Mock(); api.setup(instance => instance.polkadot.query.loAuthorityList.legalOfficerSet.entries()).returnsAsync([ [ - mockStorageKey([mockCodecWithToString(HOST_ADDRESS)]), - mockOption(mockHost()), + mockStorageKey([mockCodecWithToString(HOST_ADDRESSES[0])]), + mockOption(mockHost(BASE_URLS[0], PEER_IDS[0])), + ], + [ + mockStorageKey([mockCodecWithToString(HOST_ADDRESSES[1])]), + mockOption(mockHost(BASE_URLS[1], PEER_IDS[1])), ], [ mockStorageKey([mockCodecWithToString(GUEST_ADDRESS)]), - mockOption(mockGuest()), + mockOption(mockGuest(HOST_ADDRESSES[0])), ] ]); api.setup(instance => instance.adapters.fromLogionRuntimeRegion(REGION)).returns("Europe"); return api.object(); } -const HOST_ADDRESS = "vQvWaxNDdzuX5N3qSvGMtjdHcQdw1TAcPNgx4S1Utd3MTxYeN"; +const HOST_ADDRESSES = [ "vQvWaxNDdzuX5N3qSvGMtjdHcQdw1TAcPNgx4S1Utd3MTxYeN", "vQx5kESPn8dWyX4KxMCKqUyCaWUwtui1isX6PVNcZh2Ghjitr" ]; const GUEST_ADDRESS = "vQvZF2YMgKuQhzfF7T3xDjHjuEmcPSUVEoUDPy1mzuSXzFgca"; const REGION_TYPE: Region = "Europe"; const REGION = mockCodecWithToString(REGION_TYPE); function mockAxiosFactory(): AxiosFactory { - const axios = mockAxios(); + const axios0 = mockAxios([ HOST_ADDRESSES[0], GUEST_ADDRESS ]); + const axios1 = mockAxios([ HOST_ADDRESSES[1] ]); const factory = new Mock(); - factory.setup(instance => instance.buildAxiosInstance(ENDPOINT, undefined)).returns(axios); + factory.setup(instance => instance.buildAxiosInstance(BASE_URLS[0], undefined)).returns(axios0); + factory.setup(instance => instance.buildAxiosInstance(BASE_URLS[1], undefined)).returns(axios1); return factory.object(); } -function mockAxios(): AxiosInstance { +function mockAxios(addresses: string[]): AxiosInstance { const axios = new Mock(); const response = new Mock(); - const legalOfficers: DirectoryLegalOfficer[] = [ - { - address: HOST_ADDRESS, - additionalDetails: "", - postalAddress: EMPTY_POSTAL_ADDRESS, - userIdentity: EMPTY_USER_IDENTITY, - }, - { - address: GUEST_ADDRESS, + const legalOfficers: DirectoryLegalOfficer[] = addresses.map(address => ( { + address, additionalDetails: "", postalAddress: EMPTY_POSTAL_ADDRESS, userIdentity: EMPTY_USER_IDENTITY, - }, - ]; + } + )) response.setup(instance => instance.data.legalOfficers).returns(legalOfficers); axios.setup(instance => instance.get("/api/legal-officer")).returnsAsync(response.object()); return axios.object(); } -function mockHost(): PalletLoAuthorityListLegalOfficerData { +function mockHost(baseUrl: string, peerId: string): PalletLoAuthorityListLegalOfficerData { const host = new Mock(); host.setup(instance => instance.isHost).returns(true); const hostData = new Mock(); hostData.setup(instance => instance.baseUrl) - .returns(mockOption(mockCodecWithToUtf8(BASE_URL))); + .returns(mockOption(mockCodecWithToUtf8(baseUrl))); hostData.setup(instance => instance.nodeId) - .returns(mockOption(mockCodecWithToString(PEER_ID))); + .returns(mockOption(mockCodecWithToString(peerId))); hostData.setup(instance => instance.region) .returns(REGION); host.setup(instance => instance.asHost).returns(hostData.object()); return host.object(); } -const BASE_URL = "https://test-node.logion.network"; -const PEER_ID = "12D3KooWJvyP3VJYymTqG7eH4PM5rN4T2agk5cdNCfNymAqwqcvZ"; +const BASE_URLS = [ "https://test-node01.logion.network", "https://test-node02.logion.network" ]; +const PEER_IDS = [ "12D3KooWJvyP3VJYymTqG7eH4PM5rN4T2agk5cdNCfNymAqwqcvZ", "12D3KooWBmAwcd4PJNJvfV89HwE48nwkRmAgo8Vy3uQEyNNHBox2" ]; -function mockGuest(): PalletLoAuthorityListLegalOfficerData { +function mockGuest(hostAddress: string): PalletLoAuthorityListLegalOfficerData { const guest = new Mock(); guest.setup(instance => instance.isHost).returns(false); const guestData = new Mock(); - guestData.setup(instance => instance.hostId).returns(mockCodecWithToString(HOST_ADDRESS)); + guestData.setup(instance => instance.hostId).returns(mockCodecWithToString(hostAddress)); guest.setup(instance => instance.asGuest).returns(guestData.object()); return guest.object(); } diff --git a/packages/client/test/Environment.spec.ts b/packages/client/test/Environment.spec.ts index 1ebab878..2be807ce 100644 --- a/packages/client/test/Environment.spec.ts +++ b/packages/client/test/Environment.spec.ts @@ -12,13 +12,11 @@ describe("Environment", () => { it("creates config from environment", () => { const config = createLogionClientConfig(Environment.TEST, () => fileUploader); - expect(config.directoryEndpoint).toEqual("https://test-directory.logion.network"); expect(config.rpcEndpoints).toEqual([ "wss://test-para-rpc01.logion.network" ]); }) it("creates config from environment string", () => { const config = createLogionClientConfig("TEST", () => fileUploader); - expect(config.directoryEndpoint).toEqual("https://test-directory.logion.network"); expect(config.rpcEndpoints).toEqual([ "wss://test-para-rpc01.logion.network" ]); }) diff --git a/packages/client/test/Loc.spec.ts b/packages/client/test/Loc.spec.ts index 2ac4d812..6516cac5 100644 --- a/packages/client/test/Loc.spec.ts +++ b/packages/client/test/Loc.spec.ts @@ -1002,7 +1002,7 @@ async function buildSharedState(isVerifiedIssuer: boolean = false): Promise { factory.setupDefaultNetworkState(); factory.setupFileUploaderMock(); - factory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, token); + factory.setupAuthenticatedDirectoryClientMock(token); const axiosFactoryMock = factory.setupAxiosFactoryMock(); uploaderMock = factory.setupFileUploaderMock(); diff --git a/packages/client/test/LogionClient.spec.ts b/packages/client/test/LogionClient.spec.ts index 76811c7f..6d0e1ac6 100644 --- a/packages/client/test/LogionClient.spec.ts +++ b/packages/client/test/LogionClient.spec.ts @@ -10,7 +10,6 @@ import { import { ALICE, BOB, - DIRECTORY_ENDPOINT, buildAliceAndBobTokens, buildAliceTokens, buildAuthenticatedSharedStateUsingTestConfig, @@ -30,7 +29,7 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultAxiosInstanceFactory(); testConfigFactory.setupDefaultNetworkState(); testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + const directoryClient = testConfigFactory.setupDirectoryClientMock(); directoryClient.setup(instance => instance.getLegalOfficers()) .returns(Promise.resolve(testConfigFactory.buildLegalOfficerClasses(clientLegalOfficers))); }); @@ -50,10 +49,10 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultAxiosInstanceFactory(); testConfigFactory.setupDefaultNetworkState(); api = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + const directoryClient = testConfigFactory.setupDirectoryClientMock(); directoryClient.setup(instance => instance.getLegalOfficers()) .returns(Promise.resolve(testConfigFactory.buildLegalOfficerClasses(clientLegalOfficers))); - testConfigFactory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, token); + testConfigFactory.setupAuthenticatedDirectoryClientMock(token); }); const client = await LogionClient.create(config); @@ -75,16 +74,16 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultNetworkState(); testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + const directoryClient = testConfigFactory.setupDirectoryClientMock(); const legalOfficerClasses = testConfigFactory.buildLegalOfficerClasses(clientLegalOfficers); directoryClient.setup(instance => instance.getLegalOfficers()) .returns(Promise.resolve(legalOfficerClasses)); - const authenticationClient = testConfigFactory.setupAuthenticationClientMock(LOGION_CLIENT_CONFIG, clientLegalOfficers); + const authenticationClient = testConfigFactory.setupAuthenticationClientMock(clientLegalOfficers); authenticationClient.setup(instance => instance.authenticate(addresses, signer.object())) .returns(Promise.resolve(tokens)); - testConfigFactory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, token); + testConfigFactory.setupAuthenticatedDirectoryClientMock(token); }); const client = await LogionClient.create(config); @@ -104,8 +103,8 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultAxiosInstanceFactory(); testConfigFactory.setupDefaultNetworkState(); testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - testConfigFactory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, tokens.get(alice)!.value); - authenticationClient = testConfigFactory.setupAuthenticationClientMock(LOGION_CLIENT_CONFIG, legalOfficers); + testConfigFactory.setupAuthenticatedDirectoryClientMock(tokens.get(alice)!.value); + authenticationClient = testConfigFactory.setupAuthenticationClientMock(legalOfficers); authenticationClient.setup(instance => instance.refresh(tokens)).returns(Promise.resolve(tokens)); }, alice, legalOfficers, tokens); const client = new LogionClient({ ...sharedState }); @@ -124,8 +123,8 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultAxiosInstanceFactory(); testConfigFactory.setupDefaultNetworkState(); testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - testConfigFactory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, tokens.get(alice)!.value); - authenticationClient = testConfigFactory.setupAuthenticationClientMock(LOGION_CLIENT_CONFIG, legalOfficers); + testConfigFactory.setupAuthenticatedDirectoryClientMock(tokens.get(alice)!.value); + authenticationClient = testConfigFactory.setupAuthenticationClientMock(legalOfficers); authenticationClient.setup(instance => instance.refresh(tokens)).returns(Promise.resolve(tokens)); }, alice, legalOfficers, tokens); const client = new LogionClient({ ...sharedState }); @@ -144,9 +143,9 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultNetworkState(); const api = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); const alice = ALICE.account; - testConfigFactory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, tokens.get(alice)!.value); + testConfigFactory.setupAuthenticatedDirectoryClientMock(tokens.get(alice)!.value); const bob = BOB.account; - testConfigFactory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, tokens.get(bob)!.value); + testConfigFactory.setupAuthenticatedDirectoryClientMock(tokens.get(bob)!.value); const config = testConfigFactory.buildTestConfig(LOGION_CLIENT_CONFIG); const sharedState = await buildAuthenticatedSharedStateUsingTestConfig(config, alice, legalOfficers, tokens); @@ -155,7 +154,7 @@ describe("LogionClient", () => { const bobClient = aliceClient.withCurrentAccount(bob); expect(bobClient.currentAccount).toBe(bob); - testConfigFactory.verifyComponentFactory(instance => instance.buildDirectoryClient(api.object(), DIRECTORY_ENDPOINT, It.IsAny(), tokens.get(bob)!.value)); + testConfigFactory.verifyComponentFactory(instance => instance.buildDirectoryClient(api.object(), It.IsAny(), tokens.get(bob)!.value)); }); it("logs out", async () => { @@ -167,8 +166,8 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultAxiosInstanceFactory(); testConfigFactory.setupDefaultNetworkState(); testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - testConfigFactory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, tokens.get(alice)!.value); - testConfigFactory.setupAuthenticationClientMock(LOGION_CLIENT_CONFIG, legalOfficers); + testConfigFactory.setupAuthenticatedDirectoryClientMock(tokens.get(alice)!.value); + testConfigFactory.setupAuthenticationClientMock(legalOfficers); }, alice, legalOfficers, tokens); const authenticatedClient = new LogionClient({ ...sharedState }); diff --git a/packages/client/test/Public.spec.ts b/packages/client/test/Public.spec.ts index 6a121d30..7ebb5639 100644 --- a/packages/client/test/Public.spec.ts +++ b/packages/client/test/Public.spec.ts @@ -176,7 +176,7 @@ async function buildSharedState(): Promise { (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); factory.setupFileUploaderMock(); - factory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + factory.setupDirectoryClientMock(); const axiosFactoryMock = factory.setupAxiosFactoryMock(); diff --git a/packages/client/test/RecoveryReview.spec.ts b/packages/client/test/RecoveryReview.spec.ts index 60927aee..3a750c8b 100644 --- a/packages/client/test/RecoveryReview.spec.ts +++ b/packages/client/test/RecoveryReview.spec.ts @@ -72,7 +72,7 @@ function setupConfig(axios: Mock): LogionClientConfig { .returns(axios.object()); setupBackend(axios); testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + const directoryClient = testConfigFactory.setupDirectoryClientMock(); directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([ new LegalOfficerClass({ legalOfficer: ALICE, diff --git a/packages/client/test/SecretRecovery.spec.ts b/packages/client/test/SecretRecovery.spec.ts index 34c28e84..1bb38c30 100644 --- a/packages/client/test/SecretRecovery.spec.ts +++ b/packages/client/test/SecretRecovery.spec.ts @@ -50,7 +50,7 @@ function configure() { axiosFactory.setup(instance => instance.buildAxiosInstance(It.IsAny(), It.IsAny())) .returns(axios.object()); const nodeApi = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + const directoryClient = testConfigFactory.setupDirectoryClientMock(); directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([ new LegalOfficerClass({ diff --git a/packages/client/test/TestConfigFactory.ts b/packages/client/test/TestConfigFactory.ts index 52f92497..37dcc826 100644 --- a/packages/client/test/TestConfigFactory.ts +++ b/packages/client/test/TestConfigFactory.ts @@ -42,26 +42,25 @@ export class TestConfigFactory { return nodeApi; } - setupDirectoryClientMock(config: LogionClientConfig): Mock { + setupDirectoryClientMock(): Mock { const directoryClient = new Mock(); - this._componentFactory.setup(instance => instance.buildDirectoryClient(It.IsAny(), config.directoryEndpoint, It.IsAny())) + this._componentFactory.setup(instance => instance.buildDirectoryClient(It.IsAny(), It.IsAny())) .returns(directoryClient.object()); return directoryClient; } - setupAuthenticatedDirectoryClientMock(config: LogionClientConfig, token: string): Mock { + setupAuthenticatedDirectoryClientMock(token: string): Mock { const directoryClient = new Mock(); - this._componentFactory.setup(instance => instance.buildDirectoryClient(It.IsAny(), config.directoryEndpoint, It.IsAny(), token)) + this._componentFactory.setup(instance => instance.buildDirectoryClient(It.IsAny(), It.IsAny(), token)) .returns(directoryClient.object()); return directoryClient; } - setupAuthenticationClientMock(config: LogionClientConfig, legalOfficers: LegalOfficer[]): Mock { + setupAuthenticationClientMock(legalOfficers: LegalOfficer[]): Mock { const authenticationClient = new Mock(); this._componentFactory.setup(instance => instance.buildAuthenticationClient( It.IsAny(), - config.directoryEndpoint, - It.Is(value => legalOfficers.map(lo => lo.account).every(item => value.map(lo => lo.account.address).includes(item.address))), It.IsAny() + It.Is(value => legalOfficers.map(lo => lo.account).every(item => value.map(lo => lo.account.address).includes(item.address))) )).returns(authenticationClient.object()); return authenticationClient; } diff --git a/packages/client/test/Utils.ts b/packages/client/test/Utils.ts index 7ff736c7..9f4f3a7f 100644 --- a/packages/client/test/Utils.ts +++ b/packages/client/test/Utils.ts @@ -64,8 +64,6 @@ export const CHARLIE: LegalOfficer = { export const LEGAL_OFFICERS = [ ALICE, BOB, CHARLIE ]; -export const DIRECTORY_ENDPOINT = "https://directory.logion.network"; - export function buildAliceTokens(api: LogionNodeApiClass, expirationDateTime: DateTime): AccountTokens { return new AccountTokens(api, { [`Polkadot:${ALICE.account.address}`]: { @@ -93,7 +91,6 @@ export const LOGION_CLASSIFICATION_LOC_ID = new UUID(); export const LOGION_CLIENT_CONFIG: LogionClientConfig = { rpcEndpoints: [ "wss://rpc.logion.network" ], - directoryEndpoint: DIRECTORY_ENDPOINT, buildFileUploader: () => new Mock().object(), creativeCommonsLoc: CREATIVE_COMMONS_LOC_ID, logionClassificationLoc: LOGION_CLASSIFICATION_LOC_ID, @@ -117,7 +114,7 @@ export async function buildAuthenticatedSharedStateUsingTestConfig( ): Promise { const componentFactory = (config as any).__componentFactory; const axiosFactory = componentFactory.buildAxiosFactory(); - const directoryClient = componentFactory.buildDirectoryClient(config.directoryEndpoint, axiosFactory); + const directoryClient = componentFactory.buildDirectoryClient(axiosFactory); const nodesUp: LegalOfficerEndpoint[] = legalOfficers.map(legalOfficer => ({ url: legalOfficer.node, legalOfficer: legalOfficer.account.address })); const networkState = componentFactory.buildNetworkState(nodesUp, []); const nodeApi = await componentFactory.buildNodeApi(config.rpcEndpoints); diff --git a/packages/client/test/Vault.spec.ts b/packages/client/test/Vault.spec.ts index 8796347f..719df2c5 100644 --- a/packages/client/test/Vault.spec.ts +++ b/packages/client/test/Vault.spec.ts @@ -80,7 +80,7 @@ describe("Vault", () => { const sharedState = await buildTestAuthenticatedSharedSate( (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); - factory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + factory.setupDirectoryClientMock(); factory.setupAxiosFactoryMock(); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); @@ -156,7 +156,7 @@ describe("Vault", () => { const sharedState = await buildTestAuthenticatedSharedSate( (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); - factory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + factory.setupDirectoryClientMock(); factory.setupAxiosFactoryMock(); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); @@ -233,7 +233,7 @@ describe("Vault", () => { const sharedState = await buildTestAuthenticatedSharedSate( (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); - factory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + factory.setupDirectoryClientMock(); factory.setupAxiosFactoryMock(); factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); }, @@ -302,7 +302,7 @@ describe("Vault", () => { const sharedState = await buildTestAuthenticatedSharedSate( (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); - factory.setupDirectoryClientMock(LOGION_CLIENT_CONFIG); + factory.setupDirectoryClientMock(); factory.setupAxiosFactoryMock(); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); diff --git a/packages/client/test/Voter.spec.ts b/packages/client/test/Voter.spec.ts index ebc6b80a..4beb07dc 100644 --- a/packages/client/test/Voter.spec.ts +++ b/packages/client/test/Voter.spec.ts @@ -61,7 +61,7 @@ async function buildSharedState(): Promise { (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); factory.setupFileUploaderMock(); - factory.setupAuthenticatedDirectoryClientMock(LOGION_CLIENT_CONFIG, token); + factory.setupAuthenticatedDirectoryClientMock(token); const axiosFactoryMock = factory.setupAxiosFactoryMock(); From 984b95ff96339ff2d37d8cea7ce9bd27ea0641ee Mon Sep 17 00:00:00 2001 From: Benoit Devos Date: Tue, 18 Jun 2024 15:04:56 +0200 Subject: [PATCH 2/2] feat: implement feedback from peer-review. logion-network/logion-internal#1292 --- .../client-node/integration/LegalOfficer.ts | 4 +-- packages/client/src/ComponentFactory.ts | 6 ++-- ...rectoryClient.ts => LegalOfficerClient.ts} | 11 ++++---- packages/client/src/LogionClient.ts | 24 ++++++++-------- packages/client/src/SharedClient.ts | 4 +-- packages/client/src/index.ts | 2 +- packages/client/test/AccountRecovery.spec.ts | 14 +++++----- packages/client/test/Balance.spec.ts | 20 ++++++------- packages/client/test/DirectoryClient.spec.ts | 8 +++--- packages/client/test/Loc.spec.ts | 2 +- packages/client/test/LogionClient.spec.ts | 28 +++++++++---------- packages/client/test/Public.spec.ts | 2 +- packages/client/test/RecoveryReview.spec.ts | 4 +-- packages/client/test/SecretRecovery.spec.ts | 4 +-- packages/client/test/TestConfigFactory.ts | 22 +++++++-------- packages/client/test/Utils.ts | 4 +-- packages/client/test/Vault.spec.ts | 8 +++--- packages/client/test/Voter.spec.ts | 2 +- 18 files changed, 85 insertions(+), 84 deletions(-) rename packages/client/src/{DirectoryClient.ts => LegalOfficerClient.ts} (94%) diff --git a/packages/client-node/integration/LegalOfficer.ts b/packages/client-node/integration/LegalOfficer.ts index f34eec20..ed52820f 100644 --- a/packages/client-node/integration/LegalOfficer.ts +++ b/packages/client-node/integration/LegalOfficer.ts @@ -43,8 +43,8 @@ export async function updateLegalOfficer(state: State) { additionalDetails: "Some new details", } as LegalOfficer; const aliceClient = client.withCurrentAccount(alice.account); - await aliceClient.directoryClient.createOrUpdate(updatedAlice); - const legalOfficers = await client.directoryClient.getLegalOfficers(); + await aliceClient.legalOfficerClient.createOrUpdate(updatedAlice); + const legalOfficers = await client.legalOfficerClient.getLegalOfficers(); const legalOfficer = legalOfficers.find(legalOfficer => legalOfficer.account.equals(alice.account)) expect(legalOfficer?.userIdentity).toEqual(updatedAlice.userIdentity); expect(legalOfficer?.postalAddress).toEqual(updatedAlice.postalAddress); diff --git a/packages/client/src/ComponentFactory.ts b/packages/client/src/ComponentFactory.ts index 84afcaea..30347345 100644 --- a/packages/client/src/ComponentFactory.ts +++ b/packages/client/src/ComponentFactory.ts @@ -1,7 +1,7 @@ import { LogionNodeApiClass, Hash } from "@logion/node-api"; import { AuthenticationClient } from "./AuthenticationClient.js"; import { AxiosFactory } from "./AxiosFactory.js"; -import { DirectoryClient } from "./DirectoryClient.js"; +import { LegalOfficerClient } from "./LegalOfficerClient.js"; import { NetworkState } from "./NetworkState.js"; import { LegalOfficerEndpoint } from "./SharedClient.js"; import { LegalOfficerClass } from "./Types.js"; @@ -83,7 +83,7 @@ export abstract class AxiosFileUploader implements FileUploader { export interface CoreComponentFactory { buildAxiosFactory: () => AxiosFactory; - buildDirectoryClient: (api: LogionNodeApiClass, axiosFactory: AxiosFactory, token?: string) => DirectoryClient; + buildLegalOfficerClient: (api: LogionNodeApiClass, axiosFactory: AxiosFactory, token?: string) => LegalOfficerClient; buildAuthenticationClient: (api: LogionNodeApiClass, legalOfficers: LegalOfficerClass[]) => AuthenticationClient; buildNetworkState(nodesUp: LegalOfficerEndpoint[], nodesDown: LegalOfficerEndpoint[]): NetworkState; buildNodeApi(rpcEndpoints: string[]): Promise; @@ -91,7 +91,7 @@ export interface CoreComponentFactory { export const CoreComponentFactoryInstance: CoreComponentFactory = { buildAxiosFactory: () => new AxiosFactory(), - buildDirectoryClient: (api: LogionNodeApiClass, axiosFactory: AxiosFactory, token?: string) => new DirectoryClient(api, axiosFactory, token), + buildLegalOfficerClient: (api: LogionNodeApiClass, axiosFactory: AxiosFactory, token?: string) => new LegalOfficerClient(api, axiosFactory, token), buildAuthenticationClient: (api: LogionNodeApiClass, legalOfficers: LegalOfficerClass[]) => new AuthenticationClient(api, legalOfficers), buildNetworkState: (nodesUp: LegalOfficerEndpoint[], nodesDown: LegalOfficerEndpoint[]) => new NetworkState(nodesUp, nodesDown), buildNodeApi: (rpcEndpoints: string[]) => LogionNodeApiClass.connect(rpcEndpoints), diff --git a/packages/client/src/DirectoryClient.ts b/packages/client/src/LegalOfficerClient.ts similarity index 94% rename from packages/client/src/DirectoryClient.ts rename to packages/client/src/LegalOfficerClient.ts index b8dbd1eb..51a59314 100644 --- a/packages/client/src/DirectoryClient.ts +++ b/packages/client/src/LegalOfficerClient.ts @@ -9,7 +9,7 @@ import { LegalOfficer, LegalOfficerClass, LegalOfficerPostalAddress, UserIdentit import { MultiSourceHttpClient, aggregateArrays, Endpoint, MultiSourceHttpClientState } from "./Http.js"; import { newBackendError } from "./Error.js"; -export interface DirectoryLegalOfficer { +interface BackendLegalOfficer { userIdentity: UserIdentity; postalAddress: LegalOfficerPostalAddress; address: string; @@ -23,7 +23,7 @@ export interface CreateOrUpdateLegalOfficer { additionalDetails: string; } -export class DirectoryClient { +export class LegalOfficerClient { constructor(api: LogionNodeApiClass, axiosFactory: AxiosFactory, token?: string) { this.authenticated = token !== undefined; @@ -56,7 +56,7 @@ export class DirectoryClient { onchainMap: Record ): Promise { const offchain = (await axios.get("/api/legal-officer") - .then(response => response.data.legalOfficers)) as DirectoryLegalOfficer[]; + .then(response => response.data.legalOfficers)) as BackendLegalOfficer[]; const offchainMap = this.toOffchainMap(offchain); const legalOfficers = []; for(const address in offchainMap) { @@ -72,14 +72,15 @@ export class DirectoryClient { legalOfficers.push(new LegalOfficerClass({ legalOfficer, axiosFactory: this.axiosFactory, + token: this.token, })); } } return legalOfficers; } - private toOffchainMap(array: DirectoryLegalOfficer[]): Record { - const map: Record = {}; + private toOffchainMap(array: BackendLegalOfficer[]): Record { + const map: Record = {}; array.forEach(item => { map[item.address] = item; }); return map; } diff --git a/packages/client/src/LogionClient.ts b/packages/client/src/LogionClient.ts index bbd09721..c367188a 100644 --- a/packages/client/src/LogionClient.ts +++ b/packages/client/src/LogionClient.ts @@ -5,7 +5,7 @@ import { LogionNodeApiClass, UUID, ValidAccountId } from "@logion/node-api"; import { AccountTokens } from "./AuthenticationClient.js"; import { BalanceState, getBalanceState } from "./Balance.js"; import { ComponentFactory, buildComponentFactory } from "./ComponentFactory.js"; -import { DirectoryClient } from "./DirectoryClient.js"; +import { LegalOfficerClient } from "./LegalOfficerClient.js"; import { initMultiSourceHttpClientState, MultiSourceHttpClient, Token } from "./Http.js"; import { getInitialState, ProtectionState } from "./AccountRecovery.js"; import { AccountRecoveryClient } from "./AccountRecoveryClient.js"; @@ -45,18 +45,18 @@ export class LogionClient { const componentFactory = getComponentFactory(config); const axiosFactory = componentFactory.buildAxiosFactory(); const nodeApi = await componentFactory.buildNodeApi(config.rpcEndpoints); - const directoryClient = componentFactory.buildDirectoryClient( + const legalOfficerClient = componentFactory.buildLegalOfficerClient( nodeApi, axiosFactory, ); - const allLegalOfficers = await directoryClient.getLegalOfficers(); + const allLegalOfficers = await legalOfficerClient.getLegalOfficers(); const legalOfficers = allLegalOfficers.filter(legalOfficer => legalOfficer.node); const nodesUp: LegalOfficerEndpoint[] = legalOfficers.map(legalOfficer => ({ url: legalOfficer.node, legalOfficer: legalOfficer.account.address })); const sharedState: SharedState = { config, componentFactory, axiosFactory, - directoryClient, + legalOfficerClient, nodeApi, legalOfficers, allLegalOfficers, @@ -122,8 +122,8 @@ export class LogionClient { /** * An instance of Directory client. */ - get directoryClient(): DirectoryClient { - return this.sharedState.directoryClient; + get legalOfficerClient(): LegalOfficerClient { + return this.sharedState.legalOfficerClient; } /** @@ -216,15 +216,15 @@ export class LogionClient { */ withCurrentAccount(currentAccount?: ValidAccountId): LogionClient { this.ensureConnected(); - let directoryClient: DirectoryClient; + let legalOfficerClient: LegalOfficerClient; if(currentAccount !== undefined) { - directoryClient = this.sharedState.componentFactory.buildDirectoryClient( + legalOfficerClient = this.sharedState.componentFactory.buildLegalOfficerClient( this.sharedState.nodeApi, this.sharedState.axiosFactory, this.sharedState.tokens.get(currentAccount)?.value, ); } else { - directoryClient = this.sharedState.componentFactory.buildDirectoryClient( + legalOfficerClient = this.sharedState.componentFactory.buildLegalOfficerClient( this.sharedState.nodeApi, this.sharedState.axiosFactory, ); @@ -234,7 +234,7 @@ export class LogionClient { return new LogionClient({ ...sharedState, currentAccount, - directoryClient, + legalOfficerClient, }); } @@ -244,7 +244,7 @@ export class LogionClient { */ logout(): LogionClient { this.ensureConnected(); - const directoryClient = this.sharedState.componentFactory.buildDirectoryClient( + const legalOfficerClient = this.sharedState.componentFactory.buildLegalOfficerClient( this.sharedState.nodeApi, this.sharedState.axiosFactory ); @@ -252,7 +252,7 @@ export class LogionClient { ...this.sharedState, tokens: new AccountTokens(this.sharedState.nodeApi, {}), currentAccount: undefined, - directoryClient, + legalOfficerClient, }); } diff --git a/packages/client/src/SharedClient.ts b/packages/client/src/SharedClient.ts index 38e4baa9..a1208c2a 100644 --- a/packages/client/src/SharedClient.ts +++ b/packages/client/src/SharedClient.ts @@ -4,7 +4,7 @@ import { AccountTokens } from "./AuthenticationClient.js"; import { AxiosFactory } from "./AxiosFactory.js"; import { findOrThrow } from "./Collections.js"; import { ComponentFactory, FileUploader } from "./ComponentFactory.js"; -import { DirectoryClient } from "./DirectoryClient.js"; +import { LegalOfficerClient } from "./LegalOfficerClient.js"; import { Endpoint, Token } from "./Http.js"; import { NetworkState } from "./NetworkState.js"; import { LegalOfficerClass } from "./Types.js"; @@ -25,7 +25,7 @@ export interface SharedState { config: LogionClientConfig; componentFactory: ComponentFactory; axiosFactory: AxiosFactory; - directoryClient: DirectoryClient; + legalOfficerClient: LegalOfficerClient; networkState: NetworkState; nodeApi: LogionNodeApiClass; legalOfficers: LegalOfficerClass[]; diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index 8c1da6b3..97358d2a 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -19,7 +19,7 @@ export * from './Balance.js'; export * from './CollectionItem.js'; export * from './ComponentFactory.js'; export * from './DateTimeUtil.js'; -export * from './DirectoryClient.js'; +export * from './LegalOfficerClient.js'; export * from './Environment.js'; export * from './Ethereum.js'; export * from './Hash.js'; diff --git a/packages/client/test/AccountRecovery.spec.ts b/packages/client/test/AccountRecovery.spec.ts index d24c4c8d..c6a57f68 100644 --- a/packages/client/test/AccountRecovery.spec.ts +++ b/packages/client/test/AccountRecovery.spec.ts @@ -168,7 +168,7 @@ async function buildSharedState(): Promise { (factory: TestConfigFactory) => { factory.setupDefaultAxiosInstanceFactory(); factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(token); + factory.setupAuthenticatedLegalOfficerClientMock(token); factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); }, currentAccount, @@ -284,7 +284,7 @@ describe("NoProtection", () => { setupFetchProtectionRequests(bobAxios, [], [], []); factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(token); + factory.setupAuthenticatedLegalOfficerClientMock(token); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); nodeApi.setup(instance => instance.queries.getRecoveryConfig(currentAccount)) @@ -339,7 +339,7 @@ describe("NoProtection", () => { const sharedState = await buildTestAuthenticatedSharedSate( (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(token); + factory.setupAuthenticatedLegalOfficerClientMock(token); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); nodeApi.setup(instance => instance.queries.getActiveRecovery(RECOVERED_ADDRESS, currentAccount)) @@ -453,7 +453,7 @@ describe("PendingRecovery", () => { setupFetchProtectionRequests(bobAxios, [ bobRequest ], [], []); factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(token); + factory.setupAuthenticatedLegalOfficerClientMock(token); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); nodeApi.setup(instance => instance.queries.getRecoveryConfig(currentAccount)) @@ -506,7 +506,7 @@ describe("PendingRecovery", () => { setupFetchProtectionRequests(bobAxios, [], [ bobRequest ], []); factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(token); + factory.setupAuthenticatedLegalOfficerClientMock(token); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); nodeApi.setup(instance => instance.queries.getRecoveryConfig(currentAccount)) @@ -594,7 +594,7 @@ describe("AcceptedProtection", () => { setupFetchProtectionRequests(bobAxios, [], [ bobRequest ], []); factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(token); + factory.setupAuthenticatedLegalOfficerClientMock(token); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); nodeApi.setup(instance => instance.queries.getRecoveryConfig(currentAccount)) @@ -662,7 +662,7 @@ describe("PendingRecovery", () => { setupFetchProtectionRequests(bobAxios, [], [ bobRequest ], []); factory.setupDefaultNetworkState(); - factory.setupAuthenticatedDirectoryClientMock(token); + factory.setupAuthenticatedLegalOfficerClientMock(token); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); const recoveryConfig = { diff --git a/packages/client/test/Balance.spec.ts b/packages/client/test/Balance.spec.ts index 2b364be6..d14dc95b 100644 --- a/packages/client/test/Balance.spec.ts +++ b/packages/client/test/Balance.spec.ts @@ -22,9 +22,9 @@ describe("Balance", () => { testConfigFactory.setupDefaultAxiosInstanceFactory(); testConfigFactory.setupDefaultNetworkState(); const nodeApi = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(); + const legalOfficerClient = testConfigFactory.setupLegalOfficerClientMock(); - directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([])); + legalOfficerClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([])); nodeApi.setup(instance => instance.queries.getAccountData(REQUESTER_ADDRESS)) .returns(Promise.resolve(BALANCE)); @@ -73,11 +73,11 @@ describe("Balance", () => { const axiosFactory = testConfigFactory.setupAxiosFactoryMock(); testConfigFactory.setupDefaultNetworkState(); const nodeApi = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(); + const legalOfficerClient = testConfigFactory.setupLegalOfficerClientMock(); setupFetchTransactions(axiosFactory, transactions, REQUESTER_ADDRESS.address) - directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([ new LegalOfficerClass({ + legalOfficerClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([ new LegalOfficerClass({ legalOfficer: ALICE, axiosFactory: axiosFactory.object(), }) ])); @@ -132,9 +132,9 @@ describe("Balance", () => { const axiosFactory = testConfigFactory.setupAxiosFactoryMock(); testConfigFactory.setupDefaultNetworkState(); const nodeApi = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(); + const legalOfficerClient = testConfigFactory.setupLegalOfficerClientMock(); - directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([])); + legalOfficerClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([])); nodeApi.setup(instance => instance.queries.getAccountData(REQUESTER_ADDRESS)) .returns(Promise.resolve(BALANCE)); @@ -201,9 +201,9 @@ describe("Balance", () => { const axiosFactory = testConfigFactory.setupAxiosFactoryMock(); testConfigFactory.setupDefaultNetworkState(); const nodeApi = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(); + const legalOfficerClient = testConfigFactory.setupLegalOfficerClientMock(); - directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([])); + legalOfficerClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([])); nodeApi.setup(instance => instance.queries.getAccountData(REQUESTER_ADDRESS)) .returns(Promise.resolve(BALANCE)); @@ -279,9 +279,9 @@ describe("Balance", () => { const axiosFactory = testConfigFactory.setupAxiosFactoryMock(); testConfigFactory.setupDefaultNetworkState(); const nodeApi = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(); + const legalOfficerClient = testConfigFactory.setupLegalOfficerClientMock(); - directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([])); + legalOfficerClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([])); nodeApi.setup(instance => instance.queries.getAccountData(REQUESTER_ADDRESS)) .returns(Promise.resolve(BALANCE)); diff --git a/packages/client/test/DirectoryClient.spec.ts b/packages/client/test/DirectoryClient.spec.ts index e9201ed9..926e5653 100644 --- a/packages/client/test/DirectoryClient.spec.ts +++ b/packages/client/test/DirectoryClient.spec.ts @@ -4,15 +4,15 @@ import { Mock } from "moq.ts"; import { AccountId32 } from "@polkadot/types/interfaces/types.js"; import type { Bytes } from '@polkadot/types-codec'; import { PalletLoAuthorityListLegalOfficerData, PalletLoAuthorityListHostData, PalletLoAuthorityListGuestData, LogionRuntimeRegion } from "@polkadot/types/lookup"; -import { AxiosFactory, DirectoryClient, DirectoryLegalOfficer } from "../src/index.js"; +import { AxiosFactory, LegalOfficerClient } from "../src/index.js"; import { EMPTY_POSTAL_ADDRESS, EMPTY_USER_IDENTITY, mockCodecWithToString, mockCodecWithToUtf8, mockOption, mockStorageKey } from "./Utils.js"; -describe("DirectoryClient", () => { +describe("LegalOfficerClient", () => { it("handles guest LLOs", async () => { const api = mockApi(); const axiosFactory = mockAxiosFactory(); - const client = new DirectoryClient(api, axiosFactory); + const client = new LegalOfficerClient(api, axiosFactory); const legalOfficers = await client.getLegalOfficers(); @@ -72,7 +72,7 @@ function mockAxiosFactory(): AxiosFactory { function mockAxios(addresses: string[]): AxiosInstance { const axios = new Mock(); const response = new Mock(); - const legalOfficers: DirectoryLegalOfficer[] = addresses.map(address => ( { + const legalOfficers = addresses.map(address => ( { address, additionalDetails: "", postalAddress: EMPTY_POSTAL_ADDRESS, diff --git a/packages/client/test/Loc.spec.ts b/packages/client/test/Loc.spec.ts index 6516cac5..cf6494ad 100644 --- a/packages/client/test/Loc.spec.ts +++ b/packages/client/test/Loc.spec.ts @@ -1002,7 +1002,7 @@ async function buildSharedState(isVerifiedIssuer: boolean = false): Promise { factory.setupDefaultNetworkState(); factory.setupFileUploaderMock(); - factory.setupAuthenticatedDirectoryClientMock(token); + factory.setupAuthenticatedLegalOfficerClientMock(token); const axiosFactoryMock = factory.setupAxiosFactoryMock(); uploaderMock = factory.setupFileUploaderMock(); diff --git a/packages/client/test/LogionClient.spec.ts b/packages/client/test/LogionClient.spec.ts index 6d0e1ac6..3c89a1c6 100644 --- a/packages/client/test/LogionClient.spec.ts +++ b/packages/client/test/LogionClient.spec.ts @@ -29,8 +29,8 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultAxiosInstanceFactory(); testConfigFactory.setupDefaultNetworkState(); testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(); - directoryClient.setup(instance => instance.getLegalOfficers()) + const legalOfficerClient = testConfigFactory.setupLegalOfficerClientMock(); + legalOfficerClient.setup(instance => instance.getLegalOfficers()) .returns(Promise.resolve(testConfigFactory.buildLegalOfficerClasses(clientLegalOfficers))); }); const client = await LogionClient.create(config); @@ -49,10 +49,10 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultAxiosInstanceFactory(); testConfigFactory.setupDefaultNetworkState(); api = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(); - directoryClient.setup(instance => instance.getLegalOfficers()) + const legalOfficerClient = testConfigFactory.setupLegalOfficerClientMock(); + legalOfficerClient.setup(instance => instance.getLegalOfficers()) .returns(Promise.resolve(testConfigFactory.buildLegalOfficerClasses(clientLegalOfficers))); - testConfigFactory.setupAuthenticatedDirectoryClientMock(token); + testConfigFactory.setupAuthenticatedLegalOfficerClientMock(token); }); const client = await LogionClient.create(config); @@ -74,16 +74,16 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultNetworkState(); testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(); + const legalOfficerClient = testConfigFactory.setupLegalOfficerClientMock(); const legalOfficerClasses = testConfigFactory.buildLegalOfficerClasses(clientLegalOfficers); - directoryClient.setup(instance => instance.getLegalOfficers()) + legalOfficerClient.setup(instance => instance.getLegalOfficers()) .returns(Promise.resolve(legalOfficerClasses)); const authenticationClient = testConfigFactory.setupAuthenticationClientMock(clientLegalOfficers); authenticationClient.setup(instance => instance.authenticate(addresses, signer.object())) .returns(Promise.resolve(tokens)); - testConfigFactory.setupAuthenticatedDirectoryClientMock(token); + testConfigFactory.setupAuthenticatedLegalOfficerClientMock(token); }); const client = await LogionClient.create(config); @@ -103,7 +103,7 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultAxiosInstanceFactory(); testConfigFactory.setupDefaultNetworkState(); testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - testConfigFactory.setupAuthenticatedDirectoryClientMock(tokens.get(alice)!.value); + testConfigFactory.setupAuthenticatedLegalOfficerClientMock(tokens.get(alice)!.value); authenticationClient = testConfigFactory.setupAuthenticationClientMock(legalOfficers); authenticationClient.setup(instance => instance.refresh(tokens)).returns(Promise.resolve(tokens)); }, alice, legalOfficers, tokens); @@ -123,7 +123,7 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultAxiosInstanceFactory(); testConfigFactory.setupDefaultNetworkState(); testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - testConfigFactory.setupAuthenticatedDirectoryClientMock(tokens.get(alice)!.value); + testConfigFactory.setupAuthenticatedLegalOfficerClientMock(tokens.get(alice)!.value); authenticationClient = testConfigFactory.setupAuthenticationClientMock(legalOfficers); authenticationClient.setup(instance => instance.refresh(tokens)).returns(Promise.resolve(tokens)); }, alice, legalOfficers, tokens); @@ -143,9 +143,9 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultNetworkState(); const api = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); const alice = ALICE.account; - testConfigFactory.setupAuthenticatedDirectoryClientMock(tokens.get(alice)!.value); + testConfigFactory.setupAuthenticatedLegalOfficerClientMock(tokens.get(alice)!.value); const bob = BOB.account; - testConfigFactory.setupAuthenticatedDirectoryClientMock(tokens.get(bob)!.value); + testConfigFactory.setupAuthenticatedLegalOfficerClientMock(tokens.get(bob)!.value); const config = testConfigFactory.buildTestConfig(LOGION_CLIENT_CONFIG); const sharedState = await buildAuthenticatedSharedStateUsingTestConfig(config, alice, legalOfficers, tokens); @@ -154,7 +154,7 @@ describe("LogionClient", () => { const bobClient = aliceClient.withCurrentAccount(bob); expect(bobClient.currentAccount).toBe(bob); - testConfigFactory.verifyComponentFactory(instance => instance.buildDirectoryClient(api.object(), It.IsAny(), tokens.get(bob)!.value)); + testConfigFactory.verifyComponentFactory(instance => instance.buildLegalOfficerClient(api.object(), It.IsAny(), tokens.get(bob)!.value)); }); it("logs out", async () => { @@ -166,7 +166,7 @@ describe("LogionClient", () => { testConfigFactory.setupDefaultAxiosInstanceFactory(); testConfigFactory.setupDefaultNetworkState(); testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - testConfigFactory.setupAuthenticatedDirectoryClientMock(tokens.get(alice)!.value); + testConfigFactory.setupAuthenticatedLegalOfficerClientMock(tokens.get(alice)!.value); testConfigFactory.setupAuthenticationClientMock(legalOfficers); }, alice, legalOfficers, tokens); const authenticatedClient = new LogionClient({ ...sharedState }); diff --git a/packages/client/test/Public.spec.ts b/packages/client/test/Public.spec.ts index 7ebb5639..81a83d75 100644 --- a/packages/client/test/Public.spec.ts +++ b/packages/client/test/Public.spec.ts @@ -176,7 +176,7 @@ async function buildSharedState(): Promise { (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); factory.setupFileUploaderMock(); - factory.setupDirectoryClientMock(); + factory.setupLegalOfficerClientMock(); const axiosFactoryMock = factory.setupAxiosFactoryMock(); diff --git a/packages/client/test/RecoveryReview.spec.ts b/packages/client/test/RecoveryReview.spec.ts index 3a750c8b..09e27aba 100644 --- a/packages/client/test/RecoveryReview.spec.ts +++ b/packages/client/test/RecoveryReview.spec.ts @@ -72,8 +72,8 @@ function setupConfig(axios: Mock): LogionClientConfig { .returns(axios.object()); setupBackend(axios); testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(); - directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([ + const legalOfficerClient = testConfigFactory.setupLegalOfficerClientMock(); + legalOfficerClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([ new LegalOfficerClass({ legalOfficer: ALICE, axiosFactory: axiosFactory.object(), diff --git a/packages/client/test/SecretRecovery.spec.ts b/packages/client/test/SecretRecovery.spec.ts index 1bb38c30..21934255 100644 --- a/packages/client/test/SecretRecovery.spec.ts +++ b/packages/client/test/SecretRecovery.spec.ts @@ -50,9 +50,9 @@ function configure() { axiosFactory.setup(instance => instance.buildAxiosInstance(It.IsAny(), It.IsAny())) .returns(axios.object()); const nodeApi = testConfigFactory.setupNodeApiMock(LOGION_CLIENT_CONFIG); - const directoryClient = testConfigFactory.setupDirectoryClientMock(); + const legalOfficerClient = testConfigFactory.setupLegalOfficerClientMock(); - directoryClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([ + legalOfficerClient.setup(instance => instance.getLegalOfficers()).returns(Promise.resolve([ new LegalOfficerClass({ legalOfficer: ALICE, axiosFactory: axiosFactory.object(), diff --git a/packages/client/test/TestConfigFactory.ts b/packages/client/test/TestConfigFactory.ts index 37dcc826..247dca4f 100644 --- a/packages/client/test/TestConfigFactory.ts +++ b/packages/client/test/TestConfigFactory.ts @@ -5,7 +5,7 @@ import { AuthenticationClient, AxiosFactory, ComponentFactory, - DirectoryClient, + LegalOfficerClient, LogionClientConfig, LegalOfficer, LegalOfficerClass, @@ -42,18 +42,18 @@ export class TestConfigFactory { return nodeApi; } - setupDirectoryClientMock(): Mock { - const directoryClient = new Mock(); - this._componentFactory.setup(instance => instance.buildDirectoryClient(It.IsAny(), It.IsAny())) - .returns(directoryClient.object()); - return directoryClient; + setupLegalOfficerClientMock(): Mock { + const legalOfficerClient = new Mock(); + this._componentFactory.setup(instance => instance.buildLegalOfficerClient(It.IsAny(), It.IsAny())) + .returns(legalOfficerClient.object()); + return legalOfficerClient; } - setupAuthenticatedDirectoryClientMock(token: string): Mock { - const directoryClient = new Mock(); - this._componentFactory.setup(instance => instance.buildDirectoryClient(It.IsAny(), It.IsAny(), token)) - .returns(directoryClient.object()); - return directoryClient; + setupAuthenticatedLegalOfficerClientMock(token: string): Mock { + const legalOfficerClient = new Mock(); + this._componentFactory.setup(instance => instance.buildLegalOfficerClient(It.IsAny(), It.IsAny(), token)) + .returns(legalOfficerClient.object()); + return legalOfficerClient; } setupAuthenticationClientMock(legalOfficers: LegalOfficer[]): Mock { diff --git a/packages/client/test/Utils.ts b/packages/client/test/Utils.ts index 9f4f3a7f..83ba6777 100644 --- a/packages/client/test/Utils.ts +++ b/packages/client/test/Utils.ts @@ -114,7 +114,7 @@ export async function buildAuthenticatedSharedStateUsingTestConfig( ): Promise { const componentFactory = (config as any).__componentFactory; const axiosFactory = componentFactory.buildAxiosFactory(); - const directoryClient = componentFactory.buildDirectoryClient(axiosFactory); + const legalOfficerClient = componentFactory.buildLegalOfficerClient(axiosFactory); const nodesUp: LegalOfficerEndpoint[] = legalOfficers.map(legalOfficer => ({ url: legalOfficer.node, legalOfficer: legalOfficer.account.address })); const networkState = componentFactory.buildNetworkState(nodesUp, []); const nodeApi = await componentFactory.buildNodeApi(config.rpcEndpoints); @@ -127,7 +127,7 @@ export async function buildAuthenticatedSharedStateUsingTestConfig( config, componentFactory, axiosFactory, - directoryClient, + legalOfficerClient, networkState, nodeApi, currentAccount: currentAccount, diff --git a/packages/client/test/Vault.spec.ts b/packages/client/test/Vault.spec.ts index 719df2c5..83db243a 100644 --- a/packages/client/test/Vault.spec.ts +++ b/packages/client/test/Vault.spec.ts @@ -80,7 +80,7 @@ describe("Vault", () => { const sharedState = await buildTestAuthenticatedSharedSate( (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); - factory.setupDirectoryClientMock(); + factory.setupLegalOfficerClientMock(); factory.setupAxiosFactoryMock(); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); @@ -156,7 +156,7 @@ describe("Vault", () => { const sharedState = await buildTestAuthenticatedSharedSate( (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); - factory.setupDirectoryClientMock(); + factory.setupLegalOfficerClientMock(); factory.setupAxiosFactoryMock(); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); @@ -233,7 +233,7 @@ describe("Vault", () => { const sharedState = await buildTestAuthenticatedSharedSate( (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); - factory.setupDirectoryClientMock(); + factory.setupLegalOfficerClientMock(); factory.setupAxiosFactoryMock(); factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); }, @@ -302,7 +302,7 @@ describe("Vault", () => { const sharedState = await buildTestAuthenticatedSharedSate( (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); - factory.setupDirectoryClientMock(); + factory.setupLegalOfficerClientMock(); factory.setupAxiosFactoryMock(); const nodeApi = factory.setupNodeApiMock(LOGION_CLIENT_CONFIG); diff --git a/packages/client/test/Voter.spec.ts b/packages/client/test/Voter.spec.ts index 4beb07dc..052c3ad0 100644 --- a/packages/client/test/Voter.spec.ts +++ b/packages/client/test/Voter.spec.ts @@ -61,7 +61,7 @@ async function buildSharedState(): Promise { (factory: TestConfigFactory) => { factory.setupDefaultNetworkState(); factory.setupFileUploaderMock(); - factory.setupAuthenticatedDirectoryClientMock(token); + factory.setupAuthenticatedLegalOfficerClientMock(token); const axiosFactoryMock = factory.setupAxiosFactoryMock();