Skip to content

Commit

Permalink
Merge pull request #271 from logion-network/feature/decentralize-dir
Browse files Browse the repository at this point in the history
Decentralized directory.
  • Loading branch information
benoitdevos authored Jun 18, 2024
2 parents 2f78ec1 + 984b95f commit 8db2726
Show file tree
Hide file tree
Showing 29 changed files with 241 additions and 283 deletions.
77 changes: 4 additions & 73 deletions packages/client-node/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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:
- [email protected]
- 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
31 changes: 31 additions & 0 deletions packages/client-node/integration/LegalOfficer.ts
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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: "[email protected]",
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.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);
expect(legalOfficer?.additionalDetails).toEqual(updatedAlice.additionalDetails);
}
6 changes: 5 additions & 1 deletion packages/client-node/integration/Main.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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);
});
Expand Down
25 changes: 12 additions & 13 deletions packages/client-node/integration/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
};
Expand Down Expand Up @@ -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<LogionClientConfig>): Promise<State> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', '', '[email protected]', '+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', '', '[email protected]', '+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', '', '[email protected]', '+1234', 'Charlie''s Company', 'Line 1', 'Line 2', '1000', 'City', 'Country', null);
4 changes: 4 additions & 0 deletions packages/client-node/scripts/directory_data_node2.sql
Original file line number Diff line number Diff line change
@@ -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', '', '[email protected]', '+1234', 'Bob''s Company', 'Line 1', 'Line 2', '1000', 'City', 'Country', null);
3 changes: 2 additions & 1 deletion packages/client-node/scripts/integration_test_db_setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
@@ -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": "[email protected]",
Expand Down
21 changes: 3 additions & 18 deletions packages/client/src/AuthenticationClient.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -18,31 +17,17 @@ type AuthenticationResponse = Record<string, { value: string, expiredOn: string

export class AuthenticationClient {

constructor(api: LogionNodeApiClass, directoryEndpoint: string, legalOfficers: LegalOfficerClass[], axiosFactory: AxiosFactory) {
constructor(api: LogionNodeApiClass, legalOfficers: LegalOfficerClass[]) {
this.api = api;
this.directoryEndpoint = directoryEndpoint;
this.legalOfficers = legalOfficers;
this.axiosFactory = axiosFactory;
}

private api: LogionNodeApiClass;

private directoryEndpoint: string;

private legalOfficers: LegalOfficerClass[];

private axiosFactory: AxiosFactory;

async authenticate(addresses: ValidAccountId[], signer: RawSigner): Promise<AccountTokens> {
return this.doWithDirectoryOrFirstAvailableNode(axios => this.authenticateWithAxios(axios, addresses, signer));
}

private doWithDirectoryOrFirstAvailableNode<T>(axiosConsumer: (axios: AxiosInstance) => Promise<T>): Promise<T> {
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<T>(axiosConsumer: (axios: AxiosInstance) => Promise<T>): Promise<T> {
Expand Down Expand Up @@ -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
})
Expand Down
14 changes: 7 additions & 7 deletions packages/client/src/ComponentFactory.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
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";
import { LegalOfficerClient } from "./LegalOfficerClient.js";
import { NetworkState } from "./NetworkState.js";
import { LegalOfficerEndpoint } from "./SharedClient.js";
import { LegalOfficerClass } from "./Types.js";
Expand Down Expand Up @@ -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;
buildLegalOfficerClient: (api: LogionNodeApiClass, axiosFactory: AxiosFactory, token?: string) => LegalOfficerClient;
buildAuthenticationClient: (api: LogionNodeApiClass, legalOfficers: LegalOfficerClass[]) => AuthenticationClient;
buildNetworkState(nodesUp: LegalOfficerEndpoint[], nodesDown: LegalOfficerEndpoint[]): NetworkState<LegalOfficerEndpoint>;
buildNodeApi(rpcEndpoints: string[]): Promise<LogionNodeApiClass>;
}

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),
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[]) => buildApiClass(rpcEndpoints),
buildNodeApi: (rpcEndpoints: string[]) => LogionNodeApiClass.connect(rpcEndpoints),
};

export interface ComponentFactory extends CoreComponentFactory {
Expand Down
9 changes: 0 additions & 9 deletions packages/client/src/Environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,20 @@ import { FileUploader } from "./ComponentFactory.js";
import { UUID } from "@logion/node-api";

export enum Environment {
DEV = 'DEV',
TEST = 'TEST',
MVP = 'MVP',
}

const configs: Record<Environment, Omit<LogionClientConfig, 'buildFileUploader'>> = {
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: {
rpcEndpoints: [
"wss://para-rpc01.logion.network",
"wss://para-rpc02.logion.network",
],
directoryEndpoint: "https://directory.logion.network",
logionClassificationLoc: UUID.fromDecimalStringOrThrow("85815882149698756717105061322008904805"),
}
}
Expand Down
Loading

0 comments on commit 8db2726

Please sign in to comment.