Skip to content

Commit d748b3d

Browse files
hai-koKarl AdlerAlexNi245
authored
Billboard deploy (#496)
* initial react setup and dm3-billboard-api fix * setup new project using vite - add messages list with auto scroll logic - add new messages simulation button - TODO: cleanup old package, boilerplate etc .. * improve scroll behaviour and clean upcode * add scrollbars, normalize css class names * remove old billboard-app * add message create area - add timeout button - add tolerance to scrolled to bottom detection * add date formatting * use svg colors from vars * add viewers count, empty view and branding - optimize some css - add icons and logos - fix some margins * smaller UI fixes * fix scrolling the whole page first * style scroll-to-bottom button * add viewers count, configure env vars * move wrongly located component * add random mack message, fix jumping avatar * add experimental provider, fix some styles - add experimental metamask provider - fix create message styles for text area - hide gear icon button, if no action is defined * add websocket listener - expose all props to toplevel component - add event websocket listener for message - check for existing messages - fix small UI bugs - remove support for .env vars * migrate to socket.io - add viewers count event - fix problem with adding keys - add warning to unique function * make avatar configurable * prepare npm release - separate css from js - create types - configure vite in lib mode - temporarily add registry for our scope "testscope/" * add use auth hook * add yarn dir to gitignore * add dedicated profile endpoint * adjust profilep * add interface docs and update README * add send msg * ready for publish * fix dm3 styles * disable button when no message was entered - add small timeout of 6 seconds - add separate disabled state for timeout and disabled prop * build: npm publish * add create UserProfile in case it does not exit yet * build: billboard client deploy * build: heroku * fix: build * build: ds * fix: build * feat: new logger --------- Co-authored-by: Karl Adler <[email protected]> Co-authored-by: AlexNi245 <[email protected]>
1 parent 3e8706f commit d748b3d

File tree

129 files changed

+3427
-6840
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+3427
-6840
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,6 @@ packages/lib/**/dist
5757
!.yarn/plugins
5858
!.yarn/releases
5959
!.yarn/sdks
60-
!.yarn/versions
60+
!.yarn/versions
61+
62+
packages/**/.yarn

.yarnrc.yml

+12
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,15 @@ plugins:
55
spec: "@yarnpkg/plugin-workspace-tools"
66

77
yarnPath: .yarn/releases/yarn-3.5.1.cjs
8+
9+
unsafeHttpWhitelist:
10+
- "localhost"
11+
12+
# using https://verdaccio.org/ for the scope: `@testscope`
13+
# Needs to be removed before release
14+
# Update Scope in package.json
15+
npmScopes:
16+
testscope:
17+
npmPublishRegistry: http://localhost:4873
18+
npmRegistryServer: http://localhost:4873
19+
# npmAuthIdent: user:password

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
"packages/lib/offchainResolver",
1313
"packages/lib/offchainResolver-api",
1414
"packages/offchain-resolver-backend",
15-
"packages/lib/lib-billboard-api",
15+
"packages/lib/billboard-api",
1616
"packages/backend",
1717
"packages/billboard-client",
1818
"packages/react",
1919
"packages/web",
2020
"packages/offchain-resolver",
21+
"packages/billboard-widget",
2122
"packages/integration-tests"
2223
],
2324
"nohoist": [
@@ -43,8 +44,8 @@
4344
"scripts": {
4445
"docker:up": "cd packages/backend && docker-compose up -d",
4546
"build": " yarn workspaces foreach -pt run build",
46-
"start": "cd packages/backend && yarn start",
47-
"resolver": "cd packages/offchain-resolver && yarn start",
47+
"start": "yarn workspace dm3-backend start",
48+
"resolver": "yarn workspace dm3-offchain-resolver-backend start",
4849
"lint": "eslint '*/**/*.{js,ts,tsx}' --fix",
4950
"format": "prettier --write '*/**/*.{js,ts,tsx,json}'",
5051
"format:check": "prettier --check '*/**/*.{js,ts,tsx,json}'",

packages/backend/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"docker:up": "docker-compose up -d",
3131
"start": "ts-node --transpile-only ./src/index.ts",
3232
"test": "npm run docker:up && jest --coverage --runInBand --transformIgnorePatterns 'node_modules/(?!(dm3-lib-\\w*)/)'",
33-
"build": "tsc && cp ./config.yml ./dist/config.yml | true",
33+
"build": "yarn tsc && cp ./config.yml ./dist/config.yml | true",
3434
"createDeliveryServiceProfile": "node --no-warnings ./cli.js"
3535
},
3636
"devDependencies": {

packages/backend/src/cleanup/cleanUpPendingMessages.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const DEFAULT_CLEANUP_INTERVAL = 86400000;
77
async function onCleanUpPendingMessages(db: IDatabase, ttl: number) {
88
const now = new Date().getTime();
99
const expiryDate = now - ttl;
10-
log('[Clean up] Delete expired messages');
10+
log('[Clean up] Delete expired messages', 'info');
1111
await db.deleteExpiredMessages(expiryDate);
1212
}
1313

@@ -21,7 +21,7 @@ export function startCleanUpPendingMessagesJob(
2121
if (ttl <= 0) {
2222
return;
2323
}
24-
log('[Clean up] Start Clean up job');
24+
log('[Clean up] Start Clean up job', 'info');
2525
return setInterval(() => {
2626
onCleanUpPendingMessages(db, ttl);
2727
}, cleaningInterval);

packages/backend/src/config/getDeliveryServiceProperties.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function getDeliveryServiceProperties(
1919
defaultDeliveryServiceProperties: DeliveryServiceProperties = DEFAULT_DELIVERY_SERVICE_PROPERTIES,
2020
): DeliveryServiceProperties {
2121
if (!existsSync(path)) {
22-
log('Config file not found. Default Config is used');
22+
log('Config file not found. Default Config is used', 'info');
2323
return defaultDeliveryServiceProperties;
2424
}
2525
const yamlString = readFileSync(path, { encoding: 'utf-8' });

packages/backend/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,5 @@ app.use(express.static(path.join(__dirname, '../../web/build')));
8383
const port = process.env.PORT || '8080';
8484

8585
server.listen(port, () => {
86-
log('[Server] listening at port ' + port + ' and dir ' + __dirname);
86+
log('[Server] listening at port ' + port + ' and dir ' + __dirname, 'info');
8787
});

packages/backend/src/messaging.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
checkToken,
1010
incomingMessage,
1111
} from 'dm3-lib-delivery/dist.backend';
12+
import { log } from 'dm3-lib-shared';
1213
const pendingMessageSchema = {
1314
type: 'object',
1415
properties: {
@@ -23,7 +24,6 @@ const pendingMessageSchema = {
2324
export function onConnection(app: express.Application & WithLocals) {
2425
return (socket: Socket) => {
2526
socket.on('disconnect', () => {
26-
app;
2727
app.locals.logger.info({
2828
method: 'WS DISCONNECT',
2929
socketId: socket.id,

packages/backend/src/rpc/methods/handleSubmitMessage.ts

+12-7
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ import { validateSchema } from 'dm3-lib-shared/dist.backend';
44
import 'dotenv/config';
55
import express from 'express';
66
import { WithLocals } from '../../types';
7-
8-
interface SubmitMessage {
9-
token: string;
10-
}
7+
import { log } from 'dm3-lib-shared';
118

129
export async function handleSubmitMessage(
1310
req: express.Request & { app: WithLocals },
@@ -19,8 +16,15 @@ export async function handleSubmitMessage(
1916

2017
const envelop = JSON.parse(stringifiedEnvelop);
2118

22-
if (!envelop || !token) {
23-
return res.send(400);
19+
if (!token) {
20+
log('Auth token missing', 'error');
21+
return res.status(400).send('Auth token missing');
22+
}
23+
24+
if (!envelop) {
25+
log('Envelop missing', 'error');
26+
27+
return res.status(400).send('Envelop missing');
2428
}
2529

2630
const isSchemaValid = validateSchema(schema.MessageSubmission, {
@@ -58,7 +62,8 @@ export async function handleSubmitMessage(
5862
method: 'RPC SUBMIT MESSAGE',
5963
error,
6064
});
65+
log('[handleSubmitMessage]' + error, 'error');
6166

62-
return res.send(400);
67+
return res.status(400).send();
6368
}
6469
}

packages/billboard-client/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"axios": "^0.27.2",
99
"body-parser": "^1.20.1",
1010
"connect-redis": "^6.1.3",
11+
"cors": "^2.8.5",
1112
"dm3-lib-delivery": "^0.1.1",
1213
"dm3-lib-messaging": "^0.1.1",
1314
"dm3-lib-profile": "^0.1.1",
@@ -21,12 +22,13 @@
2122
"prettier": "^2.6.2",
2223
"redis": "^4.1.0",
2324
"socket.io": "^4.5.1",
25+
"ts-node": "^10.9.1",
2426
"winston": "^3.8.2",
2527
"yaml": "^2.1.3"
2628
},
2729
"scripts": {
2830
"docker:up": "docker-compose up -d",
29-
"start": "ts-node --transpile-only ./src/index.ts",
31+
"start": "yarn ts-node --transpile-only ./src/index.ts",
3032
"test": "npm run docker:up && jest --coverage --runInBand --forceExit",
3133
"lint": "eslint '*/**/*.{js,ts,tsx}' --fix",
3234
"format": "prettier --write '*/**/*.{js,ts,tsx,json}'",

packages/billboard-client/src/api/external/getExternalApi.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import express from 'express';
22
import { v4 } from 'uuid';
3+
import cors from 'cors';
34
import { getViewerCountHandler } from './handler/getViewerCount';
45
import { getMessagesHandler } from './handler/getMessages';
56
import { IDatabase } from '../../persitance/getDatabase';
67
import { IViewerService } from '../../service/viewerService/IViewerService';
78

89
export function getExternalApi(db: IDatabase, viewerService: IViewerService) {
910
const app = express();
11+
app.use(cors());
1012

1113
app.post('/rpc', async (req: express.Request, res: express.Response) => {
1214
const { method, params } = req.body;

packages/billboard-client/src/api/internal/rest/getChallenge.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export async function getChallenge(
1212
const { data } = await axios.get(url);
1313
return data.challenge;
1414
} catch (e) {
15-
log("can't get challenge from ds " + dsUrl);
15+
log("can't get challenge from ds " + dsUrl, 'error');
1616
return null;
1717
}
1818
}

packages/billboard-client/src/api/internal/rest/getIncomingMessages.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,26 @@ import { log } from 'dm3-lib-shared';
1111
export async function getIncomingMessages(
1212
dsUrl: string,
1313
ensName: string,
14+
token: string,
1415
): Promise<EncryptionEnvelop[] | null> {
1516
try {
1617
const response: AxiosResponse<EncryptionEnvelop[]> = await axios.get(
17-
`${dsUrl}/messages/incoming/${ensName}`,
18+
`${dsUrl}/delivery/messages/incoming/${ensName}`,
19+
{
20+
headers: {
21+
Authorization: `Bearer ${token}`,
22+
},
23+
},
1824
);
1925

2026
return response.data;
2127
} catch (e) {
22-
log(`Failed to retrieve incoming messages for ds ${dsUrl}`);
28+
log(
29+
`Failed to retrieve incoming messages for ds ${dsUrl}` +
30+
JSON.stringify(e),
31+
32+
'error',
33+
);
2334
return null;
2435
}
2536
}

packages/billboard-client/src/api/internal/rest/getNewToken.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export async function getNewToken(
1212
const { data } = await axios.post(url, { signature });
1313
return data.token;
1414
} catch (e) {
15-
log("can't get new token from ds");
15+
log("can't get new token from ds: " + JSON.stringify(e), 'error');
1616
return null;
1717
}
1818
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import axios from 'axios';
2+
import { SignedUserProfile, normalizeEnsName } from 'dm3-lib-profile';
3+
import { log } from 'dm3-lib-shared';
4+
5+
export async function submitUserProfile(
6+
dsUrl: string,
7+
ensName: string,
8+
signedUserProfile: SignedUserProfile,
9+
): Promise<string | null> {
10+
const url = `${dsUrl}/profile/${normalizeEnsName(ensName)}`;
11+
12+
try {
13+
const { data } = await axios.post(url, signedUserProfile);
14+
return data;
15+
} catch (e) {
16+
log(
17+
"can't submit userProfile to ds " + dsUrl + ' ' + JSON.stringify(e),
18+
'error',
19+
);
20+
return null;
21+
}
22+
}

packages/billboard-client/src/api/internal/ws/getDeliveryServiceWSConnections.ts

+20-6
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,43 @@
11
import { EncryptionEnvelop } from 'dm3-lib-messaging';
2+
import { DeliveryServiceProfile } from 'dm3-lib-profile';
23
import { log } from 'dm3-lib-shared';
34

45
import { io, Socket } from 'socket.io-client';
56

67
export const getDeliveryServiceWSClient = (
7-
deliveryServices: string[],
8+
deliveryServices: (DeliveryServiceProfile & {
9+
token: string;
10+
})[],
811
onMessage: (encelop: EncryptionEnvelop) => any,
12+
ensName: string,
913
): Promise<Socket[]> => {
1014
return Promise.all(
11-
deliveryServices.map(async (url: string) => {
15+
deliveryServices.map(async (ds) => {
1216
const client = await new Promise<Socket>((res, rej) => {
13-
const c = io(url, {});
17+
const c = io(ds.url, {
18+
auth: {
19+
account: { ensName },
20+
token: ds.token,
21+
},
22+
});
1423
c.on('connect', () => {
15-
log(`Connected to Delivery Service ${url}`);
24+
log(`Connected to Delivery Service ${ds.url}`, 'info');
1625
res(c);
1726
});
1827
c.on('connect_error', (err: any) => {
19-
log(`Connection error to Delivery Service ${url}`);
28+
log(
29+
`Connection error to Delivery Service ${ds.url} ` +
30+
JSON.stringify(err),
31+
'error',
32+
);
2033

2134
rej(err);
2235
});
2336
});
37+
log(`Register listener`, 'info');
2438
//register listners
2539
client.on('disconnect', () => {
26-
log(`disconnected from deliveryService ${url}`);
40+
log(`disconnected from deliveryService ${ds.url}`, 'info');
2741
});
2842
client.on('message', onMessage);
2943

packages/billboard-client/src/getBillboardClientApp.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const getBillboardClientApp = async (
2929

3030
//Readng the ENV config file
3131
const config = ConfigService().readConfigFromEnv();
32+
log('[getBillboardClientApp] config ' + JSON.stringify(config), 'debug');
3233

3334
//Each Ens name provided in the config file is an billboard instance
3435
//Right now we're using one profile and hence one private key for all billboards
@@ -37,6 +38,10 @@ export const getBillboardClientApp = async (
3738
ensName,
3839
privateKey: config.privateKey,
3940
}));
41+
log(
42+
'[getBillboardClientApp] billboards ' + JSON.stringify(billboards),
43+
'debug',
44+
);
4045

4146
//Register services
4247
const viewerService = await ViewerService(httpServer);
@@ -53,7 +58,7 @@ export const getBillboardClientApp = async (
5358
app.use(getExternalApi(db, viewerService));
5459

5560
httpServer.listen(port, () => {
56-
log('billboard client listening at port ' + port);
61+
log('billboard client listening at port ' + port, 'info');
5762
});
5863

5964
//In oder to finish the test everything has to be cleaned up

packages/billboard-client/src/index.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ const main = async () => {
1515
}
1616
const provider = new ethers.providers.JsonRpcProvider(rpcUrl);
1717

18-
const database = await getDatabase(winston.createLogger());
18+
const database = await getDatabase(
19+
winston.createLogger({
20+
transports: [new winston.transports.Console()],
21+
}),
22+
);
1923

2024
await getBillboardClientApp(provider, database, Number(port));
2125
};

packages/billboard-client/src/persitance/getDatabase.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export enum RedisPrefix {
99
}
1010

1111
export async function getRedisClient(logger: winston.Logger) {
12-
const url = process.env.REDIS_URL || 'redis://127.0.0.1:6368';
12+
const url = process.env.REDIS_URL ?? 'redis://127.0.0.1:6368';
1313
const socketConf = {
1414
socket: {
1515
tls: true,

packages/billboard-client/src/persitance/getMessages/getMessages.test.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,17 @@ describe('getMessages', () => {
77
let redisClient: Redis;
88
let db: IDatabase;
99
beforeEach(async () => {
10-
redisClient = await getRedisClient(winston.createLogger());
11-
db = await getDatabase(winston.createLogger(), redisClient);
10+
redisClient = await getRedisClient(
11+
winston.createLogger({
12+
transports: [new winston.transports.Console()],
13+
}),
14+
);
15+
db = await getDatabase(
16+
winston.createLogger({
17+
transports: [new winston.transports.Console()],
18+
}),
19+
redisClient,
20+
);
1221
await redisClient.flushDb();
1322
});
1423

packages/billboard-client/src/service/dsManager/DsManager.test.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,9 @@ describe('DsManager', () => {
363363
});
364364

365365
axiosMock
366-
.onGet('http://localhost:4060/messages/incoming/billboard1.eth')
366+
.onGet(
367+
'http://localhost:4060/delivery/messages/incoming/billboard1.eth',
368+
)
367369
.reply(200, [
368370
await mockChat1.createMessage('hello'),
369371
await mockChat1.createMessage('world'),

0 commit comments

Comments
 (0)