From 8b72b29ee8affea4120c9d9916485bbb45aaded2 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 17 Jul 2023 21:19:38 +0530 Subject: [PATCH] Alpha (#496) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.1 * ci(restapi): 🎉 cut release to restapi-v1.0.1 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.3 * fix: success progressHook * ci(restapi): 🎉 cut release to restapi-v1.0.4 * ci(restapi): 🎉 cut release to restapi-v1.1.0 * ci(restapi): 🎉 cut release to restapi-v1.2.0 * ci(restapi): 🎉 cut release to restapi-v1.2.0 * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * fix(component): dummy * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.3 * ci(restapi): 🎉 cut release to restapi-v1.0.4 * ci(restapi): 🎉 cut release to restapi-v1.2.1 * fix: local for local development (#295) Co-Authored-By: aman035 * fix: version update * ci(restapi): 🎉 cut release to restapi-v1.2.2 * ci(restapi): 🎉 cut release to restapi-v1.2.3 * ci(restapi): 🎉 cut release to restapi-v1.2.4 * ci(restapi): 🎉 cut release to restapi-v1.2.5 * ci(restapi): 🎉 cut release to restapi-v1.2.6 * ci(restapi): 🎉 cut release to restapi-v1.2.7 * ci(socket): 🎉 cut release to socket-v0.5.0 * fix: test commit * ci(restapi): 🎉 cut release to restapi-v1.2.8 * ci(uiweb): 🎉 cut release to uiweb-v1.0.0 * ci(uiweb): 🎉 cut release to uiweb-v1.0.0 * ci(uiweb): 🎉 cut release to uiweb-v1.0.1 * fix: added ci-version-beta * fix: added ci-version-beta * ci(restapi): 🎉 cut beta release to restapi-v1.2.9 * fix: added releaseType * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.0 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.0 * ci(restapi): 🎉 cut release to restapi-v1.2.10 * ci(restapi): 🎉 cut release to restapi-v1.2.10 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.1 * Add wallet to wallet video call methods (#309) * feat(video): add create and request method * feat(video): add simple-peer dependency * feat(video): add acceptRequest method * feat(video): add establish and end methods * refactor(video): wrap video methods in a class * feat(video): add video audio toggle functions * fix(video): add pgp private key in send video call notification * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.2 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.2 * Alpha deployment (#357) * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.1 * ci(restapi): 🎉 cut release to restapi-v1.0.1 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.3 * fix: success progressHook * ci(restapi): 🎉 cut release to restapi-v1.0.4 * ci(restapi): 🎉 cut release to restapi-v1.1.0 * ci(restapi): 🎉 cut release to restapi-v1.2.0 * ci(restapi): 🎉 cut release to restapi-v1.2.0 * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * fix(component): dummy * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.3 * ci(restapi): 🎉 cut release to restapi-v1.0.4 * ci(restapi): 🎉 cut release to restapi-v1.2.1 * fix: local for local development (#295) Co-Authored-By: aman035 * fix: version update * ci(restapi): 🎉 cut release to restapi-v1.2.2 * ci(restapi): 🎉 cut release to restapi-v1.2.3 * ci(restapi): 🎉 cut release to restapi-v1.2.4 * ci(restapi): 🎉 cut release to restapi-v1.2.5 * ci(restapi): 🎉 cut release to restapi-v1.2.6 * ci(restapi): 🎉 cut release to restapi-v1.2.7 * ci(socket): 🎉 cut release to socket-v0.5.0 * fix: test commit * ci(restapi): 🎉 cut release to restapi-v1.2.8 * ci(uiweb): 🎉 cut release to uiweb-v1.0.0 * ci(uiweb): 🎉 cut release to uiweb-v1.0.0 * ci(uiweb): 🎉 cut release to uiweb-v1.0.1 * fix: added ci-version-beta * fix: added ci-version-beta * ci(restapi): 🎉 cut beta release to restapi-v1.2.9 * fix: added releaseType * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.0 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.0 * ci(restapi): 🎉 cut release to restapi-v1.2.10 * ci(restapi): 🎉 cut release to restapi-v1.2.10 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.1 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.2 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.2 --------- Co-authored-by: aman035 * fix: added pagination and deprecation tag (#346) * fix: eip191v2 signatures for create and auth.update (#353) * fix: changed Definitions for auth.update and upgrade (#351) * fix: changed Definitions for auth.update and upgrade * fix: chnaged demoreact * fix: revert code no * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.0 * fix: sendVideoNotification and end video call logic (#367) * feat(video): add create and request method * feat(video): add simple-peer dependency * feat(video): add acceptRequest method * feat(video): add establish and end methods * refactor(video): wrap video methods in a class * feat(video): add video audio toggle functions * fix(video): add pgp private key in send video call notification * fix(video): fix end call logic and remove hidden ppt from send video call notifications * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.1 * Modify video class (#379) * feat(video): add create and request method * feat(video): add simple-peer dependency * feat(video): add acceptRequest method * feat(video): add establish and end methods * refactor(video): wrap video methods in a class * feat(video): add video audio toggle functions * fix(video): add pgp private key in send video call notification * fix(video): fix end call logic and remove hidden ppt from send video call notifications * refactor(video): combine all the states in the Video class to single state * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.2 * fix: Replace arrow functions with normal functions in the Video class (#380) * feat(video): add create and request method * feat(video): add simple-peer dependency * feat(video): add acceptRequest method * feat(video): add establish and end methods * refactor(video): wrap video methods in a class * feat(video): add video audio toggle functions * fix(video): add pgp private key in send video call notification * fix(video): fix end call logic and remove hidden ppt from send video call notifications * refactor(video): combine all the states in the Video class to single state * fix(video): replace arrow functions with normal functions --------- Co-authored-by: Madhur Gupta * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.3 * fix(video): separate react state from video class instance variable data (#389) Co-authored-by: Madhur Gupta * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.4 * fix: url fix * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.5 * fix: add video call retry logic upon error & doc: add video call in restapi/readme (#391) * docs(video): add video calls in restapi readme * fix(video): add video call retry logic upon error --------- Co-authored-by: Madhur Gupta * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.6 * fix(video): remove status change upon connect in request (#394) Co-authored-by: Madhur Gupta * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.7 * docs: add push video backend example (#396) * docs(video): add backend exmaple for push video * fix(video): add backend compatibility to create function --------- Co-authored-by: Madhur Gupta * fix(video): set trickle to true while creating peer instance (#397) Co-authored-by: Madhur Gupta * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.8 * fix(video): turn off trickle while creating peer instance (#398) Co-authored-by: Madhur Gupta * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.9 * fix: added deprecated info to history (#399) * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.10 * revert(getverificationproof): add wallet and env params to getVerificationProof (#403) Co-authored-by: Madhur Gupta * fix(video): remove stop audio/video logic from create function (#404) Co-authored-by: Madhur Gupta * fix: changed additionalMeta structure (#406) * docs: update * docs: update * fix: changed additionalMeta strcuture --------- Co-authored-by: strykerin * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.11 * fix: added enums * fix: fix versions * fix(sendvideonotifications): modify additional meta acc to new std (#407) * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.12 * fix(types): remove bad import * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.11 * fix(video): fix enableAudio * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.12 * fix: backward compatiblity fix * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.13 * docs: Update the enableVideo/Audio methods * fix: fix nft videocall (#411) * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.14 * fix: Iuser structure changed (#365) * fix: iuser changed * fix: changed route * fix: change profilePicture to picture * fix: fixed tests * fix: fix nftOwner and readme * fix: iuser changes * Deployment (#390) * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.1 * ci(restapi): 🎉 cut release to restapi-v1.0.1 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.3 * fix: success progressHook * ci(restapi): 🎉 cut release to restapi-v1.0.4 * ci(restapi): 🎉 cut release to restapi-v1.1.0 * ci(restapi): 🎉 cut release to restapi-v1.2.0 * ci(restapi): 🎉 cut release to restapi-v1.2.0 * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * fix(component): dummy * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.3 * ci(restapi): 🎉 cut release to restapi-v1.0.4 * ci(restapi): 🎉 cut release to restapi-v1.2.1 * fix: local for local development (#295) Co-Authored-By: aman035 * fix: version update * ci(restapi): 🎉 cut release to restapi-v1.2.2 * ci(restapi): 🎉 cut release to restapi-v1.2.3 * ci(restapi): 🎉 cut release to restapi-v1.2.4 * ci(restapi): 🎉 cut release to restapi-v1.2.5 * ci(restapi): 🎉 cut release to restapi-v1.2.6 * ci(restapi): 🎉 cut release to restapi-v1.2.7 * ci(socket): 🎉 cut release to socket-v0.5.0 * fix: test commit * ci(restapi): 🎉 cut release to restapi-v1.2.8 * ci(uiweb): 🎉 cut release to uiweb-v1.0.0 * ci(uiweb): 🎉 cut release to uiweb-v1.0.0 * ci(uiweb): 🎉 cut release to uiweb-v1.0.1 * fix: added ci-version-beta * fix: added ci-version-beta * ci(restapi): 🎉 cut beta release to restapi-v1.2.9 * fix: added releaseType * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.0 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.0 * ci(restapi): 🎉 cut release to restapi-v1.2.10 * ci(restapi): 🎉 cut release to restapi-v1.2.10 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.1 * ci(restapi): 🎉 cut release to restapi-v1.2.11 * fix: linkedListHash test cases removed & CI version corrected * fix: update name to beta * ci(restapi): 🎉 cut release to restapi-v1.2.12 * ci(restapi): 🎉 cut release to restapi-v1.2.12 * ci(restapi): 🎉 cut release to restapi-v1.2.13 * ci(restapi): 🎉 cut release to restapi-v1.2.14 * ci(restapi): 🎉 cut release to restapi-v1.2.15 * fix: update package json * fix: updated socket version * ci(uiweb): 🎉 cut release to uiweb-v1.0.2 * fix: socket lib update * ci(uiweb): 🎉 cut release to uiweb-v1.0.2 --------- Co-authored-by: aman035 * fix: add deprecated info to chat.chat (#392) * fix: show hardcoded msg rather than throwing error (#388) * docs: update * fix: fix decprecated param and verification of keys --------- Co-authored-by: Mohammed S Co-authored-by: strykerin * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.15 * fix: add spaces for functions (#307) * fix: add spaces for functions * fix: Separate page for space in the demo react APP * fix: start/stop spaces functions * fix: fix image and description types * fix: added functions to add and remove members from group * fix: spaces functions * fix: spaces functions refactoring * fix: few more changes * fix: spaces function testing * fix: spaces functions * fix: SDK bug fixes * fix: SDK bug fixes * fix: minor fixes * fix: minor fix * fix: minor fix * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.16 * fix(video): fix error on repeated acceptRequest calls (#442) * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.17 * fix: update path * fix: add name to SpaceIFeeds * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.18 * fix: rename based on new convention * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.19 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.19 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.19 * fix: new commit * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.20 * fix: spaces naming * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.21 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.22 * Add alpha version of Spaces SDK (#513) * refactor: added initial SpacesUI class architecture * Update packages/uiweb/src/lib/components/space/SpacesUI.tsx Co-authored-by: Arnab Chatterjee <60937304+arn4b@users.noreply.github.com> * Update packages/uiweb/src/lib/components/space/SpacesUI.tsx Co-authored-by: Arnab Chatterjee <60937304+arn4b@users.noreply.github.com> * fix: refine code structure * refactor: change structure and added a test sample * feat: added themeprovider for spaces ui components (#436) * feat: feat: add themeprovider for spaces * fix: resolved conflicts * refactor: cleaned up provider * refactor: resolved comments * feat: added colors and themeing in demoreactapp * refactor: cleaned code * refactor: resolved comments * refactor: added a basic style structure for ease of use (#453) * feat: SpaceBanner Component (#438) * feat: SpaceBanner * refactor: removed-optionals * feat: space-banner functionality * fix: reverted app.tsx * fix: reverted app.tsx * fix: removed test svg file * refactor: change structure and added a test sample * feat: space-banner functionality * refactor: api-implementation * fix: removed-svg * refactor: mobile version * Revert "fix: removed test svg file" This reverts commit 7af756badaeb8435db60712c42ca57ef9ce9f74c. * Revert "refactor: change structure and added a test sample" This reverts commit b1e8745948a9ce5e0485ad51a8cffd07010a5186. * fix: revert * refactor: lastest-pull * feat: added-spaceBanner-test * refactor: cache-to-context * refactor: custom hook added for data * refactor: spaceDTO * fix: SpaceDTO implementation * refactor: participant-container * refactor: cleanups * fix: ui-fixes * fix: EOF newlines * fix: overflow-fixed * refactor: tweaked context structure a bit --------- Co-authored-by: Samarendra Gouda Co-authored-by: Nilesh Gupta * refactor: updated theme object along with light and dark theme * feat: Create Space Component (#454) * refactor: resolved merge conflicts * feat: added modals and modal behaviour logic * feat: modal inputs * feat: change modal logic + integr8 API * feat: added CSS for modals and inputs * fix: resolved PR comments * refactor: improve css * refactor: rft create modal * feat: added search input component * Refactor/space widget component (#458) * refactor: added basic design * refactor: added full widget with style * refactor: reduced fixed height of scheduled widget content * refactor: changes requested * refactor: resolved review comments * feat: add spaces info component (#474) * Feat/added members modal (#477) * refactor: added modal * refactor: added members modal * refactor: review comments * refactor: resolve review comments * fix: review comments * 424 spaces functions webrtc logic (#482) * fix: add spaces for functions * fix: Separate page for space in the demo react APP * fix: start/stop spaces functions * fix: fix image and description types * fix: added functions to add and remove members from group * fix: spaces functions * fix: spaces functions refactoring * fix: few more changes * fix: spaces function testing * fix: spaces functions * fix: SDK bug fixes * fix: SDK bug fixes * fix: minor fixes * fix: minor fix * fix: minor fix * feat(video): add create mesh connection logic in Video class * feat(spaces): make video mesh compatible & add spaces class * feat(spaces): add backend methods in Space class --------- Co-authored-by: Shoaib Mohammed Co-authored-by: Madhur Gupta * refactor: spaces UI Components refactor (#478) > replaced hardcoded styles with context theme >added smoother animations on collapsoble components >added profile cards to invite modal * refactor: added spaceUI class variables into context as well (#488) * refactor: added spaceUI class variables into context as well * refactor: resolve review comments * refactor: added a clickHandler in spaceBanner component for extra flexibility (#489) * fix(spaces): fix console errs and refactor create, update methods (#492) * fix: add spaces for functions * fix: Separate page for space in the demo react APP * fix: start/stop spaces functions * fix: fix image and description types * fix: added functions to add and remove members from group * fix: spaces functions * fix: spaces functions refactoring * fix: few more changes * fix: spaces function testing * fix: spaces functions * fix: SDK bug fixes * fix: SDK bug fixes * fix: minor fixes * fix: minor fix * fix: minor fix * feat(video): add create mesh connection logic in Video class * feat(spaces): make video mesh compatible & add spaces class * feat(spaces): add backend methods in Space class * fix: Merge branch 'alpha' into 424-spaces-functions-webrtc-logic * fix(spaces): fix console errors and move out create, update functions from Space class --------- Co-authored-by: Shoaib Mohammed * refactor: modified init class method * refactor/added-space-feed-component(#481) * feat: space-feed * refactor: space-feed * Deployment (#440) * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.1 * ci(restapi): 🎉 cut release to restapi-v1.0.1 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.3 * fix: success progressHook * ci(restapi): 🎉 cut release to restapi-v1.0.4 * ci(restapi): 🎉 cut release to restapi-v1.1.0 * ci(restapi): 🎉 cut release to restapi-v1.2.0 * ci(restapi): 🎉 cut release to restapi-v1.2.0 * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * fix(component): dummy * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.3 * ci(restapi): 🎉 cut release to restapi-v1.0.4 * ci(restapi): 🎉 cut release to restapi-v1.2.1 * fix: local for local development (#295) Co-Authored-By: aman035 * fix: version update * ci(restapi): 🎉 cut release to restapi-v1.2.2 * ci(restapi): 🎉 cut release to restapi-v1.2.3 * ci(restapi): 🎉 cut release to restapi-v1.2.4 * ci(restapi): 🎉 cut release to restapi-v1.2.5 * ci(restapi): 🎉 cut release to restapi-v1.2.6 * ci(restapi): 🎉 cut release to restapi-v1.2.7 * ci(socket): 🎉 cut release to socket-v0.5.0 * fix: test commit * ci(restapi): 🎉 cut release to restapi-v1.2.8 * ci(uiweb): 🎉 cut release to uiweb-v1.0.0 * ci(uiweb): 🎉 cut release to uiweb-v1.0.0 * ci(uiweb): 🎉 cut release to uiweb-v1.0.1 * fix: added ci-version-beta * fix: added ci-version-beta * ci(restapi): 🎉 cut beta release to restapi-v1.2.9 * fix: added releaseType * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.0 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.0 * ci(restapi): 🎉 cut release to restapi-v1.2.10 * ci(restapi): 🎉 cut release to restapi-v1.2.10 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.1 * ci(restapi): 🎉 cut release to restapi-v1.2.11 * fix: linkedListHash test cases removed & CI version corrected * fix: update name to beta * ci(restapi): 🎉 cut release to restapi-v1.2.12 * ci(restapi): 🎉 cut release to restapi-v1.2.12 * ci(restapi): 🎉 cut release to restapi-v1.2.13 * ci(restapi): 🎉 cut release to restapi-v1.2.14 * ci(restapi): 🎉 cut release to restapi-v1.2.15 * fix: update package json * fix: updated socket version * ci(uiweb): 🎉 cut release to uiweb-v1.0.2 * fix: socket lib update * ci(uiweb): 🎉 cut release to uiweb-v1.0.2 * ci(restapi): 🎉 cut release to restapi-v1.2.16 * ci(restapi): 🎉 cut release to restapi-v1.3.0 * ci(restapi): 🎉 cut release to restapi-v1.3.1 * ci(socket): 🎉 cut release to socket-v0.5.1 * ci(restapi): 🎉 cut release to restapi-v1.3.2 * ci(restapi): 🎉 cut release to restapi-v1.3.3 * ci(restapi): 🎉 cut release to restapi-v1.3.4 --------- Co-authored-by: aman035 * feat: space-feed * refactor: space-feed * fix: api-call-custom-hooks * fix: api-call * refactor: enums/changes * fix: scrollable * fix: scrolling-issue * feat: filter-changes * fix: added types * fix: loader-issue * fix: tab-button-color * feat: new-filter and prop * fix: ended-logic && participant-number logic * refactor: add onBannerClick * fix: conflicts * revert: messed-up spaceBanner * fix: onClick issue * fix: onClick and cleanups * refactor: new pagination interface * fix: scroll-logic * fix: scroll-final * fix: .. * fix: removed any * fix: onClick-issue * fix: loading-context-to-state * refactor: add-NoSpaceIcons * refactor: new-ui-layout * refactor: new-ui-layout --------- Co-authored-by: Mohammed S Co-authored-by: aman035 Co-authored-by: Nilesh Gupta * refactor: added structure for spaces invites modal component * refactor: invite-component * fix: minor-bug * feat: Create Space API Integration (#494) * feat: create spaces integration * feat: added datetime picker * feat: completed create space API integration * feat: changed flow and time component * feat(spaces): initiate livepeer playback in start method (#499) * fix: add spaces for functions * fix: Separate page for space in the demo react APP * fix: start/stop spaces functions * fix: fix image and description types * fix: added functions to add and remove members from group * fix: spaces functions * fix: spaces functions refactoring * fix: few more changes * fix: spaces function testing * fix: spaces functions * fix: SDK bug fixes * fix: SDK bug fixes * fix: minor fixes * fix: minor fix * fix: minor fix * feat(video): add create mesh connection logic in Video class * feat(spaces): make video mesh compatible & add spaces class * feat(spaces): add backend methods in Space class * fix: Merge branch 'alpha' into 424-spaces-functions-webrtc-logic * fix(spaces): fix console errors and move out create, update functions from Space class * feat(spaces): initiate livepeer playback in start method * feat(spaces): store livepeer playback id in space description --------- Co-authored-by: Shoaib Mohammed * Add initialize method (#505) * fix: add spaces for functions * fix: Separate page for space in the demo react APP * fix: start/stop spaces functions * fix: fix image and description types * fix: added functions to add and remove members from group * fix: spaces functions * fix: spaces functions refactoring * fix: few more changes * fix: spaces function testing * fix: spaces functions * fix: SDK bug fixes * fix: SDK bug fixes * fix: minor fixes * fix: minor fix * fix: minor fix * feat(video): add create mesh connection logic in Video class * feat(spaces): make video mesh compatible & add spaces class * feat(spaces): add backend methods in Space class * fix: Merge branch 'alpha' into 424-spaces-functions-webrtc-logic * fix(spaces): fix console errors and move out create, update functions from Space class * feat(spaces): initiate livepeer playback in start method * feat(spaces): store livepeer playback id in space description * feat(spaces): add intitialize method --------- Co-authored-by: Shoaib Mohammed * refactor: resolved css in space banner * refactor: added a skeleton loading effect on space Banner component * feat: add invite functionality to create space (#506) * feat: added invite functionality * fix: add logic for time selector * fix: css fixes * refactor: info-on-widget (#504) * refactor: info-on-widget * refactor: add Space class to context * fix: padding, added new mic icons * fix: added-ref to context * feat: start added * fix: remove optional spaceId * fix: inf-bug * fix: effectAdded * fix(spaces): add is supported check in start * refactor: added-join-functionalities (#507) * refactor: added-join-functionalities * fix: screens * fix(spaces): fix livepeer stream creation in start --------- Co-authored-by: Madhur Gupta * Fix join and pgpPrivateKey in demoreact (#508) * refactor: info-on-widget * refactor: add Space class to context * fix: padding, added new mic icons * fix: added-ref to context * feat: start added * fix: remove optional spaceId * fix: inf-bug * fix: effectAdded * fix(spaces): add is supported check in start * refactor: added-join-functionalities * fix: screens * refactor: added-join-functionalities (#507) * refactor: added-join-functionalities * fix: screens * fix(spaces): fix livepeer stream creation in start * fix: join function --------- Co-authored-by: samarendra-push Co-authored-by: Samarendra Gouda <134079446+samarendra-push@users.noreply.github.com> * refactor: added feature of triggering widget from sdk * fix(spaces): fix join as speaker and listner * fix: resolved updating env and other class variables * Spaces/UI migration (#510) * fix: ui-migration * fix: migration fixes * refactor: added notification socket for space in uiweb * feat: add remove and admin func to invite modal (#509) * feat: add remove and admin func to invite modal * fix: fix null * fix(spaces): fix start * feat: add join functionality to invited spaces (#512) * feat: add join functionality to invited spaces * fix: open space widget after joining * refactor: add audio playback from space speakers (#511) * refactor: added a hidden Video container * fix: migrated initSpaceObject to parent component * feat(spaces): add user feeds socket handler logic --------- Co-authored-by: Nilesh Gupta Co-authored-by: Arnab Chatterjee <60937304+arn4b@users.noreply.github.com> Co-authored-by: Samarendra Gouda <134079446+samarendra-push@users.noreply.github.com> Co-authored-by: Samarendra Gouda Co-authored-by: Shoaib Mohammed Co-authored-by: aman035 Co-authored-by: samarendra-push * Spaces backend examples (#522) * fix: spaces documentation * Update README.md * fix: formatting issues * fix: uncommented code * Spaces SDK alpha publish (#520) * refactor: added initial SpacesUI class architecture * Update packages/uiweb/src/lib/components/space/SpacesUI.tsx Co-authored-by: Arnab Chatterjee <60937304+arn4b@users.noreply.github.com> * Update packages/uiweb/src/lib/components/space/SpacesUI.tsx Co-authored-by: Arnab Chatterjee <60937304+arn4b@users.noreply.github.com> * fix: refine code structure * refactor: change structure and added a test sample * feat: added themeprovider for spaces ui components (#436) * feat: feat: add themeprovider for spaces * fix: resolved conflicts * refactor: cleaned up provider * refactor: resolved comments * feat: added colors and themeing in demoreactapp * refactor: cleaned code * refactor: resolved comments * refactor: added a basic style structure for ease of use (#453) * feat: SpaceBanner Component (#438) * feat: SpaceBanner * refactor: removed-optionals * feat: space-banner functionality * fix: reverted app.tsx * fix: reverted app.tsx * fix: removed test svg file * refactor: change structure and added a test sample * feat: space-banner functionality * refactor: api-implementation * fix: removed-svg * refactor: mobile version * Revert "fix: removed test svg file" This reverts commit 7af756badaeb8435db60712c42ca57ef9ce9f74c. * Revert "refactor: change structure and added a test sample" This reverts commit b1e8745948a9ce5e0485ad51a8cffd07010a5186. * fix: revert * refactor: lastest-pull * feat: added-spaceBanner-test * refactor: cache-to-context * refactor: custom hook added for data * refactor: spaceDTO * fix: SpaceDTO implementation * refactor: participant-container * refactor: cleanups * fix: ui-fixes * fix: EOF newlines * fix: overflow-fixed * refactor: tweaked context structure a bit --------- Co-authored-by: Samarendra Gouda Co-authored-by: Nilesh Gupta * refactor: updated theme object along with light and dark theme * feat: Create Space Component (#454) * refactor: resolved merge conflicts * feat: added modals and modal behaviour logic * feat: modal inputs * feat: change modal logic + integr8 API * feat: added CSS for modals and inputs * fix: resolved PR comments * refactor: improve css * refactor: rft create modal * feat: added search input component * Refactor/space widget component (#458) * refactor: added basic design * refactor: added full widget with style * refactor: reduced fixed height of scheduled widget content * refactor: changes requested * refactor: resolved review comments * feat: add spaces info component (#474) * Feat/added members modal (#477) * refactor: added modal * refactor: added members modal * refactor: review comments * refactor: resolve review comments * fix: review comments * 424 spaces functions webrtc logic (#482) * fix: add spaces for functions * fix: Separate page for space in the demo react APP * fix: start/stop spaces functions * fix: fix image and description types * fix: added functions to add and remove members from group * fix: spaces functions * fix: spaces functions refactoring * fix: few more changes * fix: spaces function testing * fix: spaces functions * fix: SDK bug fixes * fix: SDK bug fixes * fix: minor fixes * fix: minor fix * fix: minor fix * feat(video): add create mesh connection logic in Video class * feat(spaces): make video mesh compatible & add spaces class * feat(spaces): add backend methods in Space class --------- Co-authored-by: Shoaib Mohammed Co-authored-by: Madhur Gupta * refactor: spaces UI Components refactor (#478) > replaced hardcoded styles with context theme >added smoother animations on collapsoble components >added profile cards to invite modal * refactor: added spaceUI class variables into context as well (#488) * refactor: added spaceUI class variables into context as well * refactor: resolve review comments * refactor: added a clickHandler in spaceBanner component for extra flexibility (#489) * fix(spaces): fix console errs and refactor create, update methods (#492) * fix: add spaces for functions * fix: Separate page for space in the demo react APP * fix: start/stop spaces functions * fix: fix image and description types * fix: added functions to add and remove members from group * fix: spaces functions * fix: spaces functions refactoring * fix: few more changes * fix: spaces function testing * fix: spaces functions * fix: SDK bug fixes * fix: SDK bug fixes * fix: minor fixes * fix: minor fix * fix: minor fix * feat(video): add create mesh connection logic in Video class * feat(spaces): make video mesh compatible & add spaces class * feat(spaces): add backend methods in Space class * fix: Merge branch 'alpha' into 424-spaces-functions-webrtc-logic * fix(spaces): fix console errors and move out create, update functions from Space class --------- Co-authored-by: Shoaib Mohammed * refactor: modified init class method * refactor/added-space-feed-component(#481) * feat: space-feed * refactor: space-feed * Deployment (#440) * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.1 * ci(restapi): 🎉 cut release to restapi-v1.0.1 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.3 * fix: success progressHook * ci(restapi): 🎉 cut release to restapi-v1.0.4 * ci(restapi): 🎉 cut release to restapi-v1.1.0 * ci(restapi): 🎉 cut release to restapi-v1.2.0 * ci(restapi): 🎉 cut release to restapi-v1.2.0 * ci(restapi): 🎉 cut release to restapi-v1.0.0 * fix(component): dummy * fix(component): dummy * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.2 * fix(component): dummy * ci(restapi): 🎉 cut release to restapi-v1.0.3 * ci(restapi): 🎉 cut release to restapi-v1.0.4 * ci(restapi): 🎉 cut release to restapi-v1.2.1 * fix: local for local development (#295) Co-Authored-By: aman035 * fix: version update * ci(restapi): 🎉 cut release to restapi-v1.2.2 * ci(restapi): 🎉 cut release to restapi-v1.2.3 * ci(restapi): 🎉 cut release to restapi-v1.2.4 * ci(restapi): 🎉 cut release to restapi-v1.2.5 * ci(restapi): 🎉 cut release to restapi-v1.2.6 * ci(restapi): 🎉 cut release to restapi-v1.2.7 * ci(socket): 🎉 cut release to socket-v0.5.0 * fix: test commit * ci(restapi): 🎉 cut release to restapi-v1.2.8 * ci(uiweb): 🎉 cut release to uiweb-v1.0.0 * ci(uiweb): 🎉 cut release to uiweb-v1.0.0 * ci(uiweb): 🎉 cut release to uiweb-v1.0.1 * fix: added ci-version-beta * fix: added ci-version-beta * ci(restapi): 🎉 cut beta release to restapi-v1.2.9 * fix: added releaseType * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.0 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.0 * ci(restapi): 🎉 cut release to restapi-v1.2.10 * ci(restapi): 🎉 cut release to restapi-v1.2.10 * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-beta.1 * ci(restapi): 🎉 cut release to restapi-v1.2.11 * fix: linkedListHash test cases removed & CI version corrected * fix: update name to beta * ci(restapi): 🎉 cut release to restapi-v1.2.12 * ci(restapi): 🎉 cut release to restapi-v1.2.12 * ci(restapi): 🎉 cut release to restapi-v1.2.13 * ci(restapi): 🎉 cut release to restapi-v1.2.14 * ci(restapi): 🎉 cut release to restapi-v1.2.15 * fix: update package json * fix: updated socket version * ci(uiweb): 🎉 cut release to uiweb-v1.0.2 * fix: socket lib update * ci(uiweb): 🎉 cut release to uiweb-v1.0.2 * ci(restapi): 🎉 cut release to restapi-v1.2.16 * ci(restapi): 🎉 cut release to restapi-v1.3.0 * ci(restapi): 🎉 cut release to restapi-v1.3.1 * ci(socket): 🎉 cut release to socket-v0.5.1 * ci(restapi): 🎉 cut release to restapi-v1.3.2 * ci(restapi): 🎉 cut release to restapi-v1.3.3 * ci(restapi): 🎉 cut release to restapi-v1.3.4 --------- Co-authored-by: aman035 * feat: space-feed * refactor: space-feed * fix: api-call-custom-hooks * fix: api-call * refactor: enums/changes * fix: scrollable * fix: scrolling-issue * feat: filter-changes * fix: added types * fix: loader-issue * fix: tab-button-color * feat: new-filter and prop * fix: ended-logic && participant-number logic * refactor: add onBannerClick * fix: conflicts * revert: messed-up spaceBanner * fix: onClick issue * fix: onClick and cleanups * refactor: new pagination interface * fix: scroll-logic * fix: scroll-final * fix: .. * fix: removed any * fix: onClick-issue * fix: loading-context-to-state * refactor: add-NoSpaceIcons * refactor: new-ui-layout * refactor: new-ui-layout --------- Co-authored-by: Mohammed S Co-authored-by: aman035 Co-authored-by: Nilesh Gupta * refactor: added structure for spaces invites modal component * refactor: invite-component * fix: minor-bug * feat: Create Space API Integration (#494) * feat: create spaces integration * feat: added datetime picker * feat: completed create space API integration * feat: changed flow and time component * feat(spaces): initiate livepeer playback in start method (#499) * fix: add spaces for functions * fix: Separate page for space in the demo react APP * fix: start/stop spaces functions * fix: fix image and description types * fix: added functions to add and remove members from group * fix: spaces functions * fix: spaces functions refactoring * fix: few more changes * fix: spaces function testing * fix: spaces functions * fix: SDK bug fixes * fix: SDK bug fixes * fix: minor fixes * fix: minor fix * fix: minor fix * feat(video): add create mesh connection logic in Video class * feat(spaces): make video mesh compatible & add spaces class * feat(spaces): add backend methods in Space class * fix: Merge branch 'alpha' into 424-spaces-functions-webrtc-logic * fix(spaces): fix console errors and move out create, update functions from Space class * feat(spaces): initiate livepeer playback in start method * feat(spaces): store livepeer playback id in space description --------- Co-authored-by: Shoaib Mohammed * Add initialize method (#505) * fix: add spaces for functions * fix: Separate page for space in the demo react APP * fix: start/stop spaces functions * fix: fix image and description types * fix: added functions to add and remove members from group * fix: spaces functions * fix: spaces functions refactoring * fix: few more changes * fix: spaces function testing * fix: spaces functions * fix: SDK bug fixes * fix: SDK bug fixes * fix: minor fixes * fix: minor fix * fix: minor fix * feat(video): add create mesh connection logic in Video class * feat(spaces): make video mesh compatible & add spaces class * feat(spaces): add backend methods in Space class * fix: Merge branch 'alpha' into 424-spaces-functions-webrtc-logic * fix(spaces): fix console errors and move out create, update functions from Space class * feat(spaces): initiate livepeer playback in start method * feat(spaces): store livepeer playback id in space description * feat(spaces): add intitialize method --------- Co-authored-by: Shoaib Mohammed * refactor: resolved css in space banner * refactor: added a skeleton loading effect on space Banner component * feat: add invite functionality to create space (#506) * feat: added invite functionality * fix: add logic for time selector * fix: css fixes * refactor: info-on-widget (#504) * refactor: info-on-widget * refactor: add Space class to context * fix: padding, added new mic icons * fix: added-ref to context * feat: start added * fix: remove optional spaceId * fix: inf-bug * fix: effectAdded * fix(spaces): add is supported check in start * refactor: added-join-functionalities (#507) * refactor: added-join-functionalities * fix: screens * fix(spaces): fix livepeer stream creation in start --------- Co-authored-by: Madhur Gupta * Fix join and pgpPrivateKey in demoreact (#508) * refactor: info-on-widget * refactor: add Space class to context * fix: padding, added new mic icons * fix: added-ref to context * feat: start added * fix: remove optional spaceId * fix: inf-bug * fix: effectAdded * fix(spaces): add is supported check in start * refactor: added-join-functionalities * fix: screens * refactor: added-join-functionalities (#507) * refactor: added-join-functionalities * fix: screens * fix(spaces): fix livepeer stream creation in start * fix: join function --------- Co-authored-by: samarendra-push Co-authored-by: Samarendra Gouda <134079446+samarendra-push@users.noreply.github.com> * refactor: added feature of triggering widget from sdk * fix(spaces): fix join as speaker and listner * fix: resolved updating env and other class variables * Spaces/UI migration (#510) * fix: ui-migration * fix: migration fixes * refactor: added notification socket for space in uiweb * feat: add remove and admin func to invite modal (#509) * feat: add remove and admin func to invite modal * fix: fix null * fix(spaces): fix start * feat: add join functionality to invited spaces (#512) * feat: add join functionality to invited spaces * fix: open space widget after joining * refactor: add audio playback from space speakers (#511) * refactor: added a hidden Video container * fix: migrated initSpaceObject to parent component * feat(spaces): add user feeds socket handler logic * fix: fix create invite UI edge cases (#515) * fix: fix create invite UI edge cases * fix: fix env * fix: fix state behaviour * fix: add wallet as name if name string empty add wallet as name if name string empty * refactor: added join function and socket code (#517) * refactor: added join function and socket code * refactor(spaces): fix mesh creation logic * refactor(spaces): remove unused imports from context * refactor(spaces): remove unused code and improve positioning of code blocks --------- Co-authored-by: Madhur Gupta * Fix isJoined, add hidden video tag (#514) * refactor: added a hidden Video container * fix: migrated initSpaceObject to parent component * fix: WIP isJoined * fix: join as a listener --------- Co-authored-by: Madhur Gupta * fix(spaces): add create audio call before join for speakers (#518) * Widget/videoplayer (#519) * refactor: added a hidden Video container * fix: migrated initSpaceObject to parent component * fix: WIP isJoined * fix: revert husky * fix: nx.json revert * fix: join as a listener * fix: start ui-logic refactor * fix: merge-conflicts * fix: isListener * fix(spaces): fix isSpeaker and isListner logic * feat: added blockies (#523) --------- Co-authored-by: Nilesh Gupta Co-authored-by: Arnab Chatterjee <60937304+arn4b@users.noreply.github.com> Co-authored-by: Samarendra Gouda <134079446+samarendra-push@users.noreply.github.com> Co-authored-by: Samarendra Gouda Co-authored-by: Shoaib Mohammed Co-authored-by: aman035 Co-authored-by: samarendra-push * ci(restapi): 🎉 cut beta release to restapi-v0.0.1-alpha.23 * Update README.md * fix: rename chats to spaces * fix: spaces examples fixes * fix: renamed spaces variables and removed some unused variables * Update README.md --------- Co-authored-by: Shoaib Mohammed Co-authored-by: Madhur Gupta Co-authored-by: Madhur Gupta Co-authored-by: strykerin Co-authored-by: Nilesh Gupta Co-authored-by: Arnab Chatterjee <60937304+arn4b@users.noreply.github.com> Co-authored-by: Samarendra Gouda <134079446+samarendra-push@users.noreply.github.com> Co-authored-by: Samarendra Gouda Co-authored-by: samarendra-push Co-authored-by: Mohammed S Co-authored-by: Monalisha Mishra --- .gitignore | 1 + .../src/app/ChatTest/AddAdminsToGroupTest.tsx | 106 + .../app/ChatTest/AddMembersToGroupTest.tsx | 108 + .../demoreact/src/app/ChatTest/ChatTest.tsx | 12 + .../ChatTest/RemoveAdminsFromGroupTest.tsx | 106 + .../ChatTest/RemoveMembersFromGroupTest.tsx | 92 + packages/demoreact/src/app/ChatTest/helper.ts | 19 + packages/demoreact/src/app/ChatWidgetTest.tsx | 3 + .../app/SpaceTest/AddListenersToSpaceTest.tsx | 104 + .../app/SpaceTest/AddSpeakersToSpaceTest.tsx | 105 + .../app/SpaceTest/ApproveSpaceRequestTest.tsx | 101 + .../src/app/SpaceTest/CreateSpaceTest.tsx | 299 +++ .../src/app/SpaceTest/GetSpaceInfoTest.tsx | 78 + .../src/app/SpaceTest/GetSpaceTest.tsx | 78 + .../app/SpaceTest/GetSpacesRequestsTest.tsx | 132 ++ .../src/app/SpaceTest/GetSpacesTest.tsx | 132 ++ .../app/SpaceTest/GetSpacesTrendingTest.tsx | 105 + .../RemoveListenersFromSpaceTest.tsx | 108 + .../SpaceTest/RemoveSpeakersFromSpaceTest.tsx | 104 + .../demoreact/src/app/SpaceTest/SpaceTest.tsx | 79 + .../src/app/SpaceTest/StartSpaceTest.tsx | 91 + .../src/app/SpaceTest/StopSpaceTest.tsx | 93 + .../src/app/SpaceTest/UpdateSpaceTest.tsx | 231 ++ .../app/SpaceUITest/CreateSpaceComponent.tsx | 7 + .../src/app/SpaceUITest/SpaceBanner.tsx | 63 + .../src/app/SpaceUITest/SpaceFeed.tsx | 85 + .../src/app/SpaceUITest/SpaceInvites.tsx | 9 + .../src/app/SpaceUITest/SpaceUITest.tsx | 52 + .../src/app/SpaceUITest/SpaceWidget.tsx | 155 ++ .../demoreact/src/app/SpaceUITest/index.tsx | 29 + .../app/SpaceUITest/useSpaceComponents.tsx | 64 + packages/demoreact/src/app/app.tsx | 259 ++- .../examples/sdk-backend-node/src/main.ts | 3 + .../sdk-backend-node/src/spaces/index.ts | 624 ++++++ .../sdk-frontend/{video => }/README.md | 0 .../components/Spaces/Checkbox.tsx | 15 + .../components/Spaces/Dropdown.tsx | 35 + .../components/Spaces/StyledComponents.tsx | 61 + .../sdk-frontend/components/Spaces/index.ts | 0 .../components/Spaces/useSpaceComponent.tsx | 72 + .../{video => }/components/VideoPlayer.tsx | 0 .../{video => }/helpers/getCAIPAddress.ts | 0 .../{video => }/hooks/usePushSocket.ts | 0 .../sdk-frontend/{video => }/next-env.d.ts | 0 .../sdk-frontend/{video => }/next.config.js | 0 .../sdk-frontend/{video => }/package.json | 3 +- .../sdk-frontend/{video => }/pages/_app.tsx | 25 +- .../examples/sdk-frontend/pages/index.tsx | 43 + .../sdk-frontend/pages/spaces/banner.tsx | 71 + .../sdk-frontend/pages/spaces/create.tsx | 16 + .../sdk-frontend/pages/spaces/feed.tsx | 90 + .../sdk-frontend/pages/spaces/index.tsx | 68 + .../sdk-frontend/pages/spaces/invites.tsx | 16 + .../sdk-frontend/pages/spaces/widget.tsx | 163 ++ .../pages/index.tsx => pages/video.tsx} | 0 .../{video => }/styles/globals.css | 0 .../sdk-frontend/{video => }/tsconfig.json | 0 .../sdk-frontend/video/pages/spaces/index.tsx | 0 packages/package-lock.json | 6 + packages/restapi/CHANGELOG.md | 179 +- packages/restapi/README.md | 1935 ++++++++++++++++- packages/restapi/package-lock.json | 519 ++++- packages/restapi/package.json | 7 +- packages/restapi/src/lib/chat/addAdmins.ts | 103 + packages/restapi/src/lib/chat/addMembers.ts | 98 + .../restapi/src/lib/chat/approveRequest.ts | 7 +- packages/restapi/src/lib/chat/createGroup.ts | 22 +- .../restapi/src/lib/chat/helpers/inbox.ts | 96 +- .../src/lib/chat/helpers/payloadHelper.ts | 162 +- .../restapi/src/lib/chat/helpers/validator.ts | 89 +- packages/restapi/src/lib/chat/index.ts | 4 + packages/restapi/src/lib/chat/removeAdmins.ts | 111 + .../restapi/src/lib/chat/removeMembers.ts | 97 + packages/restapi/src/lib/chat/send.ts | 1 + packages/restapi/src/lib/chat/updateGroup.ts | 25 +- packages/restapi/src/lib/index.ts | 2 + .../restapi/src/lib/payloads/constants.ts | 30 + packages/restapi/src/lib/payloads/index.ts | 9 +- packages/restapi/src/lib/space/Space.ts | 230 ++ .../src/lib/space/acceptPromotionInvite.ts | 28 + .../src/lib/space/acceptPromotionRequest.ts | 33 + .../restapi/src/lib/space/addListeners.ts | 49 + packages/restapi/src/lib/space/addSpeaker.ts | 34 + packages/restapi/src/lib/space/addSpeakers.ts | 33 + packages/restapi/src/lib/space/approve.ts | 58 + .../restapi/src/lib/space/connectInvitee.ts | 30 + .../restapi/src/lib/space/connectPromotor.ts | 13 + packages/restapi/src/lib/space/create.ts | 70 + packages/restapi/src/lib/space/get.ts | 39 + .../lib/space/helpers/addToMergedStream.ts | 10 + .../lib/space/helpers/getMergeStreamObject.ts | 14 + packages/restapi/src/lib/space/index.ts | 14 + packages/restapi/src/lib/space/info.ts | 33 + packages/restapi/src/lib/space/initialize.ts | 17 + .../restapi/src/lib/space/inviteToPromote.ts | 35 + packages/restapi/src/lib/space/join.ts | 83 + packages/restapi/src/lib/space/leave.ts | 26 + .../src/lib/space/rejectPromotionInvite.ts | 18 + .../src/lib/space/rejectPromotionRequest.ts | 17 + .../restapi/src/lib/space/removeListeners.ts | 49 + .../restapi/src/lib/space/removeSpeaker.ts | 37 + .../restapi/src/lib/space/removeSpeakers.ts | 41 + .../src/lib/space/requestToBePromoted.ts | 28 + packages/restapi/src/lib/space/requests.ts | 65 + packages/restapi/src/lib/space/spaces.ts | 62 + packages/restapi/src/lib/space/start.ts | 139 ++ packages/restapi/src/lib/space/stop.ts | 72 + packages/restapi/src/lib/space/trending.ts | 47 + packages/restapi/src/lib/space/update.ts | 71 + packages/restapi/src/lib/space/update_out.ts | 72 + packages/restapi/src/lib/types/index.ts | 92 +- packages/restapi/src/lib/video/Video.ts | 649 ++++-- .../video/helpers/getConnectToAddresses.ts | 17 + .../video/helpers/getConnectedAddresses.ts | 17 + .../lib/video/helpers/getIceServerConfig.ts | 14 +- .../helpers/getIncomingIndexFromAddress.ts | 7 + .../helpers/sendVideoCallNotification.ts | 32 +- packages/restapi/src/lib/video/index.ts | 1 + packages/restapi/yarn.lock | 815 +++---- packages/uiweb/package.json | 1 + .../ChatAndNotification.tsx | 8 +- packages/uiweb/src/lib/components/index.ts | 3 +- .../space/SpaceBanner/SpaceBanner.tsx | 238 ++ .../SpaceBannerLoadingSkeleton.tsx | 137 ++ .../lib/components/space/SpaceBanner/index.ts | 1 + .../SCWButton/SCWButton.tsx | 57 + .../SpaceCreationWidget/SCWButton/index.ts | 1 + .../SCWCreateModal/SCWCreateModal.tsx | 90 + .../SCWCreateModal/index.ts | 1 + .../SCWInviteModal/SCWInviteModal.tsx | 423 ++++ .../SCWInviteModal/index.ts | 1 + .../SCWScheduleModal/SCWScheduleModal.tsx | 59 + .../SCWScheduleModal/index.ts | 1 + .../SpaceCreationWidget.tsx | 192 ++ .../space/SpaceCreationWidget/index.ts | 1 + .../components/space/SpaceFeed/SpaceFeed.tsx | 478 ++++ .../lib/components/space/SpaceFeed/index.ts | 1 + .../space/SpaceInvites/SpaceInvites.tsx | 174 ++ .../components/space/SpaceInvites/index.ts | 1 + .../SpaceWidget/LiveSpaceProfileContainer.tsx | 90 + .../space/SpaceWidget/LiveWidgetContent.tsx | 229 ++ .../SpaceWidget/ScheduledWidgetContent.tsx | 231 ++ .../SpaceWidget/SpaceMembersSectionModal.tsx | 256 +++ .../space/SpaceWidget/SpaceWidget.tsx | 145 ++ .../space/SpaceWidget/SpacesInfo.tsx | 124 ++ .../space/SpaceWidget/VideoPlayer.tsx | 25 + .../space/SpaceWidget/WidgetContent.tsx | 82 + .../space/SpaceWidget/WidgetHeader.tsx | 213 ++ .../space/SpaceWidget/helpers/utils.ts | 31 + .../lib/components/space/SpaceWidget/index.ts | 1 + .../src/lib/components/space/SpacesUI.tsx | 78 + .../src/lib/components/space/exportedTypes.ts | 30 + .../lib/components/space/helpers/blockies.ts | 119 + .../src/lib/components/space/helpers/date.ts | 48 + .../src/lib/components/space/helpers/space.ts | 12 + .../uiweb/src/lib/components/space/index.ts | 15 + .../components/space/reusables/Accordion.tsx | 89 + .../lib/components/space/reusables/Button.tsx | 82 + .../components/space/reusables/Checkbox.tsx | 18 + .../space/reusables/DateTimePicker.tsx | 149 ++ .../space/reusables/HostPfpContainer.tsx | 111 + .../lib/components/space/reusables/Modal.tsx | 83 + .../space/reusables/ModalHeader.tsx | 101 + .../space/reusables/ParticipantContainer.tsx | 98 + .../space/reusables/ProfileContainer.tsx | 229 ++ .../space/reusables/SearchInput.tsx | 76 + .../components/space/reusables/Spinner.tsx | 35 + .../components/space/reusables/TextInput.tsx | 71 + .../lib/components/space/reusables/index.ts | 2 + .../components/space/theme/ThemeProvider.tsx | 19 + .../src/lib/components/space/theme/index.ts | 58 + .../components/supportChat/AddressInfo.tsx | 2 +- packages/uiweb/src/lib/config/index.ts | 3 +- packages/uiweb/src/lib/config/styles.tsx | 75 + packages/uiweb/src/lib/context/index.ts | 3 + .../uiweb/src/lib/context/spacesContext.ts | 131 ++ .../lib/dataProviders/SpaceDataProvider.tsx | 300 +++ packages/uiweb/src/lib/dataProviders/index.ts | 1 + packages/uiweb/src/lib/helpers/apiHelper.ts | 9 + packages/uiweb/src/lib/helpers/date.ts | 6 + packages/uiweb/src/lib/helpers/index.ts | 5 +- packages/uiweb/src/lib/hooks/index.ts | 3 +- packages/uiweb/src/lib/hooks/space/index.ts | 8 + .../src/lib/hooks/space/useFeedScroll.ts | 13 + .../src/lib/hooks/space/useGetSpaceInfo.ts | 37 + .../uiweb/src/lib/hooks/space/useMySpaces.ts | 44 + .../src/lib/hooks/space/usePopularSpaces.ts | 41 + .../lib/hooks/space/usePushSpaceSocket.tsx | 112 + .../uiweb/src/lib/hooks/space/useSpaceData.ts | 11 + .../hooks/space/useSpaceNotificationSocket.ts | 150 ++ .../src/lib/hooks/space/useSpaceRequests.ts | 45 + packages/uiweb/src/lib/hooks/useChatScroll.ts | 2 +- packages/uiweb/src/lib/icons/ArrowLeft.svg | 4 + packages/uiweb/src/lib/icons/ArrowLeft.tsx | 9 + .../uiweb/src/lib/icons/CalendarPurple.tsx | 28 + packages/uiweb/src/lib/icons/CaretDown.svg | 3 + .../uiweb/src/lib/icons/CaretDownGrey.svg | 3 + packages/uiweb/src/lib/icons/CaretUp.svg | 3 + packages/uiweb/src/lib/icons/CaretUpGrey.svg | 3 + packages/uiweb/src/lib/icons/CloseSvg.tsx | 12 +- packages/uiweb/src/lib/icons/Members.svg | 18 + packages/uiweb/src/lib/icons/MicEngage.svg | 3 + packages/uiweb/src/lib/icons/Minimize.tsx | 2 +- packages/uiweb/src/lib/icons/Muted.svg | 3 + packages/uiweb/src/lib/icons/Share.svg | 14 + packages/uiweb/src/lib/icons/Spaces.svg | 19 + packages/uiweb/src/lib/icons/atVector.svg | 4 + packages/uiweb/src/lib/icons/calendar.svg | 6 + .../uiweb/src/lib/icons/calendarPurple.svg | 4 + packages/uiweb/src/lib/icons/checkIcon.svg | 3 + packages/uiweb/src/lib/icons/copyVector.svg | 4 + packages/uiweb/src/lib/icons/filter.svg | 3 + packages/uiweb/src/lib/icons/hand.svg | 11 + packages/uiweb/src/lib/icons/live.svg | 13 + packages/uiweb/src/lib/icons/micoff.svg | 3 + packages/uiweb/src/lib/icons/micon.svg | 5 + packages/uiweb/src/lib/icons/scheduled.svg | 6 + packages/uiweb/src/lib/icons/settings.svg | 5 + .../uiweb/src/lib/icons/settingsBlack.svg | 5 + .../uiweb/src/lib/icons/twitterVector.svg | 3 + packages/uiweb/src/lib/index.ts | 1 + packages/uiweb/yarn.lock | 660 +++++- 222 files changed, 16643 insertions(+), 1064 deletions(-) create mode 100644 packages/demoreact/src/app/ChatTest/AddAdminsToGroupTest.tsx create mode 100644 packages/demoreact/src/app/ChatTest/AddMembersToGroupTest.tsx create mode 100644 packages/demoreact/src/app/ChatTest/RemoveAdminsFromGroupTest.tsx create mode 100644 packages/demoreact/src/app/ChatTest/RemoveMembersFromGroupTest.tsx create mode 100644 packages/demoreact/src/app/ChatTest/helper.ts create mode 100644 packages/demoreact/src/app/SpaceTest/AddListenersToSpaceTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/AddSpeakersToSpaceTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/ApproveSpaceRequestTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/CreateSpaceTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/GetSpaceInfoTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/GetSpaceTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/GetSpacesRequestsTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/GetSpacesTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/GetSpacesTrendingTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/RemoveListenersFromSpaceTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/RemoveSpeakersFromSpaceTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/SpaceTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/StartSpaceTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/StopSpaceTest.tsx create mode 100644 packages/demoreact/src/app/SpaceTest/UpdateSpaceTest.tsx create mode 100644 packages/demoreact/src/app/SpaceUITest/CreateSpaceComponent.tsx create mode 100644 packages/demoreact/src/app/SpaceUITest/SpaceBanner.tsx create mode 100644 packages/demoreact/src/app/SpaceUITest/SpaceFeed.tsx create mode 100644 packages/demoreact/src/app/SpaceUITest/SpaceInvites.tsx create mode 100644 packages/demoreact/src/app/SpaceUITest/SpaceUITest.tsx create mode 100644 packages/demoreact/src/app/SpaceUITest/SpaceWidget.tsx create mode 100644 packages/demoreact/src/app/SpaceUITest/index.tsx create mode 100644 packages/demoreact/src/app/SpaceUITest/useSpaceComponents.tsx create mode 100644 packages/examples/sdk-backend-node/src/spaces/index.ts rename packages/examples/sdk-frontend/{video => }/README.md (100%) create mode 100644 packages/examples/sdk-frontend/components/Spaces/Checkbox.tsx create mode 100644 packages/examples/sdk-frontend/components/Spaces/Dropdown.tsx create mode 100644 packages/examples/sdk-frontend/components/Spaces/StyledComponents.tsx create mode 100644 packages/examples/sdk-frontend/components/Spaces/index.ts create mode 100644 packages/examples/sdk-frontend/components/Spaces/useSpaceComponent.tsx rename packages/examples/sdk-frontend/{video => }/components/VideoPlayer.tsx (100%) rename packages/examples/sdk-frontend/{video => }/helpers/getCAIPAddress.ts (100%) rename packages/examples/sdk-frontend/{video => }/hooks/usePushSocket.ts (100%) rename packages/examples/sdk-frontend/{video => }/next-env.d.ts (100%) rename packages/examples/sdk-frontend/{video => }/next.config.js (100%) rename packages/examples/sdk-frontend/{video => }/package.json (85%) rename packages/examples/sdk-frontend/{video => }/pages/_app.tsx (56%) create mode 100644 packages/examples/sdk-frontend/pages/index.tsx create mode 100644 packages/examples/sdk-frontend/pages/spaces/banner.tsx create mode 100644 packages/examples/sdk-frontend/pages/spaces/create.tsx create mode 100644 packages/examples/sdk-frontend/pages/spaces/feed.tsx create mode 100644 packages/examples/sdk-frontend/pages/spaces/index.tsx create mode 100644 packages/examples/sdk-frontend/pages/spaces/invites.tsx create mode 100644 packages/examples/sdk-frontend/pages/spaces/widget.tsx rename packages/examples/sdk-frontend/{video/pages/index.tsx => pages/video.tsx} (100%) rename packages/examples/sdk-frontend/{video => }/styles/globals.css (100%) rename packages/examples/sdk-frontend/{video => }/tsconfig.json (100%) create mode 100644 packages/examples/sdk-frontend/video/pages/spaces/index.tsx create mode 100644 packages/package-lock.json create mode 100644 packages/restapi/src/lib/chat/addAdmins.ts create mode 100644 packages/restapi/src/lib/chat/addMembers.ts create mode 100644 packages/restapi/src/lib/chat/removeAdmins.ts create mode 100644 packages/restapi/src/lib/chat/removeMembers.ts create mode 100644 packages/restapi/src/lib/space/Space.ts create mode 100644 packages/restapi/src/lib/space/acceptPromotionInvite.ts create mode 100644 packages/restapi/src/lib/space/acceptPromotionRequest.ts create mode 100644 packages/restapi/src/lib/space/addListeners.ts create mode 100644 packages/restapi/src/lib/space/addSpeaker.ts create mode 100644 packages/restapi/src/lib/space/addSpeakers.ts create mode 100644 packages/restapi/src/lib/space/approve.ts create mode 100644 packages/restapi/src/lib/space/connectInvitee.ts create mode 100644 packages/restapi/src/lib/space/connectPromotor.ts create mode 100644 packages/restapi/src/lib/space/create.ts create mode 100644 packages/restapi/src/lib/space/get.ts create mode 100644 packages/restapi/src/lib/space/helpers/addToMergedStream.ts create mode 100644 packages/restapi/src/lib/space/helpers/getMergeStreamObject.ts create mode 100644 packages/restapi/src/lib/space/index.ts create mode 100644 packages/restapi/src/lib/space/info.ts create mode 100644 packages/restapi/src/lib/space/initialize.ts create mode 100644 packages/restapi/src/lib/space/inviteToPromote.ts create mode 100644 packages/restapi/src/lib/space/join.ts create mode 100644 packages/restapi/src/lib/space/leave.ts create mode 100644 packages/restapi/src/lib/space/rejectPromotionInvite.ts create mode 100644 packages/restapi/src/lib/space/rejectPromotionRequest.ts create mode 100644 packages/restapi/src/lib/space/removeListeners.ts create mode 100644 packages/restapi/src/lib/space/removeSpeaker.ts create mode 100644 packages/restapi/src/lib/space/removeSpeakers.ts create mode 100644 packages/restapi/src/lib/space/requestToBePromoted.ts create mode 100644 packages/restapi/src/lib/space/requests.ts create mode 100644 packages/restapi/src/lib/space/spaces.ts create mode 100644 packages/restapi/src/lib/space/start.ts create mode 100644 packages/restapi/src/lib/space/stop.ts create mode 100644 packages/restapi/src/lib/space/trending.ts create mode 100644 packages/restapi/src/lib/space/update.ts create mode 100644 packages/restapi/src/lib/space/update_out.ts create mode 100644 packages/restapi/src/lib/video/helpers/getConnectToAddresses.ts create mode 100644 packages/restapi/src/lib/video/helpers/getConnectedAddresses.ts create mode 100644 packages/restapi/src/lib/video/helpers/getIncomingIndexFromAddress.ts create mode 100644 packages/uiweb/src/lib/components/space/SpaceBanner/SpaceBanner.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceBanner/SpaceBannerLoadingSkeleton.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceBanner/index.ts create mode 100644 packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/SCWButton.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/index.ts create mode 100644 packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/SCWCreateModal.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/index.ts create mode 100644 packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/SCWInviteModal.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/index.ts create mode 100644 packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/SCWScheduleModal.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/index.ts create mode 100644 packages/uiweb/src/lib/components/space/SpaceCreationWidget/SpaceCreationWidget.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceCreationWidget/index.ts create mode 100644 packages/uiweb/src/lib/components/space/SpaceFeed/SpaceFeed.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceFeed/index.ts create mode 100644 packages/uiweb/src/lib/components/space/SpaceInvites/SpaceInvites.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceInvites/index.ts create mode 100644 packages/uiweb/src/lib/components/space/SpaceWidget/LiveSpaceProfileContainer.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceWidget/LiveWidgetContent.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceWidget/ScheduledWidgetContent.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceWidget/SpaceMembersSectionModal.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceWidget/SpaceWidget.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceWidget/SpacesInfo.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceWidget/VideoPlayer.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceWidget/WidgetContent.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceWidget/WidgetHeader.tsx create mode 100644 packages/uiweb/src/lib/components/space/SpaceWidget/helpers/utils.ts create mode 100644 packages/uiweb/src/lib/components/space/SpaceWidget/index.ts create mode 100644 packages/uiweb/src/lib/components/space/SpacesUI.tsx create mode 100644 packages/uiweb/src/lib/components/space/exportedTypes.ts create mode 100644 packages/uiweb/src/lib/components/space/helpers/blockies.ts create mode 100644 packages/uiweb/src/lib/components/space/helpers/date.ts create mode 100644 packages/uiweb/src/lib/components/space/helpers/space.ts create mode 100644 packages/uiweb/src/lib/components/space/index.ts create mode 100644 packages/uiweb/src/lib/components/space/reusables/Accordion.tsx create mode 100644 packages/uiweb/src/lib/components/space/reusables/Button.tsx create mode 100644 packages/uiweb/src/lib/components/space/reusables/Checkbox.tsx create mode 100644 packages/uiweb/src/lib/components/space/reusables/DateTimePicker.tsx create mode 100644 packages/uiweb/src/lib/components/space/reusables/HostPfpContainer.tsx create mode 100644 packages/uiweb/src/lib/components/space/reusables/Modal.tsx create mode 100644 packages/uiweb/src/lib/components/space/reusables/ModalHeader.tsx create mode 100644 packages/uiweb/src/lib/components/space/reusables/ParticipantContainer.tsx create mode 100644 packages/uiweb/src/lib/components/space/reusables/ProfileContainer.tsx create mode 100644 packages/uiweb/src/lib/components/space/reusables/SearchInput.tsx create mode 100644 packages/uiweb/src/lib/components/space/reusables/Spinner.tsx create mode 100644 packages/uiweb/src/lib/components/space/reusables/TextInput.tsx create mode 100644 packages/uiweb/src/lib/components/space/reusables/index.ts create mode 100644 packages/uiweb/src/lib/components/space/theme/ThemeProvider.tsx create mode 100644 packages/uiweb/src/lib/components/space/theme/index.ts create mode 100644 packages/uiweb/src/lib/config/styles.tsx create mode 100644 packages/uiweb/src/lib/context/spacesContext.ts create mode 100644 packages/uiweb/src/lib/dataProviders/SpaceDataProvider.tsx create mode 100644 packages/uiweb/src/lib/dataProviders/index.ts create mode 100644 packages/uiweb/src/lib/helpers/apiHelper.ts create mode 100644 packages/uiweb/src/lib/helpers/date.ts create mode 100644 packages/uiweb/src/lib/hooks/space/index.ts create mode 100644 packages/uiweb/src/lib/hooks/space/useFeedScroll.ts create mode 100644 packages/uiweb/src/lib/hooks/space/useGetSpaceInfo.ts create mode 100644 packages/uiweb/src/lib/hooks/space/useMySpaces.ts create mode 100644 packages/uiweb/src/lib/hooks/space/usePopularSpaces.ts create mode 100644 packages/uiweb/src/lib/hooks/space/usePushSpaceSocket.tsx create mode 100644 packages/uiweb/src/lib/hooks/space/useSpaceData.ts create mode 100644 packages/uiweb/src/lib/hooks/space/useSpaceNotificationSocket.ts create mode 100644 packages/uiweb/src/lib/hooks/space/useSpaceRequests.ts create mode 100644 packages/uiweb/src/lib/icons/ArrowLeft.svg create mode 100644 packages/uiweb/src/lib/icons/ArrowLeft.tsx create mode 100644 packages/uiweb/src/lib/icons/CalendarPurple.tsx create mode 100644 packages/uiweb/src/lib/icons/CaretDown.svg create mode 100644 packages/uiweb/src/lib/icons/CaretDownGrey.svg create mode 100644 packages/uiweb/src/lib/icons/CaretUp.svg create mode 100644 packages/uiweb/src/lib/icons/CaretUpGrey.svg create mode 100644 packages/uiweb/src/lib/icons/Members.svg create mode 100644 packages/uiweb/src/lib/icons/MicEngage.svg create mode 100644 packages/uiweb/src/lib/icons/Muted.svg create mode 100644 packages/uiweb/src/lib/icons/Share.svg create mode 100644 packages/uiweb/src/lib/icons/Spaces.svg create mode 100644 packages/uiweb/src/lib/icons/atVector.svg create mode 100644 packages/uiweb/src/lib/icons/calendar.svg create mode 100644 packages/uiweb/src/lib/icons/calendarPurple.svg create mode 100644 packages/uiweb/src/lib/icons/checkIcon.svg create mode 100644 packages/uiweb/src/lib/icons/copyVector.svg create mode 100644 packages/uiweb/src/lib/icons/filter.svg create mode 100644 packages/uiweb/src/lib/icons/hand.svg create mode 100644 packages/uiweb/src/lib/icons/live.svg create mode 100644 packages/uiweb/src/lib/icons/micoff.svg create mode 100644 packages/uiweb/src/lib/icons/micon.svg create mode 100644 packages/uiweb/src/lib/icons/scheduled.svg create mode 100644 packages/uiweb/src/lib/icons/settings.svg create mode 100644 packages/uiweb/src/lib/icons/settingsBlack.svg create mode 100644 packages/uiweb/src/lib/icons/twitterVector.svg diff --git a/.gitignore b/.gitignore index 2eb9aa0f6..1d4900b27 100644 --- a/.gitignore +++ b/.gitignore @@ -288,3 +288,4 @@ buck-out/ packages/restapi/yarn.lock yarn.lock *.env +**/.next diff --git a/packages/demoreact/src/app/ChatTest/AddAdminsToGroupTest.tsx b/packages/demoreact/src/app/ChatTest/AddAdminsToGroupTest.tsx new file mode 100644 index 000000000..b1d807e46 --- /dev/null +++ b/packages/demoreact/src/app/ChatTest/AddAdminsToGroupTest.tsx @@ -0,0 +1,106 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import ChatTest from './ChatTest'; + +const AddAdminsToGroupTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [chatId, setChatId] = useState(''); + const [memberAddress, setMemberAddress] = useState(''); + const [sendResponse, setSendResponse] = useState(''); + const [account, setAccount] = useState(acc); + + const updateChatId = (e: React.SyntheticEvent) => { + setChatId((e.target as HTMLInputElement).value); + }; + + const updateMemberId = (e: React.SyntheticEvent) => { + setMemberAddress((e.target as HTMLInputElement).value); + }; + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const addAdminsToGroupTest = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + const response = await PushAPI.chat.addAdmins({ + chatId: chatId, + admins: memberAddress ? memberAddress.split(',') : [], + env, + account: account, + signer: librarySigner, + }); + setSendResponse(response); + + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + return ( +
+ +

Add Admins to Group Test page

+ + + +
+ + Add Admins to Group + + + + + + + + + + + + + + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default AddAdminsToGroupTest; diff --git a/packages/demoreact/src/app/ChatTest/AddMembersToGroupTest.tsx b/packages/demoreact/src/app/ChatTest/AddMembersToGroupTest.tsx new file mode 100644 index 000000000..2ee6452e1 --- /dev/null +++ b/packages/demoreact/src/app/ChatTest/AddMembersToGroupTest.tsx @@ -0,0 +1,108 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import ChatTest from './ChatTest'; + +const AddMembersToGroupTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [chatId, setChatId] = useState(''); + const [memberAddress, setMemberAddress] = useState(''); + const [sendResponse, setSendResponse] = useState(''); + const [account, setAccount] = useState(acc); + + const updateChatId = (e: React.SyntheticEvent) => { + setChatId((e.target as HTMLInputElement).value); + }; + + const updateMemberId = (e: React.SyntheticEvent) => { + setMemberAddress((e.target as HTMLInputElement).value); + }; + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const addMembersToGroupTest = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + const response = await PushAPI.chat.addMembers({ + chatId: chatId, + members: memberAddress ? memberAddress.split(',') : [], + env, + account: account, + signer: librarySigner, + }); + setSendResponse(response); + + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + + + return ( +
+ +

Add Member to Group Test page

+ + + +
+ + Add Member to Group + + + + + + + + + + + + + + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default AddMembersToGroupTest; diff --git a/packages/demoreact/src/app/ChatTest/ChatTest.tsx b/packages/demoreact/src/app/ChatTest/ChatTest.tsx index feddae531..110f73ed5 100644 --- a/packages/demoreact/src/app/ChatTest/ChatTest.tsx +++ b/packages/demoreact/src/app/ChatTest/ChatTest.tsx @@ -68,6 +68,18 @@ const ChatTest = () => { CHAT.GETGROUP + + CHAT.ADDMEMBERSTOGROUP + + + CHAT.ADDADMINSTOGROUP + + + CHAT.REMOVEMEMBERSFROMGROUP + + + CHAT.REMOVEADMINSFROMGROUP + diff --git a/packages/demoreact/src/app/ChatTest/RemoveAdminsFromGroupTest.tsx b/packages/demoreact/src/app/ChatTest/RemoveAdminsFromGroupTest.tsx new file mode 100644 index 000000000..b875c7c46 --- /dev/null +++ b/packages/demoreact/src/app/ChatTest/RemoveAdminsFromGroupTest.tsx @@ -0,0 +1,106 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import ChatTest from './ChatTest'; + +const RemoveAdminsFromGroupTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [chatId, setChatId] = useState(''); + const [memberAddress, setMemberAddress] = useState(''); + const [sendResponse, setSendResponse] = useState(''); + const [account, setAccount] = useState(acc); + + const updateChatId = (e: React.SyntheticEvent) => { + setChatId((e.target as HTMLInputElement).value); + }; + + const updateMemberId = (e: React.SyntheticEvent) => { + setMemberAddress((e.target as HTMLInputElement).value); + }; + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const removeAdminsFromGroupTest = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + const response = await PushAPI.chat.removeAdmins({ + chatId: chatId, + admins: memberAddress ? memberAddress.split(',') : [], + env, + account: account, + signer: librarySigner, + }); + setSendResponse(response); + + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + return ( +
+ +

Remove Admins from Group Test page

+ + + +
+ + Remove Admins from Group + + + + + + + + + + + + + + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default RemoveAdminsFromGroupTest; diff --git a/packages/demoreact/src/app/ChatTest/RemoveMembersFromGroupTest.tsx b/packages/demoreact/src/app/ChatTest/RemoveMembersFromGroupTest.tsx new file mode 100644 index 000000000..b2b3974d0 --- /dev/null +++ b/packages/demoreact/src/app/ChatTest/RemoveMembersFromGroupTest.tsx @@ -0,0 +1,92 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import ChatTest from './ChatTest'; + +const RemoveMembersFromGroupTest = () => { + const { account,library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [chatId, setChatId] = useState(''); + const [memberAddress, setMemberAddress] = useState(''); + const [sendResponse, setSendResponse] = useState(''); + + const updateChatId = (e: React.SyntheticEvent) => { + setChatId((e.target as HTMLInputElement).value); + }; + +const updateMemberId = (e: React.SyntheticEvent) => { + setMemberAddress((e.target as HTMLInputElement).value); + }; + + const removeMembersFromGroupTest = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + const response = await PushAPI.chat.removeMembers({ + chatId: chatId, + members: memberAddress ? memberAddress.split(',') : [], + env, + account: account, + signer: librarySigner, + }); + setSendResponse(response); + + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + return ( +
+ +

Remove Member from Group Test page

+ + + +
+ + Remove Member from Group + + + + + + + + + + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default RemoveMembersFromGroupTest; diff --git a/packages/demoreact/src/app/ChatTest/helper.ts b/packages/demoreact/src/app/ChatTest/helper.ts new file mode 100644 index 000000000..9200ac5ab --- /dev/null +++ b/packages/demoreact/src/app/ChatTest/helper.ts @@ -0,0 +1,19 @@ +import { + ChatStatus +} from "@pushprotocol/restapi"; + +export const stringToChatStatus = (status: string | undefined): ChatStatus => { + if (!status) { + throw new Error(`Invalid ChatStatus string: ${status}`); + } + switch (status.toUpperCase()) { + case 'ACTIVE': + return ChatStatus.ACTIVE; + case 'ENDED': + return ChatStatus.ENDED; + case 'PENDING': + return ChatStatus.PENDING; + default: + throw new Error(`Invalid ChatStatus string: ${status}`); + } +}; \ No newline at end of file diff --git a/packages/demoreact/src/app/ChatWidgetTest.tsx b/packages/demoreact/src/app/ChatWidgetTest.tsx index 31f4369e9..00d26860b 100644 --- a/packages/demoreact/src/app/ChatWidgetTest.tsx +++ b/packages/demoreact/src/app/ChatWidgetTest.tsx @@ -32,6 +32,9 @@ export const ChatWidgetTest = () => { })(); },[account,env]) + const onClose = () => { + console.log('in here widget') + }; return ( { + const { account: acc, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [spaceId, setSpaceId] = useState(''); + const [listenerAddress, setListenerAddress] = useState(''); + const [sendResponse, setSendResponse] = useState(''); + const [account, setAccount] = useState(acc); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateListenerId = (e: React.SyntheticEvent) => { + setListenerAddress((e.target as HTMLInputElement).value); + }; + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + const addListenersToSpaceTest = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + const response = await PushAPI.space.addListeners({ + spaceId: spaceId, + listeners: listenerAddress ? listenerAddress.split(',') : [], + env, + account: account, + signer: librarySigner, + }); + setSendResponse(response); + + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + return ( +
+ +

Add Listeners to Space Test page

+ + + +
+ + Add Listeners to Space + + + + + + + + + + + + + + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default AddListenersToSpaceTest; diff --git a/packages/demoreact/src/app/SpaceTest/AddSpeakersToSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/AddSpeakersToSpaceTest.tsx new file mode 100644 index 000000000..2b95f9c6b --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/AddSpeakersToSpaceTest.tsx @@ -0,0 +1,105 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import SpaceTest from './SpaceTest'; + +const AddSpeakersToSpaceTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [spaceId, setSpaceId] = useState(''); + const [speakerAddress, setSpeakerAddress] = useState(''); + const [sendResponse, setSendResponse] = useState(''); + const [account, setAccount] = useState(acc); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateSpeakerId = (e: React.SyntheticEvent) => { + setSpeakerAddress((e.target as HTMLInputElement).value); + }; + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const testAddSpeakersToSpaceTest = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + const response = await PushAPI.space.addSpeakers({ + spaceId: spaceId, + speakers: speakerAddress ? speakerAddress.split(',') : [], + env, + signer: librarySigner, + }); + setSendResponse(response); + + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + return ( +
+ +

Add Speakers to Space Test page

+ + + +
+ + Add Speakers to Space + + + + + + + + + + + + + + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default AddSpeakersToSpaceTest; diff --git a/packages/demoreact/src/app/SpaceTest/ApproveSpaceRequestTest.tsx b/packages/demoreact/src/app/SpaceTest/ApproveSpaceRequestTest.tsx new file mode 100644 index 000000000..d154d0b35 --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/ApproveSpaceRequestTest.tsx @@ -0,0 +1,101 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import { walletToPCAIP10 } from '../helpers'; +import SpaceTest from './SpaceTest'; + +const ApproveRequestTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env, isCAIP } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [senderAddress, setSenderAddress] = useState(''); + const [approveResponse, setApproveResponse] = useState(''); + const [account, setAccount] = useState(acc); + + const updateSenderAddress = (e: React.SyntheticEvent) => { + setSenderAddress((e.target as HTMLInputElement).value); + }; + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const testApproveRequest = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + + const response = await PushAPI.space.approve({ + status: 'Approved', + account: isCAIP ? walletToPCAIP10(account) : account, + signer: librarySigner, + senderAddress, + env, + }); + + setApproveResponse(response); + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + return ( +
+ +

Send Message Test page

+ + + +
+ +
+ + + + + + + + + + + approve request + + +
+
+ + +
+ {approveResponse ? ( + + {JSON.stringify(approveResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default ApproveRequestTest; diff --git a/packages/demoreact/src/app/SpaceTest/CreateSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/CreateSpaceTest.tsx new file mode 100644 index 000000000..1ce5d4925 --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/CreateSpaceTest.tsx @@ -0,0 +1,299 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import { walletToPCAIP10 } from '../helpers'; +import SpaceTest from '../SpaceTest/SpaceTest'; + +const CreateSpaceTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env, isCAIP } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [spaceName, setSpaceName] = useState(''); + const [spaceDescription, setSpaceDescription] = useState(''); + const [members, setMembers] = useState(''); + const [spaceImage, setSpaceImage] = useState(''); + const [admins, setAdmins] = useState(''); + const [isPublic, setIsPublic] = useState(''); + const [contractAddressNFT, setContractAddressNFT] = useState(); + const [numberOfNFTs, setNumberOfNFTs] = useState(); + const [contractAddressERC20, setContractAddressERC20] = useState(); + const [numberOfERC20, setNumberOfERC20] = useState(); + const [meta, setMeta] = useState(); + const [scheduleAt, setScheduleAt] = useState(''); + const [scheduleEnd, setScheduleEnd] = useState(); + const [account, setAccount] = useState(acc); + + + const [sendResponse, setSendResponse] = useState(''); + + const updateSpaceName = (e: React.SyntheticEvent) => { + setSpaceName((e.target as HTMLInputElement).value); + }; + + const updateSpaceDescription = (e: React.SyntheticEvent) => { + setSpaceDescription((e.target as HTMLInputElement).value); + }; + + const updateMembers = (e: React.SyntheticEvent) => { + setMembers((e.target as HTMLInputElement).value); + }; + + const updateSpaceImage = (e: React.SyntheticEvent) => { + setSpaceImage((e.target as HTMLInputElement).value); + }; + + const updateAdmins = (e: React.SyntheticEvent) => { + setAdmins((e.target as HTMLInputElement).value); + }; + + const updateIsPublic = (e: React.SyntheticEvent) => { + setIsPublic((e.target as HTMLInputElement).value); + }; + + const updateContractAddressNFT = (e: React.SyntheticEvent) => { + setContractAddressNFT((e.target as HTMLInputElement).value); + }; + + const updateNumberOfNFTs = (e: React.SyntheticEvent) => { + setNumberOfNFTs((e.target as HTMLInputElement).value); + }; + + const updateContractAddressERC20 = (e: React.SyntheticEvent) => { + setContractAddressERC20((e.target as HTMLInputElement).value); + }; + + const updateNumberOfERC20 = (e: React.SyntheticEvent) => { + setNumberOfERC20((e.target as HTMLInputElement).value); + }; + + const updateMeta = (e: React.SyntheticEvent) => { + setMeta((e.target as HTMLInputElement).value); + }; + + const updateScheduleAt = (e: React.SyntheticEvent) => { + setScheduleAt((e.target as HTMLInputElement).value); + }; + + const updateScheduleEnd = (e: React.SyntheticEvent) => { + setScheduleEnd((e.target as HTMLInputElement).value); + }; + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const testCreateSpace = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + + const response = await PushAPI.space.create({ + spaceName, + spaceDescription, + listeners: members.split(','), + spaceImage, + speakers: admins.split(','), + isPublic: (isPublic === "true"), + contractAddressNFT, + numberOfNFTs: numberOfNFTs != null ? Number(numberOfNFTs) : undefined, + contractAddressERC20, + numberOfERC20: numberOfERC20 != null ? Number(numberOfERC20) : undefined, + signer: librarySigner, + env, + meta: meta, + scheduleAt: new Date(scheduleAt) , + scheduleEnd: scheduleEnd ? new Date(scheduleEnd) : null + }); + + setSendResponse(response); + } catch (e:any) { + console.error(e.message); + } finally { + setLoading(false); + } + }; + + return ( +
+ +

Create Space Test page

+ + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create space + + +
+
+ + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default CreateSpaceTest; diff --git a/packages/demoreact/src/app/SpaceTest/GetSpaceInfoTest.tsx b/packages/demoreact/src/app/SpaceTest/GetSpaceInfoTest.tsx new file mode 100644 index 000000000..4306a2b14 --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/GetSpaceInfoTest.tsx @@ -0,0 +1,78 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import SpaceTest from './SpaceTest'; + +const GetSpaceInfoTest = () => { + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [spaceId, setSpaceId] = useState(''); + const [sendResponse, setSendResponse] = useState(''); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const testGetSpace = async () => { + try { + setLoading(true); + + // object for connected user data + const response = await PushAPI.space.info({ + spaceId: spaceId, + env, + }); + setSendResponse(response); + + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + + + return ( +
+ +

Get Space Info Test page

+ + + +
+ + get space data + + + + + + + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default GetSpaceInfoTest; diff --git a/packages/demoreact/src/app/SpaceTest/GetSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/GetSpaceTest.tsx new file mode 100644 index 000000000..cb331c130 --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/GetSpaceTest.tsx @@ -0,0 +1,78 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import SpaceTest from './SpaceTest'; + +const GetSpaceTest = () => { + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [spaceId, setSpaceId] = useState(''); + const [sendResponse, setSendResponse] = useState(''); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const testGetSpace = async () => { + try { + setLoading(true); + + // object for connected user data + const response = await PushAPI.space.get({ + spaceId: spaceId, + env, + }); + setSendResponse(response); + + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + + + return ( +
+ +

Get Space Test page

+ + + +
+ + get space data + + + + + + + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default GetSpaceTest; diff --git a/packages/demoreact/src/app/SpaceTest/GetSpacesRequestsTest.tsx b/packages/demoreact/src/app/SpaceTest/GetSpacesRequestsTest.tsx new file mode 100644 index 000000000..f046e9fab --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/GetSpacesRequestsTest.tsx @@ -0,0 +1,132 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import SpaceTest from './SpaceTest'; + +const GetSpacesRequestsTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [getSpacesReqeustsResponse, setSpacesReqeustsResponse] = useState(''); + const [toDecrypt, setToDecrypt] = useState(false); + const [account, setAccount] = useState(acc); + const [page, setPage] = useState(1); + const [limit, setLimit] = useState(10); + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const updatePage = (e: React.SyntheticEvent) => { + setPage(parseInt((e.target as HTMLInputElement).value)); + }; + + const updateLimit = (e: React.SyntheticEvent) => { + setLimit(parseInt((e.target as HTMLInputElement).value)); + }; + + const updateToDecrypt = (e: React.SyntheticEvent) => { + setToDecrypt((e.target as HTMLInputElement).checked); + }; + const testGetSpaceRequests = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + const user = await PushAPI.user.get({ account: account, env }); + let pvtkey = null; + if (user?.encryptedPrivateKey) { + pvtkey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + account, + signer: librarySigner, + env, + }); + } + const response = await PushAPI.space.requests({ + account: account, + pgpPrivateKey: pvtkey, + toDecrypt, + env, + page, + limit, + }); + + setSpacesReqeustsResponse(response); + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + return ( +
+ +

Get Spaces Requests Test page

+ + + +
+
+ + + + + + + + + + + + + + + + + + get spaces + +
+ +
+ {getSpacesReqeustsResponse ? ( + + {JSON.stringify(getSpacesReqeustsResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default GetSpacesRequestsTest; diff --git a/packages/demoreact/src/app/SpaceTest/GetSpacesTest.tsx b/packages/demoreact/src/app/SpaceTest/GetSpacesTest.tsx new file mode 100644 index 000000000..4214bfa89 --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/GetSpacesTest.tsx @@ -0,0 +1,132 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import SpaceTest from './SpaceTest'; + +const GetSpacesTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [getSpacesResponse, setGetSpacesResponse] = useState(''); + const [toDecrypt, setToDecrypt] = useState(false); + const [account, setAccount] = useState(acc); + const [page, setPage] = useState(1); + const [limit, setLimit] = useState(10); + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const updatePage = (e: React.SyntheticEvent) => { + setPage(parseInt((e.target as HTMLInputElement).value)); + }; + + const updateLimit = (e: React.SyntheticEvent) => { + setLimit(parseInt((e.target as HTMLInputElement).value)); + }; + + const updateToDecrypt = (e: React.SyntheticEvent) => { + setToDecrypt((e.target as HTMLInputElement).checked); + }; + const testGetSpaces = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + const user = await PushAPI.user.get({ account: account, env }); + let pvtkey = null; + if (user?.encryptedPrivateKey) { + pvtkey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + account, + signer: librarySigner, + env, + }); + } + const response = await PushAPI.space.spaces({ + account: account, + pgpPrivateKey: pvtkey, + toDecrypt, + env, + page, + limit, + }); + + setGetSpacesResponse(response); + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + return ( +
+ +

Get Spaces Test page

+ + + +
+
+ + + + + + + + + + + + + + + + + + get spaces + +
+ +
+ {getSpacesResponse ? ( + + {JSON.stringify(getSpacesResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default GetSpacesTest; diff --git a/packages/demoreact/src/app/SpaceTest/GetSpacesTrendingTest.tsx b/packages/demoreact/src/app/SpaceTest/GetSpacesTrendingTest.tsx new file mode 100644 index 000000000..95bccb3e5 --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/GetSpacesTrendingTest.tsx @@ -0,0 +1,105 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import SpaceTest from './SpaceTest'; + +const GetSpacesTrendingTest = () => { + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [getSpacesTrendingResponse, setGetSpacesTrendingResponse] = useState(''); + const [toDecrypt, setToDecrypt] = useState(false); + const [page, setPage] = useState(1); + const [limit, setLimit] = useState(10); + + + const updatePage = (e: React.SyntheticEvent) => { + setPage(parseInt((e.target as HTMLInputElement).value)); + }; + + const updateLimit = (e: React.SyntheticEvent) => { + setLimit(parseInt((e.target as HTMLInputElement).value)); + }; + + const updateToDecrypt = (e: React.SyntheticEvent) => { + setToDecrypt((e.target as HTMLInputElement).checked); + }; + const testGetSpacesTrending = async () => { + try { + setLoading(true); + + const response = await PushAPI.space.trending({ + env, + page, + limit, + }); + + setGetSpacesTrendingResponse(response); + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + return ( +
+ +

Get Spaces Trending Test page

+ + + +
+
+ + + + + + + + + + + + + + get spaces + +
+ +
+ {getSpacesTrendingResponse ? ( + + {JSON.stringify(getSpacesTrendingResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default GetSpacesTrendingTest; diff --git a/packages/demoreact/src/app/SpaceTest/RemoveListenersFromSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/RemoveListenersFromSpaceTest.tsx new file mode 100644 index 000000000..fe0b3b4c1 --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/RemoveListenersFromSpaceTest.tsx @@ -0,0 +1,108 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import SpaceTest from './SpaceTest'; + +const RemoveListenersFromSpaceTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [spaceId, setSpaceId] = useState(''); + const [listenerAddress, setListenerAddress] = useState(''); + const [sendResponse, setSendResponse] = useState(''); + const [account, setAccount] = useState(acc); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const updateListenerId = (e: React.SyntheticEvent) => { + setListenerAddress((e.target as HTMLInputElement).value); + }; + + const removeListenersFromSpaceTest = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + const response = await PushAPI.space.removeListeners({ + spaceId: spaceId, + listeners: listenerAddress ? listenerAddress.split(',') : [], + env, + account: account, + signer: librarySigner, + }); + setSendResponse(response); + + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + + + return ( +
+ +

Remove Listener from Space Test page

+ + + +
+ + Remove Listeners from Space + + + + + + + + + + + + + + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default RemoveListenersFromSpaceTest; diff --git a/packages/demoreact/src/app/SpaceTest/RemoveSpeakersFromSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/RemoveSpeakersFromSpaceTest.tsx new file mode 100644 index 000000000..411a0f398 --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/RemoveSpeakersFromSpaceTest.tsx @@ -0,0 +1,104 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import SpaceTest from './SpaceTest'; + +const RemoveSpeakersFromSpaceTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [spaceId, setSpaceId] = useState(''); + const [speakerAddress, setSpeakerAddress] = useState(''); + const [sendResponse, setSendResponse] = useState(''); + const [account, setAccount] = useState(acc); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateSpeakerId = (e: React.SyntheticEvent) => { + setSpeakerAddress((e.target as HTMLInputElement).value); + }; + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const removeSpeakersFromSpaceTest = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + const response = await PushAPI.space.removeSpeakers({ + spaceId: spaceId, + speakers: speakerAddress ? speakerAddress.split(',') : [], + env, + signer: librarySigner, + }); + setSendResponse(response); + + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + return ( +
+ +

Remove Speakers from Group Test page

+ + + +
+ + Remove Speakers from Space + + + + + + + + + + + + + + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default RemoveSpeakersFromSpaceTest; diff --git a/packages/demoreact/src/app/SpaceTest/SpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/SpaceTest.tsx new file mode 100644 index 000000000..6c35791ab --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/SpaceTest.tsx @@ -0,0 +1,79 @@ +import { useState, useContext } from 'react'; +import styled from 'styled-components'; +import { Link } from 'react-router-dom'; +import { + Section, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; + +const SpaceTest = () => { + const [isLoading, setLoading] = useState(false); + + const NavMenu = styled.div` + display: flex; + flex-wrap: wrap; + gap: 30px; + justify-content: center; + + @media only screen and (max-width: 900px) { + flex-direction: column; + } + `; + + return ( +
+

Space Test page

+ + + +
+ + + SPACE.CREATE + + + SPACE.UPDATE + + + SPACE.GET + + + SPACE.INFO + + + SPACE.APPROVE + + + SPACE.START + + + SPACE.STOP + + + SPACE.ADDLISTENERSTOSPACE + + + SPACE.ADDSPEAKERSTOSPACE + + + SPACE.REMOVELISTENERSFROMSPACE + + + SPACE.REMOVESPEAKERSFROMSPACE + + + SPACE.GETSPACES + + + SPACE.GETSPACESREQUESTS + + + SPACE.GETSPACESTRENDING + + +
+
+ ); +}; + +export default SpaceTest; diff --git a/packages/demoreact/src/app/SpaceTest/StartSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/StartSpaceTest.tsx new file mode 100644 index 000000000..90364c22d --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/StartSpaceTest.tsx @@ -0,0 +1,91 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import SpaceTest from './SpaceTest'; + +const StartSpaceTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [spaceId, setSpaceId] = useState(''); + const [sendResponse, setSendResponse] = useState(''); + const [account, setAccount] = useState(acc); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const startSpaceTest = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + + // const response = await PushAPI.space.start({ + // spaceId: spaceId, + // signer: librarySigner, + // env: env, + // }); + // setSendResponse(response); + + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + return ( +
+ +

Start Space Test page

+ + + +
+ + Start space data + + + + + + + + + + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default StartSpaceTest; diff --git a/packages/demoreact/src/app/SpaceTest/StopSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/StopSpaceTest.tsx new file mode 100644 index 000000000..a2182ee3d --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/StopSpaceTest.tsx @@ -0,0 +1,93 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import SpaceTest from './SpaceTest'; + +const StopSpaceTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [spaceId, setSpaceId] = useState(''); + const [sendResponse, setSendResponse] = useState(''); + const [account, setAccount] = useState(acc); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const stopSpaceTest = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + + // const response = await PushAPI.space.stop({ + // spaceId: spaceId, + // signer: librarySigner, + // env: env, + // }); + // setSendResponse(response); + + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + + + return ( +
+ +

Stop Space Test page

+ + + +
+ + Stop space data + + + + + + + + + + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default StopSpaceTest; diff --git a/packages/demoreact/src/app/SpaceTest/UpdateSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/UpdateSpaceTest.tsx new file mode 100644 index 000000000..319db5833 --- /dev/null +++ b/packages/demoreact/src/app/SpaceTest/UpdateSpaceTest.tsx @@ -0,0 +1,231 @@ +import { useState, useContext } from 'react'; +import { + Section, + SectionItem, + CodeFormatter, + SectionButton, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; +import { Web3Context, EnvContext } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; +import { walletToPCAIP10 } from '../helpers'; +import SpaceTest from './SpaceTest'; +import { stringToChatStatus } from './../ChatTest/helper'; + +const UpdateSpaceTest = () => { + const { account: acc, library } = useContext(Web3Context); + const { env, isCAIP } = useContext(EnvContext); + const [isLoading, setLoading] = useState(false); + const [spaceId, setSpaceId] = useState(''); + const [spaceName, setSpaceName] = useState(''); + const [spaceImage, setSpaceImage] = useState(''); + const [spaceDescription, setSpaceDescription] = useState(''); + const [members, setMembers] = useState(''); + const [admins, setAdmins] = useState(''); + const [scheduleAt, setScheduleAt] = useState(''); + const [scheduleEnd, setScheduleEnd] = useState(); + const [status, setStatus] = useState(); + const [account, setAccount] = useState(acc); + + const [sendResponse, setSendResponse] = useState(''); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateSpaceName = (e: React.SyntheticEvent) => { + setSpaceName((e.target as HTMLInputElement).value); + }; + const updateSpaceDescription = (e: React.SyntheticEvent) => { + setSpaceDescription((e.target as HTMLInputElement).value); + }; + + const updateSpaceImage= (e: React.SyntheticEvent) => { + setSpaceImage((e.target as HTMLInputElement).value); + }; + + const updateMembers= (e: React.SyntheticEvent) => { + setMembers((e.target as HTMLInputElement).value); + }; + + + const updateAdmins= (e: React.SyntheticEvent) => { + setAdmins((e.target as HTMLInputElement).value); + }; + + const updateScheduleAt = (e: React.SyntheticEvent) => { + setScheduleAt((e.target as HTMLInputElement).value); + }; + + const updateScheduleEnd = (e: React.SyntheticEvent) => { + setScheduleEnd((e.target as HTMLInputElement).value); + }; + + const updateStatus = (e: React.SyntheticEvent) => { + setStatus((e.target as HTMLInputElement).value); + }; + + const updateAccount = (e: React.SyntheticEvent) => { + setAccount((e.target as HTMLInputElement).value); + }; + + const updateSpaceTest = async () => { + try { + setLoading(true); + const librarySigner = await library.getSigner(); + + const response = await PushAPI.space.update({ + spaceId, + spaceName, + spaceImage, + spaceDescription, + listeners: members.split(','), + speakers: admins.split(','), + signer: librarySigner, + env, + scheduleAt: new Date(scheduleAt) , + scheduleEnd: scheduleEnd ? new Date(scheduleEnd) : null, + status: stringToChatStatus(status) + }); + + setSendResponse(response); + } catch (e:any) { + console.error(e.message); + } finally { + setLoading(false); + } + }; + + return ( +
+ +

Update Space Test page

+ + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + update space + + +
+
+ + +
+ {sendResponse ? ( + + {JSON.stringify(sendResponse, null, 4)} + + ) : null} +
+
+
+
+ ); +}; + +export default UpdateSpaceTest; diff --git a/packages/demoreact/src/app/SpaceUITest/CreateSpaceComponent.tsx b/packages/demoreact/src/app/SpaceUITest/CreateSpaceComponent.tsx new file mode 100644 index 000000000..d06ba6635 --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/CreateSpaceComponent.tsx @@ -0,0 +1,7 @@ +import { useSpaceComponents } from "./useSpaceComponents" + +export const CreateSpaceComponent = () => { + const { CreateSpaceComponent } = useSpaceComponents(); + + return +} diff --git a/packages/demoreact/src/app/SpaceUITest/SpaceBanner.tsx b/packages/demoreact/src/app/SpaceUITest/SpaceBanner.tsx new file mode 100644 index 000000000..44c50caee --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/SpaceBanner.tsx @@ -0,0 +1,63 @@ +import React, { useState } from 'react'; + +import { useSpaceComponents } from './useSpaceComponents'; +import { Section, SectionItem } from '../components/StyledComponents'; +import Dropdown from '../components/Dropdown'; + +export const SpaceBanner = () => { + const { SpaceBannerComponent } = useSpaceComponents(); + + const [spaceId, setSpaceId] = useState(''); + const [orientation, setOrientation] = useState('maximized'); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateOrientation = (e: any) => { + setOrientation(e.target.value); + }; + + const onClickHandler = (arg: string) => { + console.log(arg); + } + + return ( +
+
+ + + + + +
+ +
+ ); +}; diff --git a/packages/demoreact/src/app/SpaceUITest/SpaceFeed.tsx b/packages/demoreact/src/app/SpaceUITest/SpaceFeed.tsx new file mode 100644 index 000000000..5b204b591 --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/SpaceFeed.tsx @@ -0,0 +1,85 @@ +import React, { useState } from 'react'; +import { useSpaceComponents } from './useSpaceComponents'; +import { Checkbox } from '../components/Checkbox'; + +export const SpaceFeed = () => { + const { SpaceFeedComponent } = useSpaceComponents(); + const [address, setAddress] = useState(); + const [showTab, setShowTab] = useState(true); + const [horizontal, setHorizontal] = useState(false); + const [width, setWidth] = useState(); + const [height, setHeight] = useState(500); + const [sortingOrder, setSortingOrder] = useState([]); + + const handleShowTab = () => { + setShowTab(!showTab); + }; + + const handleHorizontal = () => { + setHorizontal(!horizontal); + }; + + const handleAddressChange = (e: React.SyntheticEvent) => { + setAddress((e.target as HTMLInputElement).value); + }; + + const handleWidthChange = (e: React.SyntheticEvent) => { + setWidth((e.target as HTMLInputElement).value as unknown as number); + }; + + const handleHeightChange = (e: React.SyntheticEvent) => { + setHeight((e.target as HTMLInputElement).value as unknown as number); + }; + + return ( + <> + + + +
+ +
+ +
+ +
+ +
+ + { + console.log('spaceId: ', spaceId); + }} + /> + + ); +}; diff --git a/packages/demoreact/src/app/SpaceUITest/SpaceInvites.tsx b/packages/demoreact/src/app/SpaceUITest/SpaceInvites.tsx new file mode 100644 index 000000000..8b1493262 --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/SpaceInvites.tsx @@ -0,0 +1,9 @@ +import { useSpaceComponents } from "./useSpaceComponents" + +export const SpaceInvitesComponent = () => { + const { SpaceInvitesComponent } = useSpaceComponents(); + + return ( + + ) +} diff --git a/packages/demoreact/src/app/SpaceUITest/SpaceUITest.tsx b/packages/demoreact/src/app/SpaceUITest/SpaceUITest.tsx new file mode 100644 index 000000000..ce3f9c8bf --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/SpaceUITest.tsx @@ -0,0 +1,52 @@ +import { useState } from 'react'; +import styled from 'styled-components'; +import { Link } from 'react-router-dom'; +import { + Section, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; + +const SpaceUITest = () => { + const [isLoading, setIsLoading] = useState(false); + + const NavMenu = styled.div` + display: flex; + flex-wrap: wrap; + gap: 30px; + justify-content: center; + + @media only screen and (max-width: 900px) { + flex-direction: column; + } + `; + + return ( +
+

Space UI Test page

+ + + +
+ + + SPACES WIDGET + + + SPACES FEED + + + SPACES BANNER + + + CREATE SPACE + + + SPACES INVITES + + +
+
+ ); +}; + +export default SpaceUITest; diff --git a/packages/demoreact/src/app/SpaceUITest/SpaceWidget.tsx b/packages/demoreact/src/app/SpaceUITest/SpaceWidget.tsx new file mode 100644 index 000000000..1bb487857 --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/SpaceWidget.tsx @@ -0,0 +1,155 @@ +import { useState } from "react"; +import { Section, SectionItem } from "../components/StyledComponents"; +import SpaceUITest from "./SpaceUITest"; +import { useSpaceComponents } from "./useSpaceComponents" + +export const SpaceWidget = () => { + const { SpaceWidgetComponent } = useSpaceComponents(); + const [spaceId, setSpaceId] = useState(''); + const [width, setWidth] = useState(''); + const [zIndex, setZIndex] = useState('1000'); + const [shareUrl, setShareUrl] = useState(''); + const [isHost, setisHost] = useState(false); + const [isLive, setisLive] = useState(false); + const [isMember, setisMember] = useState(false); + const [isJoined, setisJoined] = useState(false); + const [isTimeToStartSpace, setisTimeToStartSpace] = useState(false); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateWidgetWidth = (e: React.SyntheticEvent) => { + setWidth((e.target as HTMLInputElement).value); + }; + + const updateZIndex = (e: React.SyntheticEvent) => { + setZIndex((e.target as HTMLInputElement).value); + }; + + const updateShareUrl = (e: React.SyntheticEvent) => { + setShareUrl((e.target as HTMLInputElement).value); + }; + + const updateIsHost = (e: React.SyntheticEvent) => { + setisHost((e.target as HTMLInputElement).checked); + }; + + const updateIsLive = (e: React.SyntheticEvent) => { + setisLive((e.target as HTMLInputElement).checked); + }; + + const updateIsMember = (e: React.SyntheticEvent) => { + setisMember((e.target as HTMLInputElement).checked); + }; + + const updateIsJoined = (e: React.SyntheticEvent) => { + setisJoined((e.target as HTMLInputElement).checked); + }; + + const updateIsTimeToStartSpace = (e: React.SyntheticEvent) => { + setisTimeToStartSpace((e.target as HTMLInputElement).checked); + }; + + return ( +
+ +

Space Widget Test page

+
+ + + + + + + + + + + + + + + + +
Temp Props
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ ); +} diff --git a/packages/demoreact/src/app/SpaceUITest/index.tsx b/packages/demoreact/src/app/SpaceUITest/index.tsx new file mode 100644 index 000000000..5e3c4137f --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/index.tsx @@ -0,0 +1,29 @@ +import { SpacesUIProvider } from '@pushprotocol/uiweb'; +import { useSpaceComponents } from './useSpaceComponents'; + +export * from './SpaceUITest'; +export * from './SpaceWidget'; +export * from './SpaceFeed'; +export * from "./SpaceBanner"; +export * from "./CreateSpaceComponent"; +export * from "./SpaceInvites"; + +export interface ISpacesComponentProps { + children: React.ReactNode; +} + +export const SpacesComponentProvider = ({ + children, +}: ISpacesComponentProps) => { + const { spaceUI } = useSpaceComponents(); + + const customtheme = { + statusColorError: 'red', + } + + return ( + + {children} + + ); +}; diff --git a/packages/demoreact/src/app/SpaceUITest/useSpaceComponents.tsx b/packages/demoreact/src/app/SpaceUITest/useSpaceComponents.tsx new file mode 100644 index 000000000..5c0ee9ffc --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/useSpaceComponents.tsx @@ -0,0 +1,64 @@ +import { + ISpaceFeedProps, + ISpaceBannerProps, + ISpaceWidgetProps, + ISpaceCreateWidgetProps, + SpacesUI, + ISpaceInvitesProps, +} from '@pushprotocol/uiweb'; +import React, { useContext, useEffect, useState } from 'react'; +import { EnvContext, Web3Context } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; + +export interface IUseSpaceReturnValues { + spaceUI: SpacesUI; + SpaceInvitesComponent: React.FC; + SpaceWidgetComponent: React.FC; + SpaceFeedComponent: React.FC; + SpaceBannerComponent: React.FC; + CreateSpaceComponent: React.FC; +} + +export const useSpaceComponents = (): IUseSpaceReturnValues => { + const { account, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const librarySigner = library?.getSigner(); + + const [pgpPrivateKey, setPgpPrivateKey] = useState(''); + + const spaceUI = new SpacesUI({ + account: account, + signer: librarySigner, + pgpPrivateKey: pgpPrivateKey, + env: env, + }); + + useEffect(() => { + (async () => { + if (!account || !env || !library) return; + + const user = await PushAPI.user.get({ account, env }); + let pgpPrivateKey; + const librarySigner = await library.getSigner(account); + if (user?.encryptedPrivateKey) { + pgpPrivateKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + account, + signer: librarySigner, + env, + }); + } + + setPgpPrivateKey(pgpPrivateKey); + })(); + }, [account, env, library]); + + return { + spaceUI, + SpaceInvitesComponent: spaceUI.SpaceInvites, + SpaceWidgetComponent: spaceUI.SpaceWidget, + SpaceBannerComponent: spaceUI.SpaceBanner, + SpaceFeedComponent: spaceUI.SpaceFeed, + CreateSpaceComponent: spaceUI.SpaceCreationButtonWidget, + }; +}; diff --git a/packages/demoreact/src/app/app.tsx b/packages/demoreact/src/app/app.tsx index 2615f2bdc..e5a51911f 100644 --- a/packages/demoreact/src/app/app.tsx +++ b/packages/demoreact/src/app/app.tsx @@ -27,6 +27,13 @@ import HistoryTest from './ChatTest/History'; import GetRequestsTest from './ChatTest/GetRequests'; import DelegationTest from './DelegationTest'; import CreateGroupTest from './ChatTest/CreateGroupTest'; +import AddMembersToGroupTest from './ChatTest/AddMembersToGroupTest'; +import AddAdminsToGroupTest from './ChatTest/AddAdminsToGroupTest'; +import CreateSpaceTest from './SpaceTest/CreateSpaceTest'; +import UpdateSpaceTest from './SpaceTest/UpdateSpaceTest'; +import GetSpaceTest from './SpaceTest/GetSpaceTest'; +import GetSpaceInfoTest from './SpaceTest/GetSpaceInfoTest'; +import ApproveSpaceRequestTest from './SpaceTest/ApproveSpaceRequestTest'; import UpdateGroupTest from './ChatTest/UpdateGroupTest'; import GetGroupTest from './ChatTest/GetGroupTest'; import GetUsersBatchTest from './ChatTest/GetUsersBatchTest'; @@ -34,6 +41,28 @@ import AuthUpdateUserTest from './ChatTest/AuthUpdateUser'; import UpdateUserProfile from './ChatTest/UpdateUserProfile'; import { Buffer } from 'buffer'; import { ENV } from './helpers'; +import SpaceTest from './SpaceTest/SpaceTest'; +import StartSpaceTest from './SpaceTest/StartSpaceTest'; +import StopSpaceTest from './SpaceTest/StopSpaceTest'; +import RemoveMembersFromGroupTest from './ChatTest/RemoveMembersFromGroupTest'; +import RemoveAdminsFromGroupTest from './ChatTest/RemoveAdminsFromGroupTest'; +import AddSpeakersToSpaceTest from './SpaceTest/AddSpeakersToSpaceTest'; +import AddListenersToSpaceTest from './SpaceTest/AddListenersToSpaceTest'; +import RemoveListenersFromSpaceTest from './SpaceTest/RemoveListenersFromSpaceTest'; +import RemoveSpeakersFromSpaceTest from './SpaceTest/RemoveSpeakersFromSpaceTest'; +import GetSpacesTest from './SpaceTest/GetSpacesTest'; +import GetSpacesRequestsTest from './SpaceTest/GetSpacesRequestsTest'; +import GetSpacesTrendingTest from './SpaceTest/GetSpacesTrendingTest'; +import SpaceUITest from './SpaceUITest/SpaceUITest'; +import { + SpacesComponentProvider, + SpaceWidget, + SpaceBanner, + SpaceFeed, + CreateSpaceComponent, + SpaceInvitesComponent +} from './SpaceUITest'; +import { useSpaceComponents } from './SpaceUITest/useSpaceComponents'; import { ChatWidgetTest } from './ChatWidgetTest'; window.Buffer = window.Buffer || Buffer; @@ -56,7 +85,7 @@ const StyledApp = styled.div` justify-content: center; text-decoration: none; - &: hover { + &:hover { text-decoration: underline; } } @@ -109,6 +138,7 @@ const StyledApp = styled.div` const NavMenu = styled.div` display: flex; + flex-flow: wrap; gap: 30px; justify-content: center; @@ -132,6 +162,9 @@ export function App() { const [env, setEnv] = useState(ENV.PROD); const [isCAIP, setIsCAIP] = useState(false); + const { SpaceWidgetComponent } = useSpaceComponents(); + const [spaceId, setSpaceId] = useState(''); + const socketData = useSDKSocket({ account: web3Data.account, chainId: web3Data.chainId, @@ -181,76 +214,160 @@ export function App() { {checkForWeb3Data(web3Data) ? ( - - - - NOTIFICATIONS - - - SECRET NOTIFICATION - - - CHANNELS - - - ALIAS - - - DELEGATIONS - - - PAYLOADS - - - SOCKET - - - EMBED - - - CHAT - - - } - /> - } /> - } /> - - } /> - - } /> - - } /> - - } /> - - } /> - - } /> - - } /> - - {/* chat method routes */} - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - {/* */} - + + + + + NOTIFICATIONS + + + SECRET NOTIFICATION + + + CHANNELS + + + ALIAS + + + DELEGATIONS + + + PAYLOADS + + + SOCKET + + + EMBED + + + CHAT + + + SPACE + + + SPACE UI + + + } + /> + } + /> + } /> + + } /> + + } /> + + } /> + + } /> + + } /> + + } /> + + } /> + } /> + + } /> + + {/* chat method routes */} + } /> + } + /> + } /> + } + /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } + /> + } + /> + } + /> + } + /> + } /> + + {/* spaces method routes */} + } /> + } /> + } /> + } /> + } + /> + } /> + } /> + } + /> + } + /> + } + /> + } + /> + } /> + } + /> + } + /> + + {/* spaces ui components routes */} + } /> + } /> + } /> + } /> + } + /> + + {/* */} + + + ) : null} diff --git a/packages/examples/sdk-backend-node/src/main.ts b/packages/examples/sdk-backend-node/src/main.ts index 18d9d37a6..a82eb72f4 100644 --- a/packages/examples/sdk-backend-node/src/main.ts +++ b/packages/examples/sdk-backend-node/src/main.ts @@ -1,6 +1,8 @@ import { runNotificaitonsUseCases } from './notification'; import { runChatUseCases, runNFTChatUseCases } from './chat'; import { runVideoUseCases } from './video'; +import { runSpacesUseCases } from './spaces'; + import { config } from './config'; import { ENV } from './types'; @@ -16,6 +18,7 @@ const start = async (): Promise => { await runChatUseCases(); await runNFTChatUseCases(); await runVideoUseCases(); + await runSpacesUseCases(); }; start(); diff --git a/packages/examples/sdk-backend-node/src/spaces/index.ts b/packages/examples/sdk-backend-node/src/spaces/index.ts new file mode 100644 index 000000000..f320f7659 --- /dev/null +++ b/packages/examples/sdk-backend-node/src/spaces/index.ts @@ -0,0 +1,624 @@ +import * as PushAPI from '@pushprotocol/restapi'; +import * as dotenv from 'dotenv'; +import { + ethers +} from 'ethers'; +import { + adjectives, + animals, + colors, + uniqueNamesGenerator, +} from 'unique-names-generator'; +dotenv.config(); + +enum ENV { + PROD = 'prod', + STAGING = 'staging', + DEV = 'dev', + /** + * **This is for local development only** + */ + LOCAL = 'local', +} + +// CONFIGS +const env = process.env.PUSH_NODE_NETWORK; // choose ENV.STAGING or ENV.PROD +const showAPIResponse = process.env.SHOW_API_RESPONSE === 'true' ? true : false; // choose to show or hide API responses + +// Addresses that will be used to +const signer = ethers.Wallet.createRandom(); +const signerSecondAccount = ethers.Wallet.createRandom(); + +// generate some dummy wallets as well +const randomWallet1 = ethers.Wallet.createRandom().address; +const randomWallet2 = ethers.Wallet.createRandom().address; +const randomWallet3 = ethers.Wallet.createRandom().address; + + +const spaceName = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], +}); + +const spaceDescription = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], +}); + +const spaceImage = + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg=='; + + +export const runSpacesUseCases = async (): Promise < void > => { + console.log(` + ███████╗██████╗ █████╗ ██████╗███████╗███████╗ + ██╔════╝██╔══██╗██╔══██╗██╔════╝██╔════╝██╔════╝ + ███████╗██████╔╝███████║██║ █████╗ ███████╗ + ╚════██║██╔═══╝ ██╔══██║██║ ██╔══╝ ╚════██║ + ███████║██║ ██║ ██║╚██████╗███████╗███████║ + ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝╚══════╝ + + `) + + console.log('PushAPI.user.create'); + await PushAPI_user_create(); + + console.log('PushAPI.space.create'); + const spaceId = await PushAPI_space_create(); + + console.log('PushAPI.space.update'); + await PushAPI_space_update(spaceId); + + console.log('PushAPI.space.get'); + await PushAPI_space_get(spaceId); + + console.log('PushAPI.space.start'); + console.log('PushAPI.space.stop'); + await PushAPI_space_start_and_stop(); + + console.log('PushAPI.space.approve'); + await PushAPI_space_approve(); + + console.log('PushAPI.space.addListeners'); + await PushAPI_space_add_listeners(spaceId); + + console.log('PushAPI.space.removeListeners'); + await PushAPI_space_remove_listeners(spaceId); + + console.log('PushAPI.space.addSpeakers'); + await PushAPI_space_add_speakers(spaceId); + + console.log('PushAPI.space.removeSpeakers'); + await PushAPI_space_remove_speakers(spaceId); + + console.log('PushAPI.space.spaces'); + await PushAPI_space_spaces(); + + console.log('PushAPI.space.requests'); + await PushAPI_space_requests(); + + console.log('PushAPI.space.trending'); + await PushAPI_space_trending(); +} + +// Push Chat - PushAPI.user.create +async function PushAPI_user_create(silent = !showAPIResponse) { + const user = await PushAPI.user.create({ + signer: signer, + env: env as ENV, + }); + + const user_2 = await PushAPI.user.create({ + signer: signerSecondAccount, + env: env as ENV, + }); + + console.log('PushAPI_user_create | Response - 200 OK'); + if (!silent) { + console.log(user); + console.log(user_2); + } + + return user; +} + +// Push Space - PushAPI.space.create +async function PushAPI_space_create( + silent = !showAPIResponse +): Promise < string > { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signer.address}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + signer: signer, + }); + + const now = new Date(); + const start = new Date(now.getTime() + 10 * 60000) + const end = new Date(now.getTime() + 60 * 60000); + + const response = await PushAPI.space.create({ + spaceName, + spaceDescription, + members: [`eip155:${randomWallet1}`, `eip155:${randomWallet2}`], + spaceImage, + admins: [], + isPublic: true, + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + scheduleAt: start, + scheduleEnd: end + }); + console.log('PushAPI_chat_createSpace | Response - 200 OK'); + if (!silent) { + console.log(response); + } + return response.spaceId; +} + +// Push Space - PushAPI.space.update +async function PushAPI_space_update( + spaceId: string, + silent = !showAPIResponse +) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signer.address}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + const now = new Date(); + const start = new Date(now.getTime() + 10 * 60000) + const end = new Date(now.getTime() + 60 * 60000); + + + // Actual API + // Convert image to base 64 and pass + // This is an idempotent operation, meaning it requires all space info to be passed no matter if only few things change + // Why so? To ensure that verificationProof always is able to replicate the current space info (trustless since signature is stored with the info) + const response = await PushAPI.space.update({ + spaceId, + spaceName, + spaceDescription, + members: [ + `eip155:${randomWallet1}`, + `eip155:${randomWallet2}`, + `eip155:${randomWallet3}`, + `eip155:${signer.address}`, + ], + spaceImage, + admins: [`eip155:${signer.address}`], // takes signer as admin automatically, add more if you want to + scheduleAt: start, + scheduleEnd: end, + status: PushAPI.ChatStatus.PENDING, + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_space_update | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Space - PushAPI.space.get +async function PushAPI_space_get( + spaceId: string, + silent = !showAPIResponse +) { + const response = await PushAPI.space.get({ + spaceId: spaceId, + env: env as ENV, + }); + + console.log('PushAPI_space_get | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Space - PushAPI.space.start +// Push Space - PushAPI.space.stop +async function PushAPI_space_start_and_stop( + silent = !showAPIResponse +): Promise < string > { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signer.address}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + signer: signer, + }); + + const now = new Date(); + const start = new Date(now.getTime() + 10 * 60000) + const end = new Date(now.getTime() + 60 * 60000); + + const response = await PushAPI.space.create({ + spaceName: uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }), + spaceDescription, + members: [`eip155:${randomWallet1}`, `eip155:${randomWallet2}`], + spaceImage, + admins: [], + isPublic: true, + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + scheduleAt: start, // Sets scheduleAt to the current time + 10 min + scheduleEnd: end, // Sets scheduleEnd to 60 minutes from now + }); + console.log('PushAPI_chat_createSpace | Response - 200 OK'); + if (!silent) { + console.log(response); + } + + const spaceId = response.spaceId + + // This is causing bug - Aman to check + /*const response2 = await PushAPI.space.start({ + spaceId: spaceId, + env: env as ENV, + signer: signer, + }); + + console.log('PushAPI_space_start | Response - 200 OK'); + if (!silent) { + console.log(response2); + }*/ + + // This is causing bug - Aman to check + /*response = await PushAPI.space.stop({ + spaceId: spaceId, + env: env as ENV, + signer: signer, + });*/ + + console.log('PushAPI_space_stop | Response - 200 OK'); + if (!silent) { + console.log(response); + } + return spaceId; +} + +// Push Space - PushAPI.space.approve +async function PushAPI_space_approve( + silent = !showAPIResponse +): Promise < string > { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signer.address}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + signer: signer, + }); + + const now = new Date(); + const start = new Date(now.getTime() + 10 * 60000) + const end = new Date(now.getTime() + 60 * 60000); + + const response = await PushAPI.space.create({ + spaceName: uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }), + spaceDescription, + members: [`eip155:${randomWallet1}`, `eip155:${randomWallet2}`], + spaceImage, + admins: [], + isPublic: true, + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + scheduleAt: start, // Sets scheduleAt to the current time + 10 min + scheduleEnd: end, // Sets scheduleEnd to 60 minutes from now + }); + console.log('PushAPI_chat_createSpace | Response - 200 OK'); + if (!silent) { + console.log(response); + } + + const spaceId = response.spaceId + + const secondUser = await PushAPI.user.get({ + account: `eip155:${signerSecondAccount.address}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKeyUser2 = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: secondUser.encryptedPrivateKey, + signer: signerSecondAccount, + }); + + // Actual api + const approveResponse = await PushAPI.chat.approve({ + status: 'Approved', + senderAddress: spaceId, // receiver's address or spaceId of a group + signer: signerSecondAccount, + pgpPrivateKey: pgpDecrpyptedPvtKeyUser2, + env: env as ENV, + }); + + console.log('PushAPI_space_approve | Response - 200 OK'); + if (!silent) { + console.log(approveResponse); + } + return spaceId; +} + +// Push Space - PushAPI.space.addListeners +async function PushAPI_space_add_listeners( + spaceId: string, + silent = !showAPIResponse +) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signer.address}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + const response = await PushAPI.space.addListeners({ + spaceId, + listeners: [ + `eip155:${ethers.Wallet.createRandom().address}`, + `eip155:${ethers.Wallet.createRandom().address}`, + `eip155:${ethers.Wallet.createRandom().address}`, + ], + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_space_addListeners | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Space - PushAPI.space.removeListeners +async function PushAPI_space_remove_listeners( + spaceId: string, + silent = !showAPIResponse +) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signer.address}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + signer: signer, + }); + + const a1 = ethers.Wallet.createRandom().address; + const a2 = ethers.Wallet.createRandom().address; + const a3 = ethers.Wallet.createRandom().address; + + const response = await PushAPI.space.addListeners({ + spaceId, + listeners: [ + `eip155:${a1}`, + `eip155:${a2}`, + `eip155:${a3}`, + ], + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_space_addListeners | Response - 200 OK'); + if (!silent) { + console.log(response); + } + + const response2 = await PushAPI.space.removeListeners({ + spaceId, + listeners: [ + `eip155:${a1}`, + `eip155:${a2}`, + `eip155:${a3}`, + ], + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_space_removeListeners | Response - 200 OK'); + if (!silent) { + console.log(response2); + } +} + +// Push Space - PushAPI.space.addSpeakers +async function PushAPI_space_add_speakers( + spaceId: string, + silent = !showAPIResponse +) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signer.address}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + const response = await PushAPI.space.addSpeakers({ + spaceId, + speakers: [ + `eip155:${ethers.Wallet.createRandom().address}`, + `eip155:${ethers.Wallet.createRandom().address}`, + `eip155:${ethers.Wallet.createRandom().address}`, + ], + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_space_addSpeakers | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Space - PushAPI.space.removeSpeakers +async function PushAPI_space_remove_speakers( + spaceId: string, + silent = !showAPIResponse +) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signer.address}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + const a1 = ethers.Wallet.createRandom().address; + const a2 = ethers.Wallet.createRandom().address; + const a3 = ethers.Wallet.createRandom().address; + + const response = await PushAPI.space.addSpeakers({ + spaceId, + speakers: [ + `eip155:${a1}`, + `eip155:${a2}`, + `eip155:${a3}`, + ], + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_space_addSpeakers | Response - 200 OK'); + if (!silent) { + console.log(response); + } + + const response2 = await PushAPI.space.removeSpeakers({ + spaceId, + speakers: [ + `eip155:${a1}`, + `eip155:${a2}`, + `eip155:${a3}`, + ], + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_space_removeSpeakers | Response - 200 OK'); + if (!silent) { + console.log(response2); + } +} + +// Push Space - PushAPI.space.spaces +async function PushAPI_space_spaces(silent = !showAPIResponse) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signer.address}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + // Actual api + const response = await PushAPI.space.spaces({ + account: `eip155:${signer.address}`, + toDecrypt: true, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_space_spaces | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Chat - PushAPI.spaces.requests +async function PushAPI_space_requests(silent = !showAPIResponse) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signer.address}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + signer: signer, + }); + + // Actual api + const response = await PushAPI.space.requests({ + account: `eip155:${signer.address}`, + toDecrypt: true, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_space_requests | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Chat - PushAPI.spaces.trending +async function PushAPI_space_trending(silent = !showAPIResponse) { + + // Actual api + const response = await PushAPI.space.trending({ + env: env as ENV, + }); + + console.log('PushAPI_space_trending | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} \ No newline at end of file diff --git a/packages/examples/sdk-frontend/video/README.md b/packages/examples/sdk-frontend/README.md similarity index 100% rename from packages/examples/sdk-frontend/video/README.md rename to packages/examples/sdk-frontend/README.md diff --git a/packages/examples/sdk-frontend/components/Spaces/Checkbox.tsx b/packages/examples/sdk-frontend/components/Spaces/Checkbox.tsx new file mode 100644 index 000000000..58e759c59 --- /dev/null +++ b/packages/examples/sdk-frontend/components/Spaces/Checkbox.tsx @@ -0,0 +1,15 @@ +import React from 'react'; + +export const Checkbox = (props: { id: string, label: string, value?: boolean, onChange: () => void }) => { + return ( +
+ + +
+ ); + }; \ No newline at end of file diff --git a/packages/examples/sdk-frontend/components/Spaces/Dropdown.tsx b/packages/examples/sdk-frontend/components/Spaces/Dropdown.tsx new file mode 100644 index 000000000..b97e8e9ee --- /dev/null +++ b/packages/examples/sdk-frontend/components/Spaces/Dropdown.tsx @@ -0,0 +1,35 @@ +import React from 'react'; + +type DropdownOptionsType = { + value: string, + label: string +}; + +const Dropdown = ({ + style, + label, + value, + width, + options, + onChange +}: { + style?: any, + label: string, + value?: string, + width?: string | number, + options: DropdownOptionsType[], + onChange: (arg0: any) => void +}) => { + return ( + + ); +}; + +export default Dropdown; \ No newline at end of file diff --git a/packages/examples/sdk-frontend/components/Spaces/StyledComponents.tsx b/packages/examples/sdk-frontend/components/Spaces/StyledComponents.tsx new file mode 100644 index 000000000..cb13603e4 --- /dev/null +++ b/packages/examples/sdk-frontend/components/Spaces/StyledComponents.tsx @@ -0,0 +1,61 @@ +import styled from 'styled-components'; + +export const Section = styled.section` + border: 2px solid #ccc; + padding: 25px; + margin: 10px 0; + display: flex; + flex-direction: column; + background-color: ${(props) => props.theme === 'dark' ? '#000' : '#fff'}; + + & .headerText { + color: ${(props) => props.theme === 'dark' ? '#fff' : '#000'}; + font-size: 2rem; + } + + & .subHeaderText { + color: ${(props) => props.theme === 'dark' ? '#fff' : '#000'}; + font-size: 1.2rem; + } +` + +export const SectionItem = styled.div` + display: flex; + gap: 15px; + align-items: center; + + & label.consoleLabel { + color: green; + } +`; + +export const SectionItemCustom = styled(SectionItem)` + justify-content: flex-end; + align-items: center; + margin: 20px 0px; +`; + +export const CodeFormatter = styled.pre` + background: #eeebeb; + padding: 15px; + border-radius: 7px; +`; + +export const SectionButton = styled.button` + font-family: "Source Sans Pro",Arial,sans-serif; + font-size: 16px; + display: flex; + margin-right: 15px; + padding: 15px 20px; + background: #674C9F; + border: 0; + border-radius: 7px; + box-shadow: rgb(0 0 0 / 52%) 0px 0px 5px; + color: #fff; + justify-content: center; + + &:hover { + cursor: pointer; + background: rgb(226, 8, 128); + } +`; diff --git a/packages/examples/sdk-frontend/components/Spaces/index.ts b/packages/examples/sdk-frontend/components/Spaces/index.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/examples/sdk-frontend/components/Spaces/useSpaceComponent.tsx b/packages/examples/sdk-frontend/components/Spaces/useSpaceComponent.tsx new file mode 100644 index 000000000..ccad60268 --- /dev/null +++ b/packages/examples/sdk-frontend/components/Spaces/useSpaceComponent.tsx @@ -0,0 +1,72 @@ +import { + ISpaceFeedProps, + ISpaceBannerProps, + ISpaceWidgetProps, + ISpaceCreateWidgetProps, + SpacesUI, + ISpaceInvitesProps, +} from '@pushprotocol/uiweb'; +import { useAccount, useNetwork, useSigner } from 'wagmi'; +import React, { useContext, useEffect, useState } from 'react'; +import { ENV } from '@pushprotocol/restapi/src/lib/constants'; +import * as PushAPI from '@pushprotocol/restapi'; +import { is } from 'date-fns/locale'; + +export interface IUseSpaceReturnValues { + spaceUI: SpacesUI; + SpaceInvitesComponent: React.FC; + SpaceWidgetComponent: React.FC; + SpaceFeedComponent: React.FC; + SpaceBannerComponent: React.FC; + CreateSpaceComponent: React.FC; +} + +export const useSpaceComponents = (): IUseSpaceReturnValues => { + const env = ENV.DEV; + + const { address, isConnected } = useAccount(); + const { chain } = useNetwork(); + const { data: signer } = useSigner(); + + const [pgpPrivateKey, setPgpPrivateKey] = useState(''); + + console.log('address: ', address, isConnected); + + const spaceUI = new SpacesUI({ + account: address as string, + signer: signer as PushAPI.SignerType, + pgpPrivateKey: pgpPrivateKey, + env: env, + }); + + useEffect(() => { + (async () => { + if (!signer || !address || !chain?.id) return; + + const user = await PushAPI.user.get({ + account: address, + env, + }); + let pgpPrivateKey = null; + if (user?.encryptedPrivateKey) { + pgpPrivateKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + account: address, + signer, + env, + }); + } + + setPgpPrivateKey(pgpPrivateKey); + })(); + }, [address, env, signer, chain]); + + return { + spaceUI, + SpaceInvitesComponent: spaceUI.SpaceInvites, + SpaceWidgetComponent: spaceUI.SpaceWidget, + SpaceBannerComponent: spaceUI.SpaceBanner, + SpaceFeedComponent: spaceUI.SpaceFeed, + CreateSpaceComponent: spaceUI.SpaceCreationButtonWidget, + }; +}; diff --git a/packages/examples/sdk-frontend/video/components/VideoPlayer.tsx b/packages/examples/sdk-frontend/components/VideoPlayer.tsx similarity index 100% rename from packages/examples/sdk-frontend/video/components/VideoPlayer.tsx rename to packages/examples/sdk-frontend/components/VideoPlayer.tsx diff --git a/packages/examples/sdk-frontend/video/helpers/getCAIPAddress.ts b/packages/examples/sdk-frontend/helpers/getCAIPAddress.ts similarity index 100% rename from packages/examples/sdk-frontend/video/helpers/getCAIPAddress.ts rename to packages/examples/sdk-frontend/helpers/getCAIPAddress.ts diff --git a/packages/examples/sdk-frontend/video/hooks/usePushSocket.ts b/packages/examples/sdk-frontend/hooks/usePushSocket.ts similarity index 100% rename from packages/examples/sdk-frontend/video/hooks/usePushSocket.ts rename to packages/examples/sdk-frontend/hooks/usePushSocket.ts diff --git a/packages/examples/sdk-frontend/video/next-env.d.ts b/packages/examples/sdk-frontend/next-env.d.ts similarity index 100% rename from packages/examples/sdk-frontend/video/next-env.d.ts rename to packages/examples/sdk-frontend/next-env.d.ts diff --git a/packages/examples/sdk-frontend/video/next.config.js b/packages/examples/sdk-frontend/next.config.js similarity index 100% rename from packages/examples/sdk-frontend/video/next.config.js rename to packages/examples/sdk-frontend/next.config.js diff --git a/packages/examples/sdk-frontend/video/package.json b/packages/examples/sdk-frontend/package.json similarity index 85% rename from packages/examples/sdk-frontend/video/package.json rename to packages/examples/sdk-frontend/package.json index e4f26153e..c5791072e 100644 --- a/packages/examples/sdk-frontend/video/package.json +++ b/packages/examples/sdk-frontend/package.json @@ -9,7 +9,8 @@ "lint": "next lint" }, "dependencies": { - "@pushprotocol/restapi": "^1.3.3", + "@pushprotocol/restapi": "../../../dist/packages/restapi", + "@pushprotocol/uiweb": "../../../dist/packages/uiweb", "@pushprotocol/socket": "^0.5.1", "@rainbow-me/rainbowkit": "0.12.14", "ethers": "^5", diff --git a/packages/examples/sdk-frontend/video/pages/_app.tsx b/packages/examples/sdk-frontend/pages/_app.tsx similarity index 56% rename from packages/examples/sdk-frontend/video/pages/_app.tsx rename to packages/examples/sdk-frontend/pages/_app.tsx index 5237f95e3..6013004e0 100644 --- a/packages/examples/sdk-frontend/video/pages/_app.tsx +++ b/packages/examples/sdk-frontend/pages/_app.tsx @@ -1,23 +1,24 @@ -import type { AppProps } from "next/app"; +import type { AppProps } from 'next/app'; import { getDefaultWallets, RainbowKitProvider, darkTheme, -} from "@rainbow-me/rainbowkit"; -import { configureChains, createClient, WagmiConfig } from "wagmi"; -import { goerli } from "wagmi/chains"; -import { publicProvider } from "wagmi/providers/public"; +} from '@rainbow-me/rainbowkit'; +import { configureChains, createClient, WagmiConfig } from 'wagmi'; +import { goerli } from 'wagmi/chains'; +import { publicProvider } from 'wagmi/providers/public'; -import "@rainbow-me/rainbowkit/styles.css"; -import "../styles/globals.css"; -import { useEffect, useState } from "react"; +import '@rainbow-me/rainbowkit/styles.css'; +import '../styles/globals.css'; +import { useEffect, useState } from 'react'; +import { SpacesComponentProvider } from './spaces'; const { chains, provider } = configureChains([goerli], [publicProvider()]); const { connectors } = getDefaultWallets({ - appName: "Connect", - projectId: "connect", + appName: 'Connect', + projectId: 'connect', chains, }); @@ -40,7 +41,9 @@ function MyApp({ Component, pageProps }: AppProps) { {loadWagmi ? ( - + + + ) : null} diff --git a/packages/examples/sdk-frontend/pages/index.tsx b/packages/examples/sdk-frontend/pages/index.tsx new file mode 100644 index 000000000..aff02dff0 --- /dev/null +++ b/packages/examples/sdk-frontend/pages/index.tsx @@ -0,0 +1,43 @@ +import { ConnectButton } from '@rainbow-me/rainbowkit'; +import { NextPage } from 'next'; +import Link from 'next/link'; +import styled from 'styled-components'; + +const Index: NextPage = () => { + return ( + +

Hello Next.js 👋

+ + + +
+ ); +}; + +export default Index; + +export const Container = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 20px; +}`; + +export const Button = styled.button` + background: #000; + color: #fff; + border: none; + border-radius: 10px; + padding: 10px 20px; + font-size: 1.2rem; + cursor: pointer; + transition: 0.3s; + &:hover { + opacity: 0.7; + } +}`; diff --git a/packages/examples/sdk-frontend/pages/spaces/banner.tsx b/packages/examples/sdk-frontend/pages/spaces/banner.tsx new file mode 100644 index 000000000..bc0a6a01c --- /dev/null +++ b/packages/examples/sdk-frontend/pages/spaces/banner.tsx @@ -0,0 +1,71 @@ +import React, { useState } from 'react'; + +import { useSpaceComponents } from './../../components/Spaces/useSpaceComponent'; +import { + Section, + SectionItem, +} from './../../components/Spaces/StyledComponents'; +import Dropdown from './../../components/Spaces/Dropdown'; +import { NextPage } from 'next'; +import Spaces from '.'; + +const SpaceBanner: NextPage = () => { + const { SpaceBannerComponent } = useSpaceComponents(); + + const [spaceId, setSpaceId] = useState(''); + const [orientation, setOrientation] = useState('maximized'); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateOrientation = (e: any) => { + setOrientation(e.target.value); + }; + + const onClickHandler = (arg: string) => { + console.log(arg); + }; + + return ( +
+ +
+ + + + + +
+ +
+ ); +}; + +export default SpaceBanner; diff --git a/packages/examples/sdk-frontend/pages/spaces/create.tsx b/packages/examples/sdk-frontend/pages/spaces/create.tsx new file mode 100644 index 000000000..c45a327ba --- /dev/null +++ b/packages/examples/sdk-frontend/pages/spaces/create.tsx @@ -0,0 +1,16 @@ +import { NextPage } from 'next'; +import { useSpaceComponents } from './../../components/Spaces/useSpaceComponent'; +import Spaces from '.'; + +const CreateSpaceComponent: NextPage = () => { + const { CreateSpaceComponent } = useSpaceComponents(); + + return ( + <> + + + + ); +}; + +export default CreateSpaceComponent; diff --git a/packages/examples/sdk-frontend/pages/spaces/feed.tsx b/packages/examples/sdk-frontend/pages/spaces/feed.tsx new file mode 100644 index 000000000..b15b4faa5 --- /dev/null +++ b/packages/examples/sdk-frontend/pages/spaces/feed.tsx @@ -0,0 +1,90 @@ +import React, { useState } from 'react'; +import { useSpaceComponents } from './../../components/Spaces/useSpaceComponent'; +import { Checkbox } from './../../components/Spaces/Checkbox'; +import { NextPage } from 'next'; +import Spaces from '.'; + +const SpaceFeed: NextPage = () => { + const { SpaceFeedComponent } = useSpaceComponents(); + const [address, setAddress] = useState(); + const [showTab, setShowTab] = useState(true); + const [horizontal, setHorizontal] = useState(false); + const [width, setWidth] = useState(); + const [height, setHeight] = useState(500); + const [sortingOrder, setSortingOrder] = useState([]); + + const handleShowTab = () => { + setShowTab(!showTab); + }; + + const handleHorizontal = () => { + setHorizontal(!horizontal); + }; + + const handleAddressChange = (e: React.SyntheticEvent) => { + setAddress((e.target as HTMLInputElement).value); + }; + + const handleWidthChange = (e: React.SyntheticEvent) => { + setWidth((e.target as HTMLInputElement).value as unknown as number); + }; + + const handleHeightChange = (e: React.SyntheticEvent) => { + setHeight((e.target as HTMLInputElement).value as unknown as number); + }; + + return ( + <> + + + + +
+ +
+ +
+ +
+ +
+ + { + console.log('spaceId: ', spaceId); + }} + /> + + ); +}; + +export default SpaceFeed; diff --git a/packages/examples/sdk-frontend/pages/spaces/index.tsx b/packages/examples/sdk-frontend/pages/spaces/index.tsx new file mode 100644 index 000000000..651988b8d --- /dev/null +++ b/packages/examples/sdk-frontend/pages/spaces/index.tsx @@ -0,0 +1,68 @@ +import { NextPage } from 'next'; +import styled from 'styled-components'; +import { Button, Container } from '..'; +import Link from 'next/link'; + +import { SpacesUIProvider } from '@pushprotocol/uiweb'; +import { useSpaceComponents } from './../../components/Spaces/useSpaceComponent'; + + +export interface ISpacesComponentProps { + children: React.ReactNode; +} + +export const SpacesComponentProvider = ({ + children, +}: ISpacesComponentProps) => { + const { spaceUI } = useSpaceComponents(); + + const customtheme = { + statusColorError: 'red', + }; + + return ( + + {children} + + ); +}; + +const Spaces: NextPage = () => { + const { SpaceWidgetComponent } = useSpaceComponents(); + return ( + + +

Spaces UI Test

+
+ + + + + +
+ +
+
+ ); +}; + +export default Spaces; + +const Section = styled.div` + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 20px; + wrap: wrap; +}`; diff --git a/packages/examples/sdk-frontend/pages/spaces/invites.tsx b/packages/examples/sdk-frontend/pages/spaces/invites.tsx new file mode 100644 index 000000000..0cf3aeca0 --- /dev/null +++ b/packages/examples/sdk-frontend/pages/spaces/invites.tsx @@ -0,0 +1,16 @@ +import { NextPage } from 'next'; +import { useSpaceComponents } from './../../components/Spaces/useSpaceComponent'; +import Spaces from '.'; + +const SpaceInvitesComponent: NextPage = () => { + const { SpaceInvitesComponent } = useSpaceComponents(); + + return ( + <> + + + + ); +}; + +export default SpaceInvitesComponent; diff --git a/packages/examples/sdk-frontend/pages/spaces/widget.tsx b/packages/examples/sdk-frontend/pages/spaces/widget.tsx new file mode 100644 index 000000000..3283285ca --- /dev/null +++ b/packages/examples/sdk-frontend/pages/spaces/widget.tsx @@ -0,0 +1,163 @@ +import { useState } from 'react'; +import { + Section, + SectionItem, +} from './../../components/Spaces/StyledComponents'; +import { useSpaceComponents } from './../../components/Spaces/useSpaceComponent'; +import Spaces from '.'; +import { NextPage } from 'next'; + +const SpaceWidget: NextPage = () => { + const { SpaceWidgetComponent } = useSpaceComponents(); + const [spaceId, setSpaceId] = useState(''); + const [width, setWidth] = useState(''); + const [zIndex, setZIndex] = useState('1000'); + const [shareUrl, setShareUrl] = useState(''); + const [isHost, setisHost] = useState(false); + const [isLive, setisLive] = useState(false); + const [isMember, setisMember] = useState(false); + const [isJoined, setisJoined] = useState(false); + const [isTimeToStartSpace, setisTimeToStartSpace] = useState(false); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateWidgetWidth = (e: React.SyntheticEvent) => { + setWidth((e.target as HTMLInputElement).value); + }; + + const updateZIndex = (e: React.SyntheticEvent) => { + setZIndex((e.target as HTMLInputElement).value); + }; + + const updateShareUrl = (e: React.SyntheticEvent) => { + setShareUrl((e.target as HTMLInputElement).value); + }; + + const updateIsHost = (e: React.SyntheticEvent) => { + setisHost((e.target as HTMLInputElement).checked); + }; + + const updateIsLive = (e: React.SyntheticEvent) => { + setisLive((e.target as HTMLInputElement).checked); + }; + + const updateIsMember = (e: React.SyntheticEvent) => { + setisMember((e.target as HTMLInputElement).checked); + }; + + const updateIsJoined = (e: React.SyntheticEvent) => { + setisJoined((e.target as HTMLInputElement).checked); + }; + + const updateIsTimeToStartSpace = (e: React.SyntheticEvent) => { + setisTimeToStartSpace((e.target as HTMLInputElement).checked); + }; + + return ( +
+ +

Space Widget Test page

+
+ + + + + + + + + + + + + + + + +
+ Temp Props +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ ); +}; + +export default SpaceWidget; diff --git a/packages/examples/sdk-frontend/video/pages/index.tsx b/packages/examples/sdk-frontend/pages/video.tsx similarity index 100% rename from packages/examples/sdk-frontend/video/pages/index.tsx rename to packages/examples/sdk-frontend/pages/video.tsx diff --git a/packages/examples/sdk-frontend/video/styles/globals.css b/packages/examples/sdk-frontend/styles/globals.css similarity index 100% rename from packages/examples/sdk-frontend/video/styles/globals.css rename to packages/examples/sdk-frontend/styles/globals.css diff --git a/packages/examples/sdk-frontend/video/tsconfig.json b/packages/examples/sdk-frontend/tsconfig.json similarity index 100% rename from packages/examples/sdk-frontend/video/tsconfig.json rename to packages/examples/sdk-frontend/tsconfig.json diff --git a/packages/examples/sdk-frontend/video/pages/spaces/index.tsx b/packages/examples/sdk-frontend/video/pages/spaces/index.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/packages/package-lock.json b/packages/package-lock.json new file mode 100644 index 000000000..84593e7d4 --- /dev/null +++ b/packages/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "packages", + "lockfileVersion": 2, + "requires": true, + "packages": {} +} diff --git a/packages/restapi/CHANGELOG.md b/packages/restapi/CHANGELOG.md index 4d1b4a228..8906e57d3 100644 --- a/packages/restapi/CHANGELOG.md +++ b/packages/restapi/CHANGELOG.md @@ -2,69 +2,189 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). -## [1.3.9](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-1.3.8...restapi-1.3.9) (2023-06-26) +## [0.0.1-alpha.23](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.22...restapi-0.0.1-alpha.23) (2023-07-12) ### Bug Fixes -* add blockedUsersList functionality to SDK ([#444](https://github.com/ethereum-push-notification-service/push-sdk/issues/444)) ([d66e3ff](https://github.com/ethereum-push-notification-service/push-sdk/commit/d66e3ff9fcb7b775705315654a759800b367122d)) -* Merge branch 'main' into deployment ([a95a1aa](https://github.com/ethereum-push-notification-service/push-sdk/commit/a95a1aaef0b2ae579e40e17e898f7df58a00388f)) -* **video:** add error handlers and turn server config ([#466](https://github.com/ethereum-push-notification-service/push-sdk/issues/466)) ([cda9a28](https://github.com/ethereum-push-notification-service/push-sdk/commit/cda9a28bbb99bf8bd40bcd13f3c486cbf1ebe5a2)) +* Merge branch 'alpha' into alpha-deployment ([b120e30](https://github.com/ethereum-push-notification-service/push-sdk/commit/b120e302f6b9f8e360b43f80dcdd3248c1e4304b)) +* Merge branch 'alpha' into alpha-deployment ([54c5721](https://github.com/ethereum-push-notification-service/push-sdk/commit/54c57219c7f3f198a3f7578a0720895aff2d27f4)) +* Merge branch 'main' into alpha ([7b316ec](https://github.com/ethereum-push-notification-service/push-sdk/commit/7b316ec8e6f3178c02e7fce6d27884ba8ef1b4f4)) +* Merge branch 'main' into alpha ([d66202d](https://github.com/ethereum-push-notification-service/push-sdk/commit/d66202d0798b9ec731d7f5d30031b89ae29d72b4)) -## [1.3.8](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-1.3.7...restapi-1.3.8) (2023-06-12) +## [0.0.1-alpha.22](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.21...restapi-0.0.1-alpha.22) (2023-07-07) ### Bug Fixes -* added types for Env and name in Ifeeds ([#452](https://github.com/ethereum-push-notification-service/push-sdk/issues/452)) ([301808e](https://github.com/ethereum-push-notification-service/push-sdk/commit/301808e81fc66df10a0f64b65eb7d13375702e00)) +* add tc fix null meta ([#502](https://github.com/ethereum-push-notification-service/push-sdk/issues/502)) ([6e48314](https://github.com/ethereum-push-notification-service/push-sdk/commit/6e48314c0e58989849f66a4ffe387d906623ef69)) +* Merge branch 'alpha' into alpha-deployment ([5c84e2f](https://github.com/ethereum-push-notification-service/push-sdk/commit/5c84e2f07667fe4e9d94561544807b11c103ac49)) +* merged maain ([942cc65](https://github.com/ethereum-push-notification-service/push-sdk/commit/942cc65a60aa043054cebb143990711fb6e2efdb)) -## [1.3.7](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-1.3.6...restapi-1.3.7) (2023-06-12) +## [0.0.1-alpha.21](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.20...restapi-0.0.1-alpha.21) (2023-07-07) ### Bug Fixes -* destroy peer instance in disconnect ([#451](https://github.com/ethereum-push-notification-service/push-sdk/issues/451)) ([439fd96](https://github.com/ethereum-push-notification-service/push-sdk/commit/439fd9627168e31b8626c88368eebb3a4443a092)) -* Merge branch 'main' into deployment ([494916b](https://github.com/ethereum-push-notification-service/push-sdk/commit/494916b3b4140f44cb5ae1d7d674a31a420d1995)) +* added messageObj and Meta Messages support ([#485](https://github.com/ethereum-push-notification-service/push-sdk/issues/485)) ([2769aa6](https://github.com/ethereum-push-notification-service/push-sdk/commit/2769aa6bb0da6e7a4d28fca6b481db6cc2958d47)) +* Merge branch 'alpha' into alpha-deployment ([c05d024](https://github.com/ethereum-push-notification-service/push-sdk/commit/c05d024415bb1cb9e1fe59714d7db5516d161c06)) +* merged main ([46cf04e](https://github.com/ethereum-push-notification-service/push-sdk/commit/46cf04e75c314065c77a5a77d9351d9ccc7e0a58)) +* spaces naming ([6db7fc0](https://github.com/ethereum-push-notification-service/push-sdk/commit/6db7fc09b680060f022040feb2a22aeed9c652d0)) + + + +## [0.0.1-alpha.20](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.19...restapi-0.0.1-alpha.20) (2023-07-03) + + +### Bug Fixes + +* new commit ([25f2725](https://github.com/ethereum-push-notification-service/push-sdk/commit/25f2725efb0e1017ee2a0460259b27f252471014)) -## [1.3.6](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-1.3.5...restapi-1.3.6) (2023-06-09) +## [0.0.1-alpha.19](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.18...restapi-0.0.1-alpha.19) (2023-07-03) ### Bug Fixes -* Merge branch 'main' into deployment ([af582f7](https://github.com/ethereum-push-notification-service/push-sdk/commit/af582f7efba83b69f5d29a97f772a00de16a0c25)) +* added silent notifications ([#467](https://github.com/ethereum-push-notification-service/push-sdk/issues/467)) ([88bafe4](https://github.com/ethereum-push-notification-service/push-sdk/commit/88bafe49d489cfe399efa7166407a50574995b16)) +* Merge branch 'alpha' into alpha-deployment ([a15e368](https://github.com/ethereum-push-notification-service/push-sdk/commit/a15e368241215e2e2219792afd718567d621bf2a)) +* merge main ([6998d35](https://github.com/ethereum-push-notification-service/push-sdk/commit/6998d35aa181f17a5ad8d9501943a6a867814650)) +* rename based on new convention ([0e34479](https://github.com/ethereum-push-notification-service/push-sdk/commit/0e34479b1581abd59e0f853d6547e23a0afb5e28)) +* **video:** add error handlers and turn server config ([#466](https://github.com/ethereum-push-notification-service/push-sdk/issues/466)) ([cda9a28](https://github.com/ethereum-push-notification-service/push-sdk/commit/cda9a28bbb99bf8bd40bcd13f3c486cbf1ebe5a2)) + + + +## [0.0.1-alpha.19](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.18...restapi-0.0.1-alpha.19) (2023-07-03) + + +### Bug Fixes + +* added silent notifications ([#467](https://github.com/ethereum-push-notification-service/push-sdk/issues/467)) ([88bafe4](https://github.com/ethereum-push-notification-service/push-sdk/commit/88bafe49d489cfe399efa7166407a50574995b16)) +* Merge branch 'alpha' into alpha-deployment ([a15e368](https://github.com/ethereum-push-notification-service/push-sdk/commit/a15e368241215e2e2219792afd718567d621bf2a)) +* merge main ([6998d35](https://github.com/ethereum-push-notification-service/push-sdk/commit/6998d35aa181f17a5ad8d9501943a6a867814650)) +* rename based on new convention ([0e34479](https://github.com/ethereum-push-notification-service/push-sdk/commit/0e34479b1581abd59e0f853d6547e23a0afb5e28)) +* **video:** add error handlers and turn server config ([#466](https://github.com/ethereum-push-notification-service/push-sdk/issues/466)) ([cda9a28](https://github.com/ethereum-push-notification-service/push-sdk/commit/cda9a28bbb99bf8bd40bcd13f3c486cbf1ebe5a2)) + + + +## [0.0.1-alpha.18](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.17...restapi-0.0.1-alpha.18) (2023-06-20) + + +### Bug Fixes + +* add blockedUsersList functionality to SDK ([#444](https://github.com/ethereum-push-notification-service/push-sdk/issues/444)) ([d66e3ff](https://github.com/ethereum-push-notification-service/push-sdk/commit/d66e3ff9fcb7b775705315654a759800b367122d)) +* add name to SpaceIFeeds ([9c22271](https://github.com/ethereum-push-notification-service/push-sdk/commit/9c222715d0f15ae912b90661f9d18d42bddc4c89)) +* added types for Env and name in Ifeeds ([#452](https://github.com/ethereum-push-notification-service/push-sdk/issues/452)) ([301808e](https://github.com/ethereum-push-notification-service/push-sdk/commit/301808e81fc66df10a0f64b65eb7d13375702e00)) +* destroy peer instance in disconnect ([#451](https://github.com/ethereum-push-notification-service/push-sdk/issues/451)) ([439fd96](https://github.com/ethereum-push-notification-service/push-sdk/commit/439fd9627168e31b8626c88368eebb3a4443a092)) +* Merge branch 'alpha' into alpha-deployment ([b521522](https://github.com/ethereum-push-notification-service/push-sdk/commit/b521522c3b147b789a03b2683da4b6cefac795fe)) +* Merge branch 'main' into alpha ([64de06f](https://github.com/ethereum-push-notification-service/push-sdk/commit/64de06fc3cfd4359cf0d7fb70212e775ce9e51b9)) +* merge main ([27105a2](https://github.com/ethereum-push-notification-service/push-sdk/commit/27105a247fe4bd4db78a41be06ef6a2d52fb6b21)) +* update path ([10d62b1](https://github.com/ethereum-push-notification-service/push-sdk/commit/10d62b1a017b3d0a5044a4ab33bdce183f795f51)) * **video:** clear the peer instance in disconnect ([#445](https://github.com/ethereum-push-notification-service/push-sdk/issues/445)) ([db32d2c](https://github.com/ethereum-push-notification-service/push-sdk/commit/db32d2c901d8a208d409b6c09a716dee653b06f9)) -## [1.3.5](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-1.3.4...restapi-1.3.5) (2023-06-08) +## [0.0.1-alpha.17](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.16...restapi-0.0.1-alpha.17) (2023-06-08) ### Bug Fixes +* fix subset for take whole array ([#429](https://github.com/ethereum-push-notification-service/push-sdk/issues/429)) ([88b5a4d](https://github.com/ethereum-push-notification-service/push-sdk/commit/88b5a4d8df6363087895c9f8c635b91253237a44)) +* Merge branch 'alpha' into alpha-deployment ([a9d8ff1](https://github.com/ethereum-push-notification-service/push-sdk/commit/a9d8ff18bcad950e40b966e5b4020e29b493aa28)) +* merge main ([78c020a](https://github.com/ethereum-push-notification-service/push-sdk/commit/78c020ac61decc2d3b78d3749c8ec5df7478842f)) * **video:** fix error on repeated acceptRequest calls ([#439](https://github.com/ethereum-push-notification-service/push-sdk/issues/439)) ([4936d1f](https://github.com/ethereum-push-notification-service/push-sdk/commit/4936d1f9d747401d341a7dc502e9044c00290c8a)) +* **video:** fix error on repeated acceptRequest calls ([#442](https://github.com/ethereum-push-notification-service/push-sdk/issues/442)) ([f34bfa0](https://github.com/ethereum-push-notification-service/push-sdk/commit/f34bfa09cf88e812e07c0dcf7fabf792726c577f)) -## [1.3.4](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-1.3.3...restapi-1.3.4) (2023-06-05) +## [0.0.1-alpha.16](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.15...restapi-0.0.1-alpha.16) (2023-06-02) ### Bug Fixes -* fix subset for take whole array ([#429](https://github.com/ethereum-push-notification-service/push-sdk/issues/429)) ([88b5a4d](https://github.com/ethereum-push-notification-service/push-sdk/commit/88b5a4d8df6363087895c9f8c635b91253237a44)) +* add profile.update feature ([#410](https://github.com/ethereum-push-notification-service/push-sdk/issues/410)) ([361b930](https://github.com/ethereum-push-notification-service/push-sdk/commit/361b9303c5340238bcb7fa457370707ae864756b)) +* add spaces for functions ([#307](https://github.com/ethereum-push-notification-service/push-sdk/issues/307)) ([aea015a](https://github.com/ethereum-push-notification-service/push-sdk/commit/aea015ae478da77ebaa41a4e111ac213027b0b6a)) +* Merge branch 'alpha' into alpha-deployment ([ad6a56b](https://github.com/ethereum-push-notification-service/push-sdk/commit/ad6a56be24c326b7fb1f6eddb01b20b489eee27d)) +* merge main ([3959345](https://github.com/ethereum-push-notification-service/push-sdk/commit/39593456140e152e53f4bd7c10a19e0d8f05dfc9)) + + + +## [0.0.1-alpha.15](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.14...restapi-0.0.1-alpha.15) (2023-05-29) + + +### Bug Fixes + +* Iuser structure changed ([#365](https://github.com/ethereum-push-notification-service/push-sdk/issues/365)) ([2fc6f54](https://github.com/ethereum-push-notification-service/push-sdk/commit/2fc6f549c80a65a5a6009b0c2fa9635d757bdf11)), closes [#390](https://github.com/ethereum-push-notification-service/push-sdk/issues/390) [#295](https://github.com/ethereum-push-notification-service/push-sdk/issues/295) +* Merge branch 'alpha' into alpha-deployment ([a66c9a4](https://github.com/ethereum-push-notification-service/push-sdk/commit/a66c9a4a3628700a450b8e2fb7a5f942d1d84095)) +* merged main to alpha ([067bc5d](https://github.com/ethereum-push-notification-service/push-sdk/commit/067bc5d358c5f218628a980ce23ab3b39615805f)) +* removed undocumented fn ([#419](https://github.com/ethereum-push-notification-service/push-sdk/issues/419)) ([3fff974](https://github.com/ethereum-push-notification-service/push-sdk/commit/3fff974b1e2cfa3499439a246be190aaad2907e3)) +## [0.0.1-alpha.14](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.13...restapi-0.0.1-alpha.14) (2023-05-22) + + +### Bug Fixes + +* fix nft videocall ([#411](https://github.com/ethereum-push-notification-service/push-sdk/issues/411)) ([8cdb999](https://github.com/ethereum-push-notification-service/push-sdk/commit/8cdb999bc548caf67ec6fbe625253b5795a4e465)) +* Merge branch 'alpha' into alpha-deployment ([f247665](https://github.com/ethereum-push-notification-service/push-sdk/commit/f2476650b650ade59721c30f6e8483e86c013cd4)) + + + +## [0.0.1-alpha.13](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.12...restapi-0.0.1-alpha.13) (2023-05-19) + +### Bug Fixes + +* backward compatiblity fix ([fbf2463](https://github.com/ethereum-push-notification-service/push-sdk/commit/fbf246396a44513626fc1dda6e90c12d2f073ead)) +* Merge branch 'alpha' into alpha-deployment ([3b5a0f1](https://github.com/ethereum-push-notification-service/push-sdk/commit/3b5a0f160b72e775cf17031067fa7488171e1bbd)) + + + +## [0.0.1-alpha.12](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.11...restapi-0.0.1-alpha.12) (2023-05-19) + +### Bug Fixes + +* Merge branch 'alpha' into alpha-deployment ([963cc02](https://github.com/ethereum-push-notification-service/push-sdk/commit/963cc02768862b6a9427519257ff9f9565f613ea)) +* **video:** fix enableAudio ([85ef733](https://github.com/ethereum-push-notification-service/push-sdk/commit/85ef733127bdfbae5c66c671ddc7700785d192c0)) + + + +## [0.0.1-alpha.11](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.10...restapi-0.0.1-alpha.11) (2023-05-19) + +### Bug Fixes + +* added enums ([f1880d8](https://github.com/ethereum-push-notification-service/push-sdk/commit/f1880d8f037fc640851af4311bd5e514de5cf3db)) +* changed additionalMeta structure ([#406](https://github.com/ethereum-push-notification-service/push-sdk/issues/406)) ([0cf573e](https://github.com/ethereum-push-notification-service/push-sdk/commit/0cf573e56165bf3164a42cbc4b41a3085801e90a)) +* fix versions ([05c8fa9](https://github.com/ethereum-push-notification-service/push-sdk/commit/05c8fa9f9286e78d706c6be53e7b8ae963105766)) +* Merge branch 'alpha' into alpha-deployment ([68f11eb](https://github.com/ethereum-push-notification-service/push-sdk/commit/68f11eb71d44423081000c00c36cb0a936558f2f)) +* Merge branch 'alpha' into alpha-deployment ([3700515](https://github.com/ethereum-push-notification-service/push-sdk/commit/3700515be010fdcab6062db0a039f7df612a7a6b)) +* Merge branch 'alpha' into alpha-deployment ([925b437](https://github.com/ethereum-push-notification-service/push-sdk/commit/925b4379aa7b7d2d061b23d5ccbc42d06829f100)) +* **sendvideonotifications:** modify additional meta acc to new std ([#407](https://github.com/ethereum-push-notification-service/push-sdk/issues/407)) ([9d2124a](https://github.com/ethereum-push-notification-service/push-sdk/commit/9d2124aa61f798a0b137636aac62397e1e52150e)) +* **types:** remove bad import ([5517200](https://github.com/ethereum-push-notification-service/push-sdk/commit/55172002a2cecb33407a3828c2debeca24e0c972)) +* **video:** remove stop audio/video logic from create function ([#404](https://github.com/ethereum-push-notification-service/push-sdk/issues/404)) ([983c896](https://github.com/ethereum-push-notification-service/push-sdk/commit/983c896a2c89463f117f5a4d8153ef95501f2124)) + + +### Reverts + +* **getverificationproof:** add wallet and env params to getVerificationProof ([#403](https://github.com/ethereum-push-notification-service/push-sdk/issues/403)) ([26f6fcb](https://github.com/ethereum-push-notification-service/push-sdk/commit/26f6fcb9b2992850cd33ea613cea13830bd48bc3)) + + + +## [0.0.1-alpha.12](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.11...restapi-0.0.1-alpha.12) (2023-05-19) ## [1.3.3](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-1.3.2...restapi-1.3.3) (2023-05-31) ### Bug Fixes +* added enums ([f1880d8](https://github.com/ethereum-push-notification-service/push-sdk/commit/f1880d8f037fc640851af4311bd5e514de5cf3db)) +* fix versions ([05c8fa9](https://github.com/ethereum-push-notification-service/push-sdk/commit/05c8fa9f9286e78d706c6be53e7b8ae963105766)) +* Merge branch 'alpha' into alpha-deployment ([3700515](https://github.com/ethereum-push-notification-service/push-sdk/commit/3700515be010fdcab6062db0a039f7df612a7a6b)) +* **sendvideonotifications:** modify additional meta acc to new std ([#407](https://github.com/ethereum-push-notification-service/push-sdk/issues/407)) ([9d2124a](https://github.com/ethereum-push-notification-service/push-sdk/commit/9d2124aa61f798a0b137636aac62397e1e52150e)) * add profile.update feature ([#410](https://github.com/ethereum-push-notification-service/push-sdk/issues/410)) ([361b930](https://github.com/ethereum-push-notification-service/push-sdk/commit/361b9303c5340238bcb7fa457370707ae864756b)) * Merge branch 'main' into deployment ([59715aa](https://github.com/ethereum-push-notification-service/push-sdk/commit/59715aa307c0931e86476c18f78d495bc0de891f)) * Merge branch 'main' into deployment ([1d52d6b](https://github.com/ethereum-push-notification-service/push-sdk/commit/1d52d6ba5aaadd70d7ccfd3904100586ad74d0f0)) @@ -80,28 +200,45 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/s -## [1.3.1](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-1.3.0...restapi-1.3.1) (2023-05-22) +## [0.0.1-alpha.11](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.10...restapi-0.0.1-alpha.11) (2023-05-19) ### Bug Fixes -* merge main ([dc2ba17](https://github.com/ethereum-push-notification-service/push-sdk/commit/dc2ba179cef2f834ac4fe13a6673095b97a6e019)) +* changed additionalMeta structure ([#406](https://github.com/ethereum-push-notification-service/push-sdk/issues/406)) ([0cf573e](https://github.com/ethereum-push-notification-service/push-sdk/commit/0cf573e56165bf3164a42cbc4b41a3085801e90a)) +* Merge branch 'alpha' into alpha-deployment ([925b437](https://github.com/ethereum-push-notification-service/push-sdk/commit/925b4379aa7b7d2d061b23d5ccbc42d06829f100)) +* **video:** remove stop audio/video logic from create function ([#404](https://github.com/ethereum-push-notification-service/push-sdk/issues/404)) ([983c896](https://github.com/ethereum-push-notification-service/push-sdk/commit/983c896a2c89463f117f5a4d8153ef95501f2124)) + + +### Reverts +* **getverificationproof:** add wallet and env params to getVerificationProof ([#403](https://github.com/ethereum-push-notification-service/push-sdk/issues/403)) ([26f6fcb](https://github.com/ethereum-push-notification-service/push-sdk/commit/26f6fcb9b2992850cd33ea613cea13830bd48bc3)) -# [1.3.0](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-1.2.16...restapi-1.3.0) (2023-05-19) + +## [0.0.1-alpha.10](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.9...restapi-0.0.1-alpha.10) (2023-05-17) ### Bug Fixes -* merge main ([b58d9d5](https://github.com/ethereum-push-notification-service/push-sdk/commit/b58d9d53bd91fa33200a854170fe7e3facff4371)) +* added deprecated info to history ([#399](https://github.com/ethereum-push-notification-service/push-sdk/issues/399)) ([eda1a34](https://github.com/ethereum-push-notification-service/push-sdk/commit/eda1a345975141c5656891dbf919aacd2924d66b)) +* Merge branch 'alpha' into alpha-deployment ([46ebed2](https://github.com/ethereum-push-notification-service/push-sdk/commit/46ebed2b9d4b4ff0518429a091d0a37b1d3f022d)) -### Features -* add video sdk methods ([#395](https://github.com/ethereum-push-notification-service/push-sdk/issues/395)) ([4b9dd69](https://github.com/ethereum-push-notification-service/push-sdk/commit/4b9dd691ac1fde6a91be0478b20780f6755fbb4f)), closes [#295](https://github.com/ethereum-push-notification-service/push-sdk/issues/295) [#309](https://github.com/ethereum-push-notification-service/push-sdk/issues/309) [#357](https://github.com/ethereum-push-notification-service/push-sdk/issues/357) [#295](https://github.com/ethereum-push-notification-service/push-sdk/issues/295) +## [0.0.1-alpha.9](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.8...restapi-0.0.1-alpha.9) (2023-05-16) + +### Bug Fixes + +* Merge branch 'alpha' into alpha-deployment ([469398d](https://github.com/ethereum-push-notification-service/push-sdk/commit/469398dc94df805257d6a6bb8e0707cebc5f7d8a)) +* **video:** turn off trickle while creating peer instance ([#398](https://github.com/ethereum-push-notification-service/push-sdk/issues/398)) ([ae5b38e](https://github.com/ethereum-push-notification-service/push-sdk/commit/ae5b38e702539eaf92a516b4e557c5a88de0f4c7)) +- add deprecated info to chat.chat ([#392](https://github.com/ethereum-push-notification-service/push-sdk/issues/392)) ([d84ae64](https://github.com/ethereum-push-notification-service/push-sdk/commit/d84ae64c116adb7eea9e8faf7929b6eb3b74c657)) +- Merge branch 'alpha' into alpha-deployment ([549fd83](https://github.com/ethereum-push-notification-service/push-sdk/commit/549fd839867d84a98a10206a7f9945aeb1720e49)) +- Merge branch 'main' into alpha ([72464fd](https://github.com/ethereum-push-notification-service/push-sdk/commit/72464fd97260b612649035e3b241f946de8f9e92)) +- show hardcoded msg rather than throwing error ([#388](https://github.com/ethereum-push-notification-service/push-sdk/issues/388)) ([8962e10](https://github.com/ethereum-push-notification-service/push-sdk/commit/8962e10036916d0bc161324f5684f74bb7b74dc3)) +- **video:** set trickle to true while creating peer instance ([#397](https://github.com/ethereum-push-notification-service/push-sdk/issues/397)) ([0b609be](https://github.com/ethereum-push-notification-service/push-sdk/commit/0b609bec87a6187d1e7cbf8052a2b9a36b9fcd7a)) -## [1.2.16](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-1.2.15...restapi-1.2.16) (2023-05-19) +## [0.0.1-alpha.8](https://github.com/ethereum-push-notification-service/push-sdk/compare/restapi-0.0.1-alpha.7...restapi-0.0.1-alpha.8) (2023-05-16) ### Bug Fixes diff --git a/packages/restapi/README.md b/packages/restapi/README.md index 278ec1a80..41c86ebf8 100644 --- a/packages/restapi/README.md +++ b/packages/restapi/README.md @@ -83,6 +83,22 @@ This package gives access to Push Protocol (Push Nodes) APIs. Visit [Developer D - [enableVideo](#enablevideo) - [enableAudio](#enableaudio) - [isInitiator](#isinitiator) + - [For Spaces](#for-spaces) + - [To create a space](#to-create-a-space) + - [To create a token gated space](#to-create-a-token-gated-space) + - [To update space details](#to-update-space-details) + - [To update token gated space details](#to-update-token-gated-space-details) + - [To get space details by spaceId](#to-get-space-details-by-spaceId) + - [To start a space](#to-start-a-space) + - [To stop a space](#to-stop-a-space) + - [To approve a space request](#to-approve-a-space-request) + - [To add listeners to space](#to-add-listeners-to-space) + - [To remove listeners from space](#to-remove-listeners-from-space) + - [To add speakers to space](#to-add-speakers-to-space) + - [To remove speakers from space](#to-remove-speakers-from-space) + - [Fetching list of user spaces](#fetching-list-of-user-spaces) + - [Fetching list of user space requests](#fetching-list-of-user-space-requests) + - [Fetching list of trending spaces](#fetching-list-of-trending-spaces) # How to use in your app? @@ -1596,113 +1612,25 @@ Allowed Options (params with _ are mandatory) | env | string | 'prod' | API env - 'prod', 'staging', 'dev'|
- DEPRECATED - Expected response (Get channel's subscribers list) + Expected response (Get channel's subscribers list) ```typescript -// PushAPI.channels._getSubscribers | Response - 200 OK -[ - '0x004f0c30bdad515cb9c554e698b52d71f1227134', - '0x00bce6275dfe75758a4e266e8b7381831676bb0a', - '0x00de74918982b1350b5f1784be594b8b30a5400f', - '0x01080667d6f0a9dd7d5f303c0a57044e93e0c2de', - '0x012eaa22f2286e615e582963c4b8f3f1a5646882', - '0x01382270dc0ec27cca8e84a5c6c9370022b0d9ac', - '0x016ea99b87d0feccdf1097ba932c5d673bededbb', - '0x02045677924949cef7450e0ad427896e8a36a581', - '0x02057aa3359a05da74ba015c661c06877f4b1ec9', - '0x025846389950a13292e63e4794c7d148ff57f995', - '0x0277b0ad0ba9b830797b671f77a1fcd1ba008003', - '0x02b24ac2239b344fbc4577801f7000901e7a3944', - '0x0302cd04ee871672fa3f770dc63ddc764849191d', - '0x03b22d7742fa2a8a8f01b64f40f0f2185e965cb8', - '0x03fad591aeb926bfd95fe1e38d51811167a5ad5c', - '0x04041ee456080b1bc83dc265f133d607124937ea', - '0x04288caaefa55f1e8107a3b1682fdfc58d927f1b', - '0x044b595c9b94a17adc489bd29696af40ccb3e4d2', - '0x044c982efe7ee8443bba5fcc9feef6dc84a61421', - '0x0478c8faa8f9863bfb69b389866d5e2fdad62032', - '0x056397760b973bfb921bc10be9da5034b1e921d7', - '0x05934628535b3e96f30f05258f0ed2a433288744', - '0x05dac6b7daae1b251e8dcc1bc7fcdb2f4c36bcc6', - '0x06a81b13358188de4c6fced42c4f58f81fca3c5c', - '0x072e7399de2fa1711d3d7b8d99ba36e25c21d87d', - '0x073b49dacc79d597aa69be01a6adf1ec3a7b7f93', - '0x07add6f4fc06ac00a9b0a0d2fd3540fa011591b6', - '0x07da8ee7714e5bc9447e5d39eacd3159d90992b1', - '0x08249e6733d85239d91daf62b1862e2cf09ff77c', - '0x0827206a690235b774c3147075c36d897f1c7e80', - '0x087f5052fbcd7c02dd45fb9907c57f1eccc2be25', - '0x08e4d14eb2ca6b67f17c569b01d8bc74084f8b33', - '0x093512f0f6b123ed38fd687f11a9e2ece0c4c5f5', - '0x0984100b68e6e2b3b004934ab0881ac431863283', - '0x09a545f696881b42b118b52a04cc2ee0df365518', - '0x0a4349a6b51c8454fcff20af639da1fbef8a2501', - '0x0a651cf7a9b60082fecdb5f30db7914fd7d2cf93', - '0x0a79058fcd8d50511be32e8620d88c824e730014', - '0x0abc2c830a6757ce28377c05de38edbd4e049ddb', - '0x0bbb52b4fd34b99d0711e07dc072086e98951e6a', - '0x0bffd1d41787ef50f3945aae0100e6c5288a96be', - '0x0c41b769bdc9078ba2da2dac1b7afd2017ed3de9', - '0x0c573fc3729a7b754ea1ed7c25db55e83d860335', - '0x0cccd55a5ac261ea29136831eeaa93bfe07f5db6', - '0x0d94c4dbe58f6fe1566a7302b4e4c3cd03744626', - '0x0da6c279b3f548d189a612f73956d9d2b40909db', - '0x0e1f0a26c4de4d8bbdf220f13eb04836edd07a52', - '0x0e2cbb9d72247f0c8a04dfbaade690dfeb93740d', - '0x0f43eb2e71833319896b01e2412e07a0bb5e5a9d', - '0x0f85d268402ab52cdd72d9a28f95eabb5a653545', - '0x0fc26ce09e56594aa364d0890ae43bdc14152e25', - '0x101598974b6dba36068657986c53b5e178d757d3', - '0x102a2adf909b0ef85ce6d1b5dc61e72907cbb93a', - '0x103aaa8b06d4222b89b2be71d66c9ddf621e232d', - '0x103d189a6bab84f2ec9ab6950e66d31bec4a098e', - '0x10f26d2b7ab670b4f3e7d8ed24cd60152a1caf87', - '0x111771d37525db8c0bb19124f1547b4fbec16b54', - '0x1145b29b49f9b61d6178050b4b5e520255c2e565', - '0x124f7f89889648437c9cda73565862f398930e62', - '0x12519784a33e899718eddecfe0045b19ee6b68d8', - '0x1251a5e5cfba7a6dfd6509d65f6eef3e66ebf320', - '0x127a95027b5c7e1d807433837c9cdd7e6f336803', - '0x12c52f225608774e8e0e05d04e9b4341fd11174b', - '0x140aa50e72b394217ec331396f9b569218820364', - '0x1434a7882cdd877b398df5b83c883e9571c65813', - '0x14c0157f9eea7aee61ba2606e75716e210b4697a', - '0x14ef3ef528aea2887e40f3ea286ab2859a795463', - '0x15287a2893c4c22098f6bf0e97e2e5b933c897ef', - '0x15405d4d57491430fbf00dc032bd5b1fbf72e6e7', - '0x155ddcf7d0871da12c32f1ca3a0b3df7a15aadbe', - '0x15900c698ee356e6976e5645394f027f0704c8eb', - '0x1590a25b46cc85f85dfcc1a3746c766a13af0cb5', - '0x15bc81b35a8498cee37e2c7b857538b006cecaa5', - '0x15faf8d03d669021e341122ab4bb27559e838538', - '0x161f99e11a0d76e4aba84330738dd9c38a4d1daa', - '0x16860bd82bc5a595b47d40a553cf13fae4bc916b', - '0x16c67634b61eb144f8630ccd1ffff9a0d32f4657', - '0x16eb4622f00bed1d27dccb4c0684c0e16512a36f', - '0x18241781b17b878cfc16b109035904c8e5073e73', - '0x186800b7e090271c922450c47ad30c2702c7bfe9', - '0x18770728fe5d4a8a0e3f31eacbf022f7b82a6740', - '0x190e7f3424b23ed9b54ed8ce8688cbca672ad022', - '0x1971b593c77617092b342d63a7f9111b31a0faba', - '0x19b3161b77b1c36d92a1ccad1cd1a301d1576d31', - '0x1a41820f84d090e4afc3066f6d8214d2a6e32870', - '0x1a668e5cdd5ae00d02fadf6c00bf9c9dd98aeb1a', - '0x1aa3127b831a33830ac0fe3ee4b0741d1a4a4e04', - '0x1bbc42f65f49a2efd83eea49c3698bd35ae3e0ec', - '0x1bc5c90cc9bfb632ca432d46176c52b3578f64e2', - '0x1c6f97c400a9804a1bb1d7026c77cd7494e78ca5', - '0x1cb28bbe58891442064a3a1d5813c92c217d2424', - '0x1d0911cfa2bd2a85d610c73a7bb04818fc4c93bd', - '0x1da02db5b4ec5c151a8bd64f1320b5683fba3ff1', - '0x1db67d560813ea7aba48bd8a9429cbecbeb2118e', - '0x1e26b7da859358598bad185c83932aad741e6c10', - '0x1ec0d39981d2dcf253b2b18b945d3310bc254560', - '0x1ef7a2a03d5369ed0b9807adb2b16e87f1f30baf', - '0x1ef7f4c06cb7630fdcb5dd324f22c0a8ec85f93f', - '0x1f771818c74a052226c01ebad909640a3fd97b43', - '0x1f85fd5b55fa2e6f544b84b9852f89ed035fdacd', - ... 656 more items -] +// PushAPI.channels.getSubscribers | Response - 200 OK +{ + "itemcount": 11, + "subscribers": [ + "0x1d4f52775344f9a32093af0ccd03a4fb6dac8e30", + "0x28d615edd8404f8ca1e0271a0b5a48171589921a", + "0x4352639b99689069f9b0b847eee349c3c1b0706c", + "0x50029e62540537045bcfd3d320483865344edb33", + "0x5ac9e6205eaca2bbba6ef716fd9aabd76326eeee", + "0x778d3206374f8ac265728e18e3fe2ae6b93e4ce4", + "0xa44f2994750cf774eab05751d90ade4dedabe7fe", + "0xbcfb7da1dcf40e8cfb331683bb7d6f4eba091b08", + "0xcf5dbf241fc65a5af56c95101ac4e9ec2c57d941", + "0xd8634c39bbfd4033c0d3289c4515275102423681" + ] +} ```
@@ -4294,3 +4222,1800 @@ Allowed Options (params with \* are mandatory) ```typescript isInitiator(): boolean ``` + +--- + +## For Spaces + +### **To create a space** + +```typescript +// pre-requisite API calls that should be made before +// need to get user and through that encryptedPvtKey of the user +const user = await PushAPI.user.get(account: 'eip155:0xFe6C8E9e25f7bcF374412c5C81B2578aC473C0F7', env: 'staging'); + +// need to decrypt the encryptedPvtKey to pass in the api using helper function +const pgpDecryptedPvtKey = await PushAPI.chat.decryptPGPKey(encryptedPGPPrivateKey: user.encryptedPrivateKey, signer: _signer); + +// actual api +const response = await PushAPI.space.create({ + spaceName:'wasteful_indigo_warbler', + spaceDescription: 'boring_emerald_gamefowl', + listeners: ['0x9e60c47edF21fa5e5Af33347680B3971F2FfD464','0x3829E53A15856d1846e1b52d3Bdf5839705c29e5'], + spaceImage: <space image link> , + speakers: ['0x3829E53A15856d1846e1b52d3Bdf5839705c29e5'], + isPublic: true, + account: '0xD993eb61B8843439A23741C0A3b5138763aE11a4', + env: 'staging', + pgpPrivateKey: pgpDecryptedPvtKey, //decrypted private key + scheduleAt: new Date("2024-07-15T14:48:00.000Z"), + scheduleEnd: new Date("2024-07-15T15:48:00.000Z") +}); +``` + +### **To create a token gated space** + +```typescript +// pre-requisite API calls that should be made before +// need to get user and through that encryptedPvtKey of the user +const user = await PushAPI.user.get(account: 'eip155:0xFe6C8E9e25f7bcF374412c5C81B2578aC473C0F7', env: 'staging'); + +// need to decrypt the encryptedPvtKey to pass in the api using helper function +const pgpDecryptedPvtKey = await PushAPI.chat.decryptPGPKey(encryptedPGPPrivateKey: user.encryptedPrivateKey, signer: _signer); + +// actual api +const response = await PushAPI.space.create({ + spaceName:'wasteful_indigo_warbler', + spaceDescription: 'boring_emerald_gamefowl', + listeners: ['0x9e60c47edF21fa5e5Af33347680B3971F2FfD464','0x3829E53A15856d1846e1b52d3Bdf5839705c29e5'], + spaceImage: <space image link> , + speakers: ['0x3829E53A15856d1846e1b52d3Bdf5839705c29e5'], + contractAddressERC20: "0x8Afa8FDf9fB545C8412499E8532C958086608b30", + numberOfERC20: 20, + contractAddressNFT: "0x42af3147f17239341477113484752D5D3dda997B", + numberOfNFTTokens: 2, + isPublic: true, + account: '0xD993eb61B8843439A23741C0A3b5138763aE11a4', + env: 'staging', + pgpPrivateKey: pgpDecryptedPvtKey, //decrypted private key + scheduleAt: new Date("2024-07-15T14:48:00.000Z"), + scheduleEnd: new Date("2024-07-15T15:48:00.000Z") +}); +``` + +Allowed Options (params with _ are mandatory) +| Param | Type | Default | Remarks | +|----------|---------|---------|--------------------------------------------| +| account_ | string | - | user address | +| spaceName* | string | - | group name | +| spaceDescription* | string | - | group description | +| spaceImage* | string | - | group image link | +| listeners* | Array | - | wallet addresses of all listeners except speakers and spaceCreator | +| speakers* | Array | - | wallet addresses of all speakers except listeners and spaceCreator | +| isPublic* | boolean | - | true for public space, false for private space | +| scheduleAt\* | Date | - | Date time when the space is scheduled to start | +| scheduleEnd | Date | - | Date time when the space is scheduled to end | +| contractAddressERC20 | string | null | ERC20 Contract Address | +| numberOfERC20 | int | 0 | Minimum number of tokens required to join the space | +| contractAddressNFT | string | null | NFT Contract Address | +| numberOfNFTTokens | int | 0 | Minimum number of nfts required to join the space | +| pgpPrivateKey | string | null | mandatory for users having pgp keys| +| env | string | 'prod' | API env - 'prod', 'staging', 'dev'| + +
+ Expected response (create space) + +```typescript +// PushAPI.space.create | Response - 200 OK +{ + members: [{ + wallet: 'eip155:0x727C819feB2c7F99c66d71B8411521bca2010023', + publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + 'xsBNBGSrssEBCACg3ZjrZB40Xqr5IKIEtFldaeQyJPNwDACMekY77yApav0B\n' + + 'RwiqhFJDFJKcprSHg/vYdqalAIGRQ+J98VMBtHweurIubD/ODB6WknOms7ZY\n' + + '3ummaEzyFRombuq/C75o/0ImCi2v0PJBI3kdpwzOjiTt8S44yoAVOcTf9jyg\n' + + 'vTEVCOM81yqCf0mDB4t0jqRYewlQuJegORXDKHKTfZcnQybBkDYUGgmxOcyF\n' + + 'BaPMhSiWqAAqqb4gcFO2QKq69JoiE9dzSuF/7dvAq2QZRogC/GQW2Q9yQbq3\n' + + 'CvMNO4H2KUZzegaq2s2nMPGMXPNf4GZcZVJE1phWgAnApxTf5kUFfKr1ABEB\n' + + 'AAHNAMLAigQQAQgAPgWCZKuywQQLCQcICZDwrCS5ulOLwQMVCAoEFgACAQIZ\n' + + 'AQKbAwIeARYhBFKpO7zcSRed+QmbIfCsJLm6U4vBAABZMwf+OIbBcFQ7x++1\n' + + 'NINOYbP9v0PyJvpllDcUORbk3uiPMpvDuQYAe2Fd4dY2Y91l3VdpIm/w6HQy\n' + + 'y81Y694w4E7PRVhDwHivv5D10VE9MF3h6qOHrLLpvdhpMaB5Ur8ts5rU2zOu\n' + + '64HR04/BVO9N0nrE9iywIgVMOy6IrS+OgK3r75PPX35bam/kbbmZHeygFaE9\n' + + '+mgQVdhwgF5borekIiz1Rc8CPA/P1yZy8QQl4KGmJEs+hOc5rPnUWwarvaAH\n' + + 'mPb6H0/mG81eXBOjpJlSFu6d/uqKLpoAw5fkvFoIsNwovYpyQkSbhzwe4T2N\n' + + 'jGqGd0+La03QdB5FbaiwcnJ96lU6oM7ATQRkq7LBAQgAxu9uK1+p62+/RvcF\n' + + 'Mz7g3A8SJiN76NYxk29sjQ9gW74B/IdPv5TlUVhG6PGr2c3SucASlEHieagY\n' + + 'CXM2+fpdu4rQ6EKRAe+30GFopfzhX1d0zv9d5BE6q1ML5mkrpDECH5iuqah7\n' + + 'smmbRdWE7zRSGaHyEfVqAG3wfMzzN0BcchxxR4vMCNKYLs9v2Q09ecO7DgaY\n' + + '5CZqxaFlTo+auuDhE0XU7WRbNL77izocV1Sm+McRyo28PrFTcrRRznD1nP0V\n' + + 'eZ4+aoulqyYA+gBBaIUdSA5kQXJiy67crB50yX3V6zLIfptD2ThHPjTY/inW\n' + + 'wVHVug4jIWUQ1QQw/q9qvGxAzQARAQABwsB2BBgBCAAqBYJkq7LBCZDwrCS5\n' + + 'ulOLwQKbDBYhBFKpO7zcSRed+QmbIfCsJLm6U4vBAADu6wf+NJDX/3NAxQKN\n' + + 'Iigj0GkBm/y69iFmQvWJxxtiYCNu8VBhm8MkcghUJ8G2tWP9ueUOM8sMTEa+\n' + + 'G+l+wSNwh/1yisF3FutDpy6l+fiy6kPPD4vl08jY3GrqSuWWfMxTJhMZ5D6v\n' + + 'OW2EfdyET+oP5eOnCd6p0EXP2ic48rVHDdU2iWeg0RkGvZP3t2LljWFdLbvw\n' + + 'h7+wSD1i4LY4slUIdbLdDSLN1gWFN1HXzX10mpX0grV2sBdfkNyHhF0WcIat\n' + + 'sD9HpAx2M62yP2D9D9UZVrW7WfmOoyL1NrnXSJsI8CRFDzujvpIrr7875zSi\n' + + 'VnxDVyt7twc7cYqRDHsNYuxAuE815A==\n' + + '=2jvb\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n', + isSpeaker: true, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA4klEQVR4AcXBoW3FMBRA0dsn75E9skAU6BkMSk1CA0xNsoBnMLSyQPbIDgVlLX0OcPX1Vb1zPj6/v35QWg5o61bQok+MHHVHazmgrVtBE4wJxgRjjofzmuj4xCuiT2iRCe2gJxgTjAnGXMuBTi2MRJ8YOerOSMsBTTAmGBOMuXUraNEntKPuaEfdeUX0iU4taIIxwZhgzPGH6BP/STAmGBOMOR6W+UY7r4l3LPONttITjAnGBGMu+kSnFrQlB96xbgUt+oQmGBOMCcYcDy0HRs5rYmSZb7SWA1pkQhOMCcYEY78uSjTZAXCkaQAAAABJRU5ErkJggg==' + }], + pendingMembers: [{ + wallet: 'eip155:0x5f4e9e7Fcc17a943178c0b0881b09E8Ef9D34437', + publicKey: null, + isSpeaker: false, + image: null + }, + { + wallet: 'eip155:0xFedfA2b276676C5c6ce753ddb4B05d00104E9236', + publicKey: null, + isSpeaker: false, + image: null + } + ], + contractAddressERC20: "0x8Afa8FDf9fB545C8412499E8532C958086608b30", + numberOfERC20: 20, + contractAddressNFT: "0x42af3147f17239341477113484752D5D3dda997B", + numberOfNFTTokens: 2, + verificationProof: 'pgp:-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkq7LBCZDwrCS5ulOLwRYhBFKpO7zcSRed+QmbIfCsJLm6\n' + + 'U4vBAAAAHwf+K4f0gxaP56X4Cv2zlPWB9iUPi/1FOnx8ZF7oEf9xJSv/xA7v\n' + + '9LHBTZ2Y9AQlJpy0WLB7KGF7mVV1MdUKHjn2SFQ+1h+8d+FIHXfmB7Ie4alP\n' + + 'nnar6XjtMVKYyqXRzMzCq2F7Fjea1sUOXBxAeyJstAGG6nvsU51imaAtGQlQ\n' + + 'u7ih8D9UkiOe719v5GyI1vtiS+hHGlYo0+A7WVImH6SuVyPZ3UyPvLxXpeKs\n' + + '1SeEfuvfmKHbswm1DDGOknyo7fJ/QgKqOfkwsBIrYRNGwPGEKt8pHdwNxsNn\n' + + 'hNQtlFqtmtvieaxbhJQKXHbVgNv206xNsUBrK/U2nCakx7EMmxikFg==\n' + + '=tz9T\n' + + '-----END PGP SIGNATURE-----\n', + spaceImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + spaceName: 'wasteful_indigo_warbler', + isPublic: true, + spaceDescription: 'boring_emerald_gamefowl', + spaceCreator: 'eip155:0x727C819feB2c7F99c66d71B8411521bca2010023', + spaceId: 'spaces:e0553610da88dacac70b406d1222a6881c0bde2c5129e58b526b5ae729d82116', + scheduleAt: '2023-07-15T14:48:00.000Z', + scheduleEnd: '2023-07-15T15:48:00.000Z', + status: 'PENDING' +} + + +``` + +
+ +--- + +### **To update space details** + +Note - updateSpace is an idompotent call + +```typescript +// pre-requisite API calls that should be made before +// need to get user and through that encryptedPvtKey of the user +const user = await PushAPI.user.get(account: 'eip155:0xFe6C8E9e25f7bcF374412c5C81B2578aC473C0F7', env: 'staging'); + +// need to decrypt the encryptedPvtKey to pass in the api using helper function +const pgpDecryptedPvtKey = await PushAPI.chat.decryptPGPKey(encryptedPGPPrivateKey: user.encryptedPrivateKey, signer: _signer); + +// actual api +const response = await PushAPI.space.update({ + spaceId: 'spaces:e0553610da88dacac70b406d1222a6881c0bde2c5129e58b526b5ae729d82116', + spaceName: 'Push Space 3', + spaceDescription: 'This is the oficial space for Push Protocol', + listeners: ['0x2e60c47edF21fa5e5A333347680B3971F1FfD456','0x3829E53A15856d1846e1b52d3Bdf5839705c29e5'], + spaceImage: <group image link> , + speakers: ['0x3829E53A15856d1846e1b52d3Bdf5839705c29e5'], + scheduleAt: '2023-07-15T14:48:00.000Z', + scheduleEnd: '2023-07-15T15:48:00.000Z', + status: PushAPI.ChatStatus.PENDING, + account: '0xD993eb61B8843439A23741C0A3b5138763aE11a4', + env: 'staging', + pgpPrivateKey: pgpDecryptedPvtKey, //decrypted private key +}); +``` + +### **To update token gated space details** + +Note - updateSpace is an idompotent call + +```typescript +// pre-requisite API calls that should be made before +// need to get user and through that encryptedPvtKey of the user +const user = await PushAPI.user.get(account: 'eip155:0xFe6C8E9e25f7bcF374412c5C81B2578aC473C0F7', env: 'staging'); + +// need to decrypt the encryptedPvtKey to pass in the api using helper function +const pgpDecryptedPvtKey = await PushAPI.chat.decryptPGPKey(encryptedPGPPrivateKey: user.encryptedPrivateKey, signer: _signer); + +// actual api +const response = await PushAPI.space.update({ + spaceId: 'spaces:e0553610da88dacac70b406d1222a6881c0bde2c5129e58b526b5ae729d82116', + spaceName: 'Push Space 3', + spaceDescription: 'This is the oficial space for Push Protocol', + listeners: ['0x2e60c47edF21fa5e5A333347680B3971F1FfD456','0x3829E53A15856d1846e1b52d3Bdf5839705c29e5'], + spaceImage: <group image link> , + speakers: ['0x3829E53A15856d1846e1b52d3Bdf5839705c29e5'], + scheduleAt: '2023-07-15T14:48:00.000Z', + scheduleEnd: '2023-07-15T15:48:00.000Z', + status: PushAPI.ChatStatus.PENDING, + contractAddressERC20: "0x8Afa8FDf9fB545C8412499E8532C958086608b30", + numberOfERC20: 20, + contractAddressNFT: "0x42af3147f17239341477113484752D5D3dda997B", + numberOfNFTTokens: 2, + account: '0xD993eb61B8843439A23741C0A3b5138763aE11a4', + env: 'staging', + pgpPrivateKey: pgpDecryptedPvtKey, //decrypted private key +}); +``` + +Allowed Options (params with _ are mandatory) +| Param | Type | Default | Remarks | +|----------|---------|---------|--------------------------------------------| +| spaceId_ | string | - | Id of the space | +| account* | string | - | user address | +| spaceName* | string | - | space name | +| spaceDescription* | string | - | space description | +| spaceImage* | string | - | space image | +| status* | string | - | space status - 'ACTIVE', 'PENDING', 'ENDED' | +| listeners* | Array | - | wallet addresses of all listeners except speakers and spaceCreator | +| speakers* | Array | - | wallet addresses of all speakers except listeners and spaceCreator | +| scheduleAt* | Date | - | Date time when the space is scheduled to start | +| scheduleEnd | Date | - | Date time when the space is scheduled to end | +| contractAddressERC20 | string | null | ERC20 Contract Address | +| numberOfERC20 | int | 0 | Minimum number of tokens required to join the group | +| contractAddressNFT | string | null | NFT Contract Address | +| numberOfNFTTokens | int | 0 | Minimum number of nfts required to join the group | +| pgpPrivateKey | string | null | mandatory for users having pgp keys| +| env | string | 'prod' | API env - 'prod', 'staging', 'dev'| + +
+ Expected response (update space) + +```typescript +// PushAPI.space.update | Response - 200 OK +{ + members: [ + { + wallet: 'eip155:0x367c6555b2CAD9C2d2656066EC3996Ba12cD058d', + publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + 'xsBNBGSr17UBCADhEXWz/lsg0sDA+QRygzl+4t84/YYa459nzFRNB36jkbU8\n' + + 'FxRsE6oZTu0Leanup7aul4trJJ4qyA6xFfDjprDzrm1Gtp/gos46Lxk+br64\n' + + 'lzgqTfSKpBs9UWqOcr4Vnoq9WeOiFZax0DhN//7ibIQDWIJ0E6iOc8uiSoGZ\n' + + 's4AHTx7GtUvHxIUAk/hQY8UjjDNyhgCSrmdPeWt/SVbmFCHchdH/KhSK8JVq\n' + + 'qs8/nKx2Tm/nmAdWFZDqIJxd5tVuXXMxTZYZADZfmBltR2F/8GkF7hfX/aOo\n' + + 'gGQ/u2FPbCKRjtedfJi3WsPUKtyFg6QdwBnOQmYn0fGXlPGR7UVSsmIVABEB\n' + + 'AAHNAMLAigQQAQgAPgWCZKvXtQQLCQcICZD2NRrvru2XMgMVCAoEFgACAQIZ\n' + + 'AQKbAwIeARYhBM1nsbalDm3PtLAK2/Y1Gu+u7ZcyAADzuwgAmTBbnBQZ2w06\n' + + 'RbLmcZf8cYTof1X3mpYBa1lprMltib2jZQdu8DxhZBapYIE1O0UzV2Dy8IXj\n' + + 'zavtNFZiLR8FTwkrXQ3DGrZylnqjLkQ6m2jZsGIypb2OpTlBIBnjW98Dh99F\n' + + 'egI/5wse59IfGhYXVcKluKDAW2ezUJx8BhacZCwf/S8iG9YKrZctS5cVZxQw\n' + + 'SymXv88msoQrWhxmu2AT0rNsZ656ANMr/MuUjKMxQsoNCNIkp5kE0UTGfMwc\n' + + 'c69Gabs9uOPOqAGeSBGVfw+uJig/RJ4MWDCbj6QIDsV5FFRvTmJmmSNLNH5y\n' + + '83pHxE+923z6NiPWRonbns3pFNvhnc7ATQRkq9e1AQgAxjGMkGhs2OTW8fW/\n' + + '4tloJOID0UIDrz/24uX4JU+qjTqMzFyNGaNagT8n0xDH2E63YFmketip4QA2\n' + + '6kUBICKR2Y5kNNzkJXK4NYfa5OXEIS+lw+X7oMXd9YJ/D1fig1XD4Bf0ofsZ\n' + + 'QIxHOn6w3T/wQHOBpu+cqE3d0pW+6s6hZ4mkuPk6OXrkBSEtynk4ADQS+a3b\n' + + 'PrCGU9rJy2OnbP+lMr3onv/6BR/DFE4qCIfQt0cLu4nhAuYVYrOupi3p9eBQ\n' + + 'z/oWHCSNQVQSW2/vHp0YwMj2r3jSGdoZ3pcfy4iXOa7xEyeauOn/pHK+syOX\n' + + 'Pv64DHncql4AJFj9tw4rZ2/kkQARAQABwsB2BBgBCAAqBYJkq9e1CZD2NRrv\n' + + 'ru2XMgKbDBYhBM1nsbalDm3PtLAK2/Y1Gu+u7ZcyAADapwf/XF6I2NifyL/h\n' + + '2aVsr2lL2At732336je3WM6QnA/q1x9lmxX646c9eETUQvLLhT5RZmx1X8Fa\n' + + 'X/qGMKJe+BWLFPy5k6LnOezvvOxHGV+dzRndlWbnC9d3AZhThciw/Rd8V9W6\n' + + 'd6luo7+Apdd3rS17hG4gElhNX1drq5TuWR89yxA5oXcIqA+u3jBdpz0qo/ME\n' + + '+63r0AubixdM7rgV0skugaIXvqMKtfMC/V2A8mCL5AmRXCyfMBIsEA0L5YA1\n' + + 'wsKlHIQAy3jiPdY/2q5KUWJsR9o/IFirjnTd5vywtYsscOq/KnfLKdc2cVOr\n' + + 'e/vSkTOrD+dVTlxGhADoud4kvcOPtg==\n' + + '=6H2/\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n', + isSpeaker: true, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAy0lEQVR4AcXBMU5DMRBF0cvI63FJETn7oXY3K3CBNHX2g/WFKKdnLdCOUnyEgnjnPH2+v35RXPagOsbmEZc9qI6xqQwxQ8wQa9w5xuYvHWNzxhAzxAyxxg8ynKrPxZkMp+pzccYQM8QMsZbhVH0uzmQ4j8hwKkPMEDPEWp+LKsOp+lxUGc6ZPhdVhlP1uagMMUPMEGsZzn/KcCpDzBAzxBp3+lxUGU718vzGmVtcqfpcVBlOZYgZYoZY63PxG7ePK4/oc1EZYoaYIfYN05Y0ReqpB6sAAAAASUVORK5CYII=' + } + ], + pendingMembers: [ + { + wallet: 'eip155:0xB026B0A8BB1fea997a73c5a84fe7aF8cAab1AcF2', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA4ElEQVR4AcXBsU0EMRCG0Y+RC3ETzpwheqAFOnBmOZtSNqGC02abOaUAdwLp3AU+IYT+916+Pj6/CXLp/Kc1B5EhZogZYokn1hxEuXR21hxEuXR2DDFDzBBLuXSiNQdRaxeR+2CntYvIfRDl0okMMUPMEEs8cZw37pQbO8fJnUVlxxAzxAyxxINcOtGag7/IpbNjiBlihlh6f30jcq9EuXSiNQc7uXSiNQdRaxeRIWaIGWLJvRK1dhEdJ3dy6fxGaxeReyUyxAwxQyzxwL0SLSpRLp2dNQeRT7YMMUPMEPsB1yM4zt7CMugAAAAASUVORK5CYII=' + }, + { + wallet: 'eip155:0x9b70FD7164ec0Ed3E1B3E318836522340dd2e125', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA0UlEQVR4AcXBMWoDMRRF0ZtnkWYKgddgGKbSVrSILFBbUWUMLrICgwqXQ9L+NDKDIe+cj8+v7x+CPhpRyZV39NGISq5EwkyYCbN0f9z4a2Omj8ZMyZVo2Tei++NGJMyEmTBLz9OVqOTKTMmVIy7nlaiPRiTMhJkwS8u+8Z+WfSMSZsJMmKXLeWWmj0a07Bszz9OVqORKdDmvRMJMmAmzxAslV45ZOUKYCTNhlvpozJRcifpozJRcifpozAgzYSbMEi/00YhKrsz00ThCmAkzYfYLlLsvpsHyBx0AAAAASUVORK5CYII=' + }, + { + wallet: 'eip155:0x1A050099a08D7faf3b5923669a0FAe42A0872D72', + publicKey: null, + isSpeaker: false, + image: null + } + ], + contractAddressERC20: null, + numberOfERC20: 0, + contractAddressNFT: null, + numberOfNFTTokens: 0, + verificationProof: 'pgp:-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkq9e1CZD2NRrvru2XMhYhBM1nsbalDm3PtLAK2/Y1Gu+u\n' + + '7ZcyAAA0igf/Tgo/WU4C5g4UtHPCwU/jThQwjElzCa96bZU8bCXsgnoO1NMI\n' + + 'fwI7FxIw8FmFrktHIWT10T/9vq2ItyUvpbWRhnD5zt5aRhJ1KA1z06iwkoUt\n' + + 'DLiPfveoSDyIhUIjx5PUMN0r/tXmLhj3CrkHx1hiPBxEkhi9brfFcOvX57HS\n' + + 'VOKOeeUa4G1cmk6dtzLHWT4p7ekrFhZPHXDtZUMZEU2wbMkB6bRqlZ7UYLbN\n' + + '7+0AvCu7uaCYG0zfbl3oZc6DkIm9jnBknsII6Hqv7Dc9NLAUBWo8tPrW2/KN\n' + + '8Bv/gk5HPb16tOihIUjs8v45wO3oTPAQYbJGdF6ta+HyiKO8JWipbw==\n' + + '=wkHz\n' + + '-----END PGP SIGNATURE-----\n' + + ':null', + spaceImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + spaceName: 'mobile_aquamarine_constrictor', + isPublic: true, + spaceDescription: 'conventional_crimson_dove', + spaceCreator: 'eip155:0x367c6555b2CAD9C2d2656066EC3996Ba12cD058d', + spaceId: 'spaces:108f766a5053e2b985d0843e806f741da5ad754d128aff0710e526eebc127afc', + scheduleAt: '2023-07-15T14:48:00.000Z', + scheduleEnd: '2023-07-15T15:48:00.000Z', + status: 'PENDING' +} +``` + +
+ +--- + +### **To get space details by spaceId** +```typescript +const response = await PushAPI.space.get({ + spaceId: + 'spaces:108f766a5053e2b985d0843e806f741da5ad754d128aff0710e526eebc127afc', + env: 'staging', +}); +``` + +Allowed Options (params with _ are mandatory) +| Param | Type | Default | Remarks | +|----------|---------|---------|--------------------------------------------| +| spaceId_ | string | - | space id | +| env | string | 'prod' | API env - 'prod', 'staging', 'dev'| + +
+ Expected response (get space by space id) + +```typescript +// PushAPI_space_get | Response - 200 OK +{ + members: [ + { + wallet: 'eip155:0xd1ab5Af3Be78bB1492099CE568761F0e706352a0', + publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + 'xsBNBGSr528BCADI8kQcWkaw9PKmSrwCtPBDWj+wzPhmok9jAzxzb2+qAjSV\n' + + 'rYdIrnx6PAp1rMU6qoVg4cdDbCYPV+kCj8l3lUzH/a/SfPsDWpspA/ICWMeS\n' + + 'dMdGYxHLk2gsu0wRz69qoddXMY1h5eMZEyRnr2fsX/cy15mxO2IEHYnC2/rp\n' + + '06iFpx1T8k5HWgFDpyleWyMSQ7Bnn7GutrlHYEVtIGVfXDSkea8IDLLkzBEV\n' + + '3jlBUFhpsrlcvDwDYcMYOrqSBEtg1a+GMK+2Ye/hF37KUYTAPleKXeN0cYIs\n' + + 'Va8oleZK960XYfuy5SYCJav2kaAggNWQBie5G9C4H3h7FuFwWk8LH3DhABEB\n' + + 'AAHNAMLAigQQAQgAPgWCZKvnbwQLCQcICZBm9Bz6DvB6DwMVCAoEFgACAQIZ\n' + + 'AQKbAwIeARYhBPkdSvwnOBuAJaOWAGb0HPoO8HoPAAAkiQgAukm3owebckwr\n' + + 'xAR42r/+CBx1uoqM2ZeEAUeYtBF7sdLEsdxFrxl8wHKAbglZwtgWcfG95v2R\n' + + 'zLcBco3v9p0IuS6DZduIfhngZ49gpYwqFGyiCOvo+k14tuMbrbOZTTKp0uc6\n' + + 'icpTyP8/1U0nZrQmmSXyfh6Hgmx1OnW3zTM7oUN1ZVvj3V6rOl+ktUPjAaYo\n' + + 'CWJjth92xhDWEPZnC/4Gz2eRoTVtmx8u+/2vNPffQVgzzHznUxB+G5XeZmPk\n' + + 'z8oxxSxII8PNiAs5LizqPjyq2gEv25GlCsMXTYz60n/t/4G7Yc94yu8xD8u3\n' + + 'BpWluHC2eW0pYFcDfiNLfv0uJCrUcM7ATQRkq+dvAQgA7v7Zz4CZdPsd4jvB\n' + + 'uDwjop/Gvoz+rbvAdS3Xrsi+OTyrWAqidnXChhwExlUNelZ9v52lGxe1twwr\n' + + 'vxeQ4M0pv4oqSlZxhkqBCyj+E7ECR2WXG7ccLlzYOz3b5BXT+fEkmVsbVTjA\n' + + 'Kttjosm7FtY4igY2Hu4UlZZW8M1tYL1R/UegFeMYGY7aO7dcKeiP0NsDwm3c\n' + + '0SiU6/JlOXAIi/ZSKDJ4b5BPK6GFj5pNWr92/V7LejlZfoHAVDbb91tiPGdP\n' + + 'y3+r9T3IYsgUDLgOpPQn6o82Nctm6CnIZqAN12nJ1DEJP2JyLDedg9b5H+aa\n' + + 'FDZFc7yQ3In/QPtjHImydLt9NwARAQABwsB2BBgBCAAqBYJkq+dvCZBm9Bz6\n' + + 'DvB6DwKbDBYhBPkdSvwnOBuAJaOWAGb0HPoO8HoPAABRUQf+KoF4UXuseLBO\n' + + 'd0PD0+hEcnsYbaPWmPZtJPWusxPl6kt421luymPiThDXwaMVzRrmxkz0dNZ3\n' + + 'bUFYtS24t2BhlXZ6cGFNRjXrA9OV0kLg/kNm1vboQ1GL8qRV9CIjPVEpksQp\n' + + 'tOiYN+X+/2XdPJkaQpITHIFV067qWQSAKIonvOI8OJYOovGRQTInz0VE71Yn\n' + + 'SeiOilKBK+p2RN38jGr0PGWt740KJ6560FzfUwTAQzz9vrkYa+vEhWe+bzOd\n' + + 'YBpxj/BRTGR19DrKlGcFPdTYz5ADxCjBuCxXgoRCbBiWwh+iIstk5qkT8uHK\n' + + 'NQjzDvo3RO1cROQp0zsikladmzGZHQ==\n' + + '=q/e/\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n', + isSpeaker: true, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA10lEQVR4AcXBsWnFMBSG0c8/brOD9kgfogHUGQIuAppInSsVAQ2gdbSD64fTXl4hMI/HPWf5fXxf3DDaxkxIlTuEM+FMOFt5MtqG1XvBipGpsp9YMWaskCqWcCacCWfL4+fzwogx8069FyzhTDgTzpavv3oxEVLlFaNtzAhnwplwtvIkpIpV9hMrxsxM7wUrHxVrtA1LOBPOhLM1pIo12oaVj4rV98JMPj6wRtuwQqpYwplwJpyt3BRjZiZQuUM4E86Es7XsJ1aMTIVUeUXZTyzhTDgTzv4BnGY033BWusUAAAAASUVORK5CYII=' + } + ], + pendingMembers: [ + { + wallet: 'eip155:0xaC6C69c657cF6022fa787B14BDdaA22936B56D65', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA2UlEQVR4AcXBQWoEIRBA0Z+ikOwNDHirbARPKDiLvkzOIATaC4iQbGt6ITSzqPc+np8/fxhpVazzcfCOr99vrK4FS3AmOBOcKRddCy9GwQoxszNHw+rKluBMcCY407QqO10L1hyNO9Kq7AjOBGeCMz0fB9YcjZ20KjtdC1bXghVixhKcCc4EZzpH446uhXfM0bAEZ4IzwZmGmLHmaOyEmNmZo7ETYsYSnAnOBGfKRVoVq2vBmqNxR1oV6+SV4ExwJjhTLroWdkLM7MzRsLoWrMCBJTgTnAnO/gGd1jrTKk/8EAAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0xEf532414907E8c631307c0d501cDe6D1694bAF5e', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA00lEQVR4AcXBobHDMBBF0ZsdjftIDeGuIkzIaGsQC1MNQkZirsLcnaQCk3yqBOzMH4N3zu11f38I+GPiinacRAwxQ8wQS/zo1flSGqNenUgujVGvziiXxsgQM8QMscSPXBqjXp1RLo1Ir84ol0bEEDPEDLHkj4lI51uvzn/4YyJiiBlihlhqx0lkZ2U0Pxci+7YyasdJxBAzxAyx1KsT8W3lil6diCFmiBlit9f9/SHQq3NFLo2IIWaIGWKpVyeybyuj+bkQ2beV0VwXIoaYIWaI/QH8GTSs76EUEQAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0x2F5f27B523C8888eA79b7FA80a9CbA6b6980784c', + publicKey: null, + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA0klEQVR4AcXBsW3DQAxA0W9CExjIDhogfboDCw9gICvcHmldcIAMoYLgJJ5CKzgto4KA4ILvXT5+Pl8kwydZqJHt60bl+ryRDZ9koUYmNBOaCc0u31+/L04INSrDJ2cIzYRmQrMl1Dhj+KQSapwhNBOaCc0WDvZ1o+ROZV83KtfnjUxoJjQTmi0c3B/OO+4PpxLKP0IzoZnQbBk+yUKNyvBJJdSoDJ9kQjOhmdBsCTWy4ZNKqFEZPqmEGpnQTGgmNFs4CDWy4ZN3hBoVoZnQTGj2BxvbMvuaMCXUAAAAAElFTkSuQmCC' + } + ], + contractAddressERC20: null, + numberOfERC20: 0, + contractAddressNFT: null, + numberOfNFTTokens: 0, + verificationProof: 'pgp:-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkq+dvCZBm9Bz6DvB6DxYhBPkdSvwnOBuAJaOWAGb0HPoO\n' + + '8HoPAAD5ywf/cvaGM0DzcB22Q2FMzUZG4/ZmkN4OknvSj0d4hB/sPUIb9176\n' + + 'z+niFMjWZNFpIj8s36f16oMEZZ+Eleu9t6sECBxRDvO8pEwyByCXSmz8e/SH\n' + + 'Y659cvg5/A3bSe0FqR0VTI1o+Uz2BpnXG/P38C6D46btaIaJcr4cIh88wQ9J\n' + + 'lr05hOE7w/7Uo5OwyXala0NfB+8S4LIfpC2OlPOhyHQEJd2+WoFKb/6dO28D\n' + + 'TLuvgYJXJfc4R3ElcgFfm1N9ylG0Pt1F3c0C/k9bNokR2PVXgX2XSTQsx1rD\n' + + 'MCY/ePr93INyNZuTPcPlK87X6OTa2/gEW161vup2Xn2Did9HtL76Qw==\n' + + '=EkOP\n' + + '-----END PGP SIGNATURE-----\n' + + ':null', + spaceImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + spaceName: 'intellectual_green_bat', + isPublic: true, + spaceDescription: 'sad_purple_pinniped', + spaceCreator: 'eip155:0xd1ab5Af3Be78bB1492099CE568761F0e706352a0', + spaceId: 'spaces:9dab226c7920fe06154d76f78dfe1187bdc4fda712cdd9a8b37cc6a99741a63b', + scheduleAt: '2023-07-15T14:48:00.000Z', + scheduleEnd: '2023-07-15T15:48:00.000Z', + status: 'PENDING' +} +``` + +
+ +--- + +### **To start a space** + +```typescript +const response = await PushAPI.space.start({ + spaceId: + 'spaces:108f766a5053e2b985d0843e806f741da5ad754d128aff0710e526eebc127afc', + env: 'staging', +}); +``` + +Allowed Options (params with _ are mandatory) +| Param | Type | Default | Remarks | +|----------|---------|---------|--------------------------------------------| +| spaceId_ | string | - | space id | +| env | string | 'prod' | API env - 'prod', 'staging', 'dev'| + +
+ Expected response (start space by space id) + +```typescript +// PushAPI_space_start | Response - 200 OK +{ + members: [ + { + wallet: 'eip155:0xd1ab5Af3Be78bB1492099CE568761F0e706352a0', + publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + 'xsBNBGSr528BCADI8kQcWkaw9PKmSrwCtPBDWj+wzPhmok9jAzxzb2+qAjSV\n' + + 'rYdIrnx6PAp1rMU6qoVg4cdDbCYPV+kCj8l3lUzH/a/SfPsDWpspA/ICWMeS\n' + + 'dMdGYxHLk2gsu0wRz69qoddXMY1h5eMZEyRnr2fsX/cy15mxO2IEHYnC2/rp\n' + + '06iFpx1T8k5HWgFDpyleWyMSQ7Bnn7GutrlHYEVtIGVfXDSkea8IDLLkzBEV\n' + + '3jlBUFhpsrlcvDwDYcMYOrqSBEtg1a+GMK+2Ye/hF37KUYTAPleKXeN0cYIs\n' + + 'Va8oleZK960XYfuy5SYCJav2kaAggNWQBie5G9C4H3h7FuFwWk8LH3DhABEB\n' + + 'AAHNAMLAigQQAQgAPgWCZKvnbwQLCQcICZBm9Bz6DvB6DwMVCAoEFgACAQIZ\n' + + 'AQKbAwIeARYhBPkdSvwnOBuAJaOWAGb0HPoO8HoPAAAkiQgAukm3owebckwr\n' + + 'xAR42r/+CBx1uoqM2ZeEAUeYtBF7sdLEsdxFrxl8wHKAbglZwtgWcfG95v2R\n' + + 'zLcBco3v9p0IuS6DZduIfhngZ49gpYwqFGyiCOvo+k14tuMbrbOZTTKp0uc6\n' + + 'icpTyP8/1U0nZrQmmSXyfh6Hgmx1OnW3zTM7oUN1ZVvj3V6rOl+ktUPjAaYo\n' + + 'CWJjth92xhDWEPZnC/4Gz2eRoTVtmx8u+/2vNPffQVgzzHznUxB+G5XeZmPk\n' + + 'z8oxxSxII8PNiAs5LizqPjyq2gEv25GlCsMXTYz60n/t/4G7Yc94yu8xD8u3\n' + + 'BpWluHC2eW0pYFcDfiNLfv0uJCrUcM7ATQRkq+dvAQgA7v7Zz4CZdPsd4jvB\n' + + 'uDwjop/Gvoz+rbvAdS3Xrsi+OTyrWAqidnXChhwExlUNelZ9v52lGxe1twwr\n' + + 'vxeQ4M0pv4oqSlZxhkqBCyj+E7ECR2WXG7ccLlzYOz3b5BXT+fEkmVsbVTjA\n' + + 'Kttjosm7FtY4igY2Hu4UlZZW8M1tYL1R/UegFeMYGY7aO7dcKeiP0NsDwm3c\n' + + '0SiU6/JlOXAIi/ZSKDJ4b5BPK6GFj5pNWr92/V7LejlZfoHAVDbb91tiPGdP\n' + + 'y3+r9T3IYsgUDLgOpPQn6o82Nctm6CnIZqAN12nJ1DEJP2JyLDedg9b5H+aa\n' + + 'FDZFc7yQ3In/QPtjHImydLt9NwARAQABwsB2BBgBCAAqBYJkq+dvCZBm9Bz6\n' + + 'DvB6DwKbDBYhBPkdSvwnOBuAJaOWAGb0HPoO8HoPAABRUQf+KoF4UXuseLBO\n' + + 'd0PD0+hEcnsYbaPWmPZtJPWusxPl6kt421luymPiThDXwaMVzRrmxkz0dNZ3\n' + + 'bUFYtS24t2BhlXZ6cGFNRjXrA9OV0kLg/kNm1vboQ1GL8qRV9CIjPVEpksQp\n' + + 'tOiYN+X+/2XdPJkaQpITHIFV067qWQSAKIonvOI8OJYOovGRQTInz0VE71Yn\n' + + 'SeiOilKBK+p2RN38jGr0PGWt740KJ6560FzfUwTAQzz9vrkYa+vEhWe+bzOd\n' + + 'YBpxj/BRTGR19DrKlGcFPdTYz5ADxCjBuCxXgoRCbBiWwh+iIstk5qkT8uHK\n' + + 'NQjzDvo3RO1cROQp0zsikladmzGZHQ==\n' + + '=q/e/\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n', + isSpeaker: true, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA10lEQVR4AcXBsWnFMBSG0c8/brOD9kgfogHUGQIuAppInSsVAQ2gdbSD64fTXl4hMI/HPWf5fXxf3DDaxkxIlTuEM+FMOFt5MtqG1XvBipGpsp9YMWaskCqWcCacCWfL4+fzwogx8069FyzhTDgTzpavv3oxEVLlFaNtzAhnwplwtvIkpIpV9hMrxsxM7wUrHxVrtA1LOBPOhLM1pIo12oaVj4rV98JMPj6wRtuwQqpYwplwJpyt3BRjZiZQuUM4E86Es7XsJ1aMTIVUeUXZTyzhTDgTzv4BnGY033BWusUAAAAASUVORK5CYII=' + } + ], + pendingMembers: [ + { + wallet: 'eip155:0xaC6C69c657cF6022fa787B14BDdaA22936B56D65', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA2UlEQVR4AcXBQWoEIRBA0Z+ikOwNDHirbARPKDiLvkzOIATaC4iQbGt6ITSzqPc+np8/fxhpVazzcfCOr99vrK4FS3AmOBOcKRddCy9GwQoxszNHw+rKluBMcCY407QqO10L1hyNO9Kq7AjOBGeCMz0fB9YcjZ20KjtdC1bXghVixhKcCc4EZzpH446uhXfM0bAEZ4IzwZmGmLHmaOyEmNmZo7ETYsYSnAnOBGfKRVoVq2vBmqNxR1oV6+SV4ExwJjhTLroWdkLM7MzRsLoWrMCBJTgTnAnO/gGd1jrTKk/8EAAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0xEf532414907E8c631307c0d501cDe6D1694bAF5e', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA00lEQVR4AcXBobHDMBBF0ZsdjftIDeGuIkzIaGsQC1MNQkZirsLcnaQCk3yqBOzMH4N3zu11f38I+GPiinacRAwxQ8wQS/zo1flSGqNenUgujVGvziiXxsgQM8QMscSPXBqjXp1RLo1Ir84ol0bEEDPEDLHkj4lI51uvzn/4YyJiiBlihlhqx0lkZ2U0Pxci+7YyasdJxBAzxAyx1KsT8W3lil6diCFmiBlit9f9/SHQq3NFLo2IIWaIGWKpVyeybyuj+bkQ2beV0VwXIoaYIWaI/QH8GTSs76EUEQAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0x2F5f27B523C8888eA79b7FA80a9CbA6b6980784c', + publicKey: null, + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA0klEQVR4AcXBsW3DQAxA0W9CExjIDhogfboDCw9gICvcHmldcIAMoYLgJJ5CKzgto4KA4ILvXT5+Pl8kwydZqJHt60bl+ryRDZ9koUYmNBOaCc0u31+/L04INSrDJ2cIzYRmQrMl1Dhj+KQSapwhNBOaCc0WDvZ1o+ROZV83KtfnjUxoJjQTmi0c3B/OO+4PpxLKP0IzoZnQbBk+yUKNyvBJJdSoDJ9kQjOhmdBsCTWy4ZNKqFEZPqmEGpnQTGgmNFs4CDWy4ZN3hBoVoZnQTGj2BxvbMvuaMCXUAAAAAElFTkSuQmCC' + } + ], + contractAddressERC20: null, + numberOfERC20: 0, + contractAddressNFT: null, + numberOfNFTTokens: 0, + verificationProof: 'pgp:-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkq+dvCZBm9Bz6DvB6DxYhBPkdSvwnOBuAJaOWAGb0HPoO\n' + + '8HoPAAD5ywf/cvaGM0DzcB22Q2FMzUZG4/ZmkN4OknvSj0d4hB/sPUIb9176\n' + + 'z+niFMjWZNFpIj8s36f16oMEZZ+Eleu9t6sECBxRDvO8pEwyByCXSmz8e/SH\n' + + 'Y659cvg5/A3bSe0FqR0VTI1o+Uz2BpnXG/P38C6D46btaIaJcr4cIh88wQ9J\n' + + 'lr05hOE7w/7Uo5OwyXala0NfB+8S4LIfpC2OlPOhyHQEJd2+WoFKb/6dO28D\n' + + 'TLuvgYJXJfc4R3ElcgFfm1N9ylG0Pt1F3c0C/k9bNokR2PVXgX2XSTQsx1rD\n' + + 'MCY/ePr93INyNZuTPcPlK87X6OTa2/gEW161vup2Xn2Did9HtL76Qw==\n' + + '=EkOP\n' + + '-----END PGP SIGNATURE-----\n' + + ':null', + spaceImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + spaceName: 'intellectual_green_bat', + isPublic: true, + spaceDescription: 'sad_purple_pinniped', + spaceCreator: 'eip155:0xd1ab5Af3Be78bB1492099CE568761F0e706352a0', + spaceId: 'spaces:9dab226c7920fe06154d76f78dfe1187bdc4fda712cdd9a8b37cc6a99741a63b', + scheduleAt: '2023-07-15T14:48:00.000Z', + scheduleEnd: '2023-07-15T15:48:00.000Z', + status: 'ACTIVE' +} +``` + +
+ +--- + +### **To stop a space** + +```typescript +const response = await PushAPI.space.stop({ + spaceId: + 'spaces:108f766a5053e2b985d0843e806f741da5ad754d128aff0710e526eebc127afc', + env: 'staging', +}); +``` + +Allowed Options (params with _ are mandatory) +| Param | Type | Default | Remarks | +|----------|---------|---------|--------------------------------------------| +| spaceId_ | string | - | space id | +| env | string | 'prod' | API env - 'prod', 'staging', 'dev'| + +
+ Expected response (stop space by space id) + +```typescript +// PushAPI_space_stop | Response - 200 OK +{ + members: [ + { + wallet: 'eip155:0xd1ab5Af3Be78bB1492099CE568761F0e706352a0', + publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + 'xsBNBGSr528BCADI8kQcWkaw9PKmSrwCtPBDWj+wzPhmok9jAzxzb2+qAjSV\n' + + 'rYdIrnx6PAp1rMU6qoVg4cdDbCYPV+kCj8l3lUzH/a/SfPsDWpspA/ICWMeS\n' + + 'dMdGYxHLk2gsu0wRz69qoddXMY1h5eMZEyRnr2fsX/cy15mxO2IEHYnC2/rp\n' + + '06iFpx1T8k5HWgFDpyleWyMSQ7Bnn7GutrlHYEVtIGVfXDSkea8IDLLkzBEV\n' + + '3jlBUFhpsrlcvDwDYcMYOrqSBEtg1a+GMK+2Ye/hF37KUYTAPleKXeN0cYIs\n' + + 'Va8oleZK960XYfuy5SYCJav2kaAggNWQBie5G9C4H3h7FuFwWk8LH3DhABEB\n' + + 'AAHNAMLAigQQAQgAPgWCZKvnbwQLCQcICZBm9Bz6DvB6DwMVCAoEFgACAQIZ\n' + + 'AQKbAwIeARYhBPkdSvwnOBuAJaOWAGb0HPoO8HoPAAAkiQgAukm3owebckwr\n' + + 'xAR42r/+CBx1uoqM2ZeEAUeYtBF7sdLEsdxFrxl8wHKAbglZwtgWcfG95v2R\n' + + 'zLcBco3v9p0IuS6DZduIfhngZ49gpYwqFGyiCOvo+k14tuMbrbOZTTKp0uc6\n' + + 'icpTyP8/1U0nZrQmmSXyfh6Hgmx1OnW3zTM7oUN1ZVvj3V6rOl+ktUPjAaYo\n' + + 'CWJjth92xhDWEPZnC/4Gz2eRoTVtmx8u+/2vNPffQVgzzHznUxB+G5XeZmPk\n' + + 'z8oxxSxII8PNiAs5LizqPjyq2gEv25GlCsMXTYz60n/t/4G7Yc94yu8xD8u3\n' + + 'BpWluHC2eW0pYFcDfiNLfv0uJCrUcM7ATQRkq+dvAQgA7v7Zz4CZdPsd4jvB\n' + + 'uDwjop/Gvoz+rbvAdS3Xrsi+OTyrWAqidnXChhwExlUNelZ9v52lGxe1twwr\n' + + 'vxeQ4M0pv4oqSlZxhkqBCyj+E7ECR2WXG7ccLlzYOz3b5BXT+fEkmVsbVTjA\n' + + 'Kttjosm7FtY4igY2Hu4UlZZW8M1tYL1R/UegFeMYGY7aO7dcKeiP0NsDwm3c\n' + + '0SiU6/JlOXAIi/ZSKDJ4b5BPK6GFj5pNWr92/V7LejlZfoHAVDbb91tiPGdP\n' + + 'y3+r9T3IYsgUDLgOpPQn6o82Nctm6CnIZqAN12nJ1DEJP2JyLDedg9b5H+aa\n' + + 'FDZFc7yQ3In/QPtjHImydLt9NwARAQABwsB2BBgBCAAqBYJkq+dvCZBm9Bz6\n' + + 'DvB6DwKbDBYhBPkdSvwnOBuAJaOWAGb0HPoO8HoPAABRUQf+KoF4UXuseLBO\n' + + 'd0PD0+hEcnsYbaPWmPZtJPWusxPl6kt421luymPiThDXwaMVzRrmxkz0dNZ3\n' + + 'bUFYtS24t2BhlXZ6cGFNRjXrA9OV0kLg/kNm1vboQ1GL8qRV9CIjPVEpksQp\n' + + 'tOiYN+X+/2XdPJkaQpITHIFV067qWQSAKIonvOI8OJYOovGRQTInz0VE71Yn\n' + + 'SeiOilKBK+p2RN38jGr0PGWt740KJ6560FzfUwTAQzz9vrkYa+vEhWe+bzOd\n' + + 'YBpxj/BRTGR19DrKlGcFPdTYz5ADxCjBuCxXgoRCbBiWwh+iIstk5qkT8uHK\n' + + 'NQjzDvo3RO1cROQp0zsikladmzGZHQ==\n' + + '=q/e/\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n', + isSpeaker: true, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA10lEQVR4AcXBsWnFMBSG0c8/brOD9kgfogHUGQIuAppInSsVAQ2gdbSD64fTXl4hMI/HPWf5fXxf3DDaxkxIlTuEM+FMOFt5MtqG1XvBipGpsp9YMWaskCqWcCacCWfL4+fzwogx8069FyzhTDgTzpavv3oxEVLlFaNtzAhnwplwtvIkpIpV9hMrxsxM7wUrHxVrtA1LOBPOhLM1pIo12oaVj4rV98JMPj6wRtuwQqpYwplwJpyt3BRjZiZQuUM4E86Es7XsJ1aMTIVUeUXZTyzhTDgTzv4BnGY033BWusUAAAAASUVORK5CYII=' + } + ], + pendingMembers: [ + { + wallet: 'eip155:0xaC6C69c657cF6022fa787B14BDdaA22936B56D65', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA2UlEQVR4AcXBQWoEIRBA0Z+ikOwNDHirbARPKDiLvkzOIATaC4iQbGt6ITSzqPc+np8/fxhpVazzcfCOr99vrK4FS3AmOBOcKRddCy9GwQoxszNHw+rKluBMcCY407QqO10L1hyNO9Kq7AjOBGeCMz0fB9YcjZ20KjtdC1bXghVixhKcCc4EZzpH446uhXfM0bAEZ4IzwZmGmLHmaOyEmNmZo7ETYsYSnAnOBGfKRVoVq2vBmqNxR1oV6+SV4ExwJjhTLroWdkLM7MzRsLoWrMCBJTgTnAnO/gGd1jrTKk/8EAAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0xEf532414907E8c631307c0d501cDe6D1694bAF5e', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA00lEQVR4AcXBobHDMBBF0ZsdjftIDeGuIkzIaGsQC1MNQkZirsLcnaQCk3yqBOzMH4N3zu11f38I+GPiinacRAwxQ8wQS/zo1flSGqNenUgujVGvziiXxsgQM8QMscSPXBqjXp1RLo1Ir84ol0bEEDPEDLHkj4lI51uvzn/4YyJiiBlihlhqx0lkZ2U0Pxci+7YyasdJxBAzxAyx1KsT8W3lil6diCFmiBlit9f9/SHQq3NFLo2IIWaIGWKpVyeybyuj+bkQ2beV0VwXIoaYIWaI/QH8GTSs76EUEQAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0x2F5f27B523C8888eA79b7FA80a9CbA6b6980784c', + publicKey: null, + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA0klEQVR4AcXBsW3DQAxA0W9CExjIDhogfboDCw9gICvcHmldcIAMoYLgJJ5CKzgto4KA4ILvXT5+Pl8kwydZqJHt60bl+ryRDZ9koUYmNBOaCc0u31+/L04INSrDJ2cIzYRmQrMl1Dhj+KQSapwhNBOaCc0WDvZ1o+ROZV83KtfnjUxoJjQTmi0c3B/OO+4PpxLKP0IzoZnQbBk+yUKNyvBJJdSoDJ9kQjOhmdBsCTWy4ZNKqFEZPqmEGpnQTGgmNFs4CDWy4ZN3hBoVoZnQTGj2BxvbMvuaMCXUAAAAAElFTkSuQmCC' + } + ], + contractAddressERC20: null, + numberOfERC20: 0, + contractAddressNFT: null, + numberOfNFTTokens: 0, + verificationProof: 'pgp:-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkq+dvCZBm9Bz6DvB6DxYhBPkdSvwnOBuAJaOWAGb0HPoO\n' + + '8HoPAAD5ywf/cvaGM0DzcB22Q2FMzUZG4/ZmkN4OknvSj0d4hB/sPUIb9176\n' + + 'z+niFMjWZNFpIj8s36f16oMEZZ+Eleu9t6sECBxRDvO8pEwyByCXSmz8e/SH\n' + + 'Y659cvg5/A3bSe0FqR0VTI1o+Uz2BpnXG/P38C6D46btaIaJcr4cIh88wQ9J\n' + + 'lr05hOE7w/7Uo5OwyXala0NfB+8S4LIfpC2OlPOhyHQEJd2+WoFKb/6dO28D\n' + + 'TLuvgYJXJfc4R3ElcgFfm1N9ylG0Pt1F3c0C/k9bNokR2PVXgX2XSTQsx1rD\n' + + 'MCY/ePr93INyNZuTPcPlK87X6OTa2/gEW161vup2Xn2Did9HtL76Qw==\n' + + '=EkOP\n' + + '-----END PGP SIGNATURE-----\n' + + ':null', + spaceImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + spaceName: 'intellectual_green_bat', + isPublic: true, + spaceDescription: 'sad_purple_pinniped', + spaceCreator: 'eip155:0xd1ab5Af3Be78bB1492099CE568761F0e706352a0', + spaceId: 'spaces:9dab226c7920fe06154d76f78dfe1187bdc4fda712cdd9a8b37cc6a99741a63b', + scheduleAt: '2023-07-15T14:48:00.000Z', + scheduleEnd: '2023-07-15T15:48:00.000Z', + status: 'ENDED' +} +``` + +
+ +--- + +### **To approve a space request** + +```typescript +const response = await PushAPI.space.approve({ + status: 'Approved', + account: '0x18C0Ab0809589c423Ac9eb42897258757b6b3d3d', + senderAddress: '0x873a538254f8162377296326BB3eDDbA7d00F8E9', // spaceId + env: 'staging', +}); +``` + +Allowed Options (params with _ are mandatory) +| Param | Type | Default | Remarks | +|----------|---------|---------|--------------------------------------------| +| status | 'Approved' | 'Approved' | flag for approving and rejecting space request, supports only approving for now| +| senderAddress_ | string | - | space request sender's address or spaceId of a space | +| signer\* | - | - | signer object | +| pgpPrivateKey | string | null | mandatory for users having pgp keys| +| env | string | 'prod' | API env - 'prod', 'staging', 'dev'| + +
+ Expected response (approve space request for a spaceId) + +```typescript +// PushAPI_space_approve | Response - 204 OK +``` + +
+ +--- + + +### **To add listeners to space** + +```typescript +const response = await PushAPI.space.addListeners({ + spaceId, + listeners: [ + `eip155:0x65585D8D2475194A26C0B187e6bED494E5D68d5F`, + `eip155:0xE99F29C1b2A658a478E7766D5A2bB28322326C45`, + ], + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + +``` + +Allowed Options (params with _ are mandatory) +| Param | Type | Default | Remarks | +|----------|---------|---------|--------------------------------------------| +| spaceId_ | string | - | space id | +| listeners | Array | - | new listeners that needs to be added to the space. Don't add listeners which are already part of space | +| env | string | 'prod' | API env - 'prod', 'staging', 'dev'| + +
+ Expected response (add Listeners to space) + +```typescript +// PushAPI_space_add_listeners | Response - 200 OK +{ + members: [{ + wallet: 'eip155:0x4Be8cFD08B330853A530DEBB72a2DAf4d4F3D2Ba', + publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + 'xsBNBGSs51IBCAC+y8oXbU2YvfI7Z4xnSRfcPecRR+nO/XVLDbt30mbn1NU8\n' + + 'wHSXcuHLJTuU9yJy1t9AMB2SY8n/YWMFbeNICF0OQVINkvFS+8Ec/F42IIlb\n' + + 'StUY8rLS9pxTQoI3k1LnQKNL1krGiEuDl2ZT3l304aPGkF1sowu5w6xnzl/o\n' + + 'nb6cgc48jVqIgqoVUCnEoxc3GKdSORm35nl0RBDasFdFPJctnpg2n7hLofU1\n' + + 'RGOIzf/cITY7AE3nta0cqaFgNsO4rO0fXRwgDBAu66CtBG4Px2X8hT7IYMum\n' + + 'XJtCis3KvrmQAOhWrbAwmWjHbkSDSYigd39rmlht21GKf0/kfoILBgRfABEB\n' + + 'AAHNAMLAigQQAQgAPgWCZKznUgQLCQcICZDTsTetOyJa2gMVCAoEFgACAQIZ\n' + + 'AQKbAwIeARYhBHGBWhlF6JChmgQO7tOxN607IlraAADq/Af/XWeAagX5+JCX\n' + + 'ChzadMaUtI6m2F7nT8sJcJep/a0Ldyz6kPmP9k6kmWO+QXJwl4FrP3e7HPer\n' + + 'SjTeIWm0FJ2a+pRtF+lWk7xjIWJuZxbx79nOk98arde75fT+bebne1V0raUM\n' + + 'gXPQIc60++okAPif6vJVLAaSMNbCkv8+Lsy0mJqsjY3b9iMVKWHKb8XVvTuN\n' + + 'pobxVV4dLq53lrdNDIiwAWTlbxyuKLSEF4f+hIPJX3PAhquORinOubclUwTM\n' + + '+kEmE6VI3pW4VL1VRi10cDI6ruEVwqOwQyYcp9gSDKXFR6ZXz7t0hjUUhl+3\n' + + 'z6T7yqAjExW1O4tETVSbt3jg6DjaAM7ATQRkrOdSAQgArRRrLZees3xCYyBO\n' + + '9WDzy7XCM2FxmaIJs/ibWwTtD1ZVoc9NKeOx07FYwGiYjigY6FxxJHdr20IQ\n' + + '3xieIyBLZM2XAIXrsxq4M9GLG8R6nhd35BenjcvSGiZH1Rq0aXtFt9Fd7gc6\n' + + 'E8XpMcHPH8KEnf66sPz18vrVCdstVU4Qj2ZjH25ilfeGdMj2HHfDxVN8sRhl\n' + + 'AXAcwblQ+IVXGjuKw19T4zN874bcAaOmXfzxu3+2PtxVSR5uV03x1ln3ji+b\n' + + '+GF8atJMMHCqE0FC/dEciS+BWSQtv0D93XWjzExJeyhd7Z+I3BG8JPuJT5Yj\n' + + '4PxktEgwUxQc83JFFwED9knzyQARAQABwsB2BBgBCAAqBYJkrOdSCZDTsTet\n' + + 'OyJa2gKbDBYhBHGBWhlF6JChmgQO7tOxN607IlraAABLdggAhe1KLjtHTsUI\n' + + 'SR0K25EJ+9gXC7wmebve9wNZL22/Ud9hnyS77/VUmMNBgdPyhm/9ITMhVtTt\n' + + 'rRNo1AzsVKDn3/dW1kc+nSribOufxzMoBM7Bm918Zt/0/7wCegz0bp3EAoQ8\n' + + 'KEa2KPY9lSh2WtEDoA87D8JB1xwIfcR98vg5/AZ7VdtE88foSqXAm+6F85hz\n' + + 'nAASNBO9CCDvUofR28b4exT/aWX0qZxLAukgH7fnYC3KPVv+9ug6mdyJPsOZ\n' + + 'LFjF327UKLrBuQ6VRlfKF+XULJbtNPxckgwO1V/oxycq/M67acGoXgc2MgP/\n' + + '2qOkbiQC0ZxcA+Ze5TNNhuGWKv6d9g==\n' + + '=S9Ba\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n', + isSpeaker: true, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA1UlEQVR4AcXBQU1FUQxF0f2bZ6gaIOkAC4yxUCRQHyRoqIo6wcJnesLgEgJJ17p9vDzeEe9vd046nZOo4eT59YYylhnLjGW3p8+HOwedzl9EDSfGMmOZsezim05HRQ2q0zmJGlSno6IGZSwzlhnLrk5HRQ2q01FRw0mno6IG1ekoY5mxzFh2RQ2q01FRw29EDarTUVGDMpYZy4xlV6ejogbV6aio4aTTUVGD6nSUscxYZiy7+KbT+U+dzomxzFhmLLv4QdSgnl9vHNWgOp0TY5mxzFj2BfKPPQUA5ipXAAAAAElFTkSuQmCC' + }], + pendingMembers: [{ + wallet: 'eip155:0x4d2eFB18383a48aCe19a198ae5228BB4bf854cec', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA9UlEQVR4AcXBoZHDMBCG0S87ZqEmooaiLmJJsNtwIyFuwzhERZgKmoqkhxz9HaCbmwP73u159w8iN0fVVFC5OT01FVRujqqpoIxgRjAj2JCbo6b1QE3LiDrpeywjF+vBRXOUEcwIZgQb+MW5zaiaCl3NUdN60GMEM4IZwYaaChfNUdN6cNGcnmk9UOc2o2oqKCOYEcwINuTmqJoKF835i3ObUTUVVG6OMoIZwYxgt+fdP4jHMqJe+xuVm9NTU0E9lhH12t8oI5gRzAg28OXcZlTeuKip0JObo06+7AVlBDOCGcFuz7t/6MjN+Y+aCj1GMCOYEewHE5pCbf3G8WQAAAAASUVORK5CYII=' + }, + { + wallet: 'eip155:0x8E50Bfb57f803814c242c5a25890f5F0c13304fF', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA20lEQVR4AcXBsWkDQRCG0W+Gy53pkgVVsiXYFVx2rsANiCtEmQoxbCHmYBNd6gLW6aBgjDDmf89eXr8GiW6VqIxGplslKqORccQcMUdsWued6Ho/k+lW+Yt13okcMUfMEZt4sM470YUb0XYsZC6nG9HKTsYRc8Qcsel6P5PpVnnGdixEZTQyjpgj5ohNPOhWyZTRyHSrRN0qURmNyBFzxBwx+34rg0QZjahbJVNGI+pWyThijpgjNvGLbpWojEamW+UZjpgj5ojZx/vnINiOhf90Od2IHDFHzBH7AWIQNGL6hyehAAAAAElFTkSuQmCC' + }, + { + wallet: 'eip155:0xaA6E4434D881D2bDEea891AE127313AE5515a06B', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAyklEQVR4AcXBsZGDMABE0c8OqQPGZShzCdCCVNZVIhVAYrpQ6g48lMClkgMlBPve9HjtF0bCTJgJszmXykiKgTtyqYwIM2EmzOYUAyO5VO5IMTAizISZMJu/70rrOOmkGLgjl0prXegIM2EmzKbHa79o5FIZSTEwkktlJMVAS5gJM2E282Nd6Dy3QCuXykiKgdb3XRkRZsJMmE375++isS50jpNOioGRXCqtdaFznHSEmTATZjM/nluglUvljucWaOVSaQkzYSbM/gGGCDCC/3c1nwAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0xf6106dd699B6e40f1E822c38DDA459F533470b11', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAwUlEQVR4AcXBsU2DMRSF0S9XHoIFIipmIEW2sPQ6pmGEdJa8BYXXsOgYxKF9afzrr+45l++39uSEUGenrcoZwkyYCbPCgVAna6uyE+pkbVV2hJkwE2Yl1MnaqmT364Ps5/eLnfv1QRZzkIU6mTATZsKscCDm4IXYijk4Q5gJM2FWONDeb7yYbLX3G1nMwY4wE2bCrHAg5iALdbYmpwgzYSbMLh+ff0+MhJkwE2Yl5iALdXbaquyEOjttVTJhJsyE2T84uix63kKmNgAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0xAF3d4989652a6ED5554b6191c555525977424Cc9', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA3UlEQVR4AcXBsW3DMBCG0c8/tEMmUClkBDVaQAWHIKAZWHAGAxyChZDejbOCkcrDOO3ZxQlGENx7p4/t64Gj58JfpFbxiGAimAg2cOB6uWHNy4TnernxDhFMBBPBBl70XHg2YaVW8fRcsOalYKVWsUQwEUwEGziQWsXqueBJrWL1XPCIYCKYCHb6/vl8YKRW+U89FywRTAQTwQZebOOK53zf8Wzjim/CEsFEMBFs4MD5vmP1XPCktmNt44pHBBPBRLAhtYrVc+HZipXajmcbV6x5mbBSq1gimAgmgv0CTksv6eJNDqkAAAAASUVORK5CYII=' + }, + { + wallet: 'eip155:0x2ccBeEf6e30dF46D0A7Ee79Bc66FBF3beA7EeA5A', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA00lEQVR4AcXBIW6AMBiG4XdfmnAYboLlCE3NFBLX4JB40hMsWM4x08OgNvsXUbMs//N8fH59/2DksfCfthqxhDPhTDgLvGw1Yq3nhLWnm571nLD2dNMjnAlnwlnIY8HaasQajplGpWs4ZhqVRh4LlnAmnAln4VkuGinSs54TXcdMz7NcWMKZcCachT3dWHksWM9yYQ3HTM+zXFj5oLGlG0s4E86Es8DLViONFLEyhZ493TQqXcKZcCacCWfCmXAmnAVe8lj4izwWerYasYQz4Uw4+wXktDHpzVVJlwAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0x65585D8D2475194A26C0B187e6bED494E5D68d5F', + publicKey: null, + isSpeaker: false, + image: null + }, + { + wallet: 'eip155:0xE99F29C1b2A658a478E7766D5A2bB28322326C45', + publicKey: null, + isSpeaker: false, + image: null + }, + { + wallet: 'eip155:0xa145b34443e28C8f718Cd0691Dc41A81E0d0A857', + publicKey: null, + isSpeaker: false, + image: null + } + ], + contractAddressERC20: null, + numberOfERC20: 0, + contractAddressNFT: null, + numberOfNFTTokens: 0, + verificationProof: 'pgp:-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkrOdUCZDTsTetOyJa2hYhBHGBWhlF6JChmgQO7tOxN607\n' + + 'IlraAAAqUQf9FvAtNouG7+2YSyyx7eiHRJZroDPFohH/F2xyc+oJkgh40p2y\n' + + 'hyKw+DSp0FA+IiT95/y8RbGDUrNFz+/kdMfZWCEYFim3Cy+c5k1/YNc8qxx6\n' + + 'VLwef+2YZepC1pSS9K0zbu04uVPWrNmDa5lHXqzTx/mOxWlxLD0NfpI60csE\n' + + 'iQx57duy2gMeW9MwOKSFjOSnWHKy7AySm/vBwZ9Rj4gnOhsvwbAfLprQQf4G\n' + + 'cUaxG/HOb0c/8Ugews0Z1uDJFmGKjT5R5CR63vPo5qDGQwWkm+LYpshCIV+K\n' + + 'ofLepDqQRuEFa7VyUlDOvMcF15LtlvAhwhkIVHvTGjXZC91e8/IUsQ==\n' + + '=UpR2\n' + + '-----END PGP SIGNATURE-----\n' + + ':null', + spaceImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + spaceName: 'weird_moccasin_alligator', + isPublic: true, + spaceDescription: 'equivalent_blue_armadillo', + spaceCreator: 'eip155:0x4Be8cFD08B330853A530DEBB72a2DAf4d4F3D2Ba', + spaceId: 'spaces:d37c4e303a2ff194e546d3af94353ec829324a578ebffbeadebd1ba91ab88548', + scheduleAt: '2023-07-15T14:48:00.000Z', + scheduleEnd: '2023-07-15T15:48:00.000Z', + status: 'PENDING' +} +``` + +
+ +--- + +### **To remove listeners from space** + +```typescript +const response = await PushAPI.space.removeListeners({ + spaceId, + listeners: [ + `eip155:0xB12869BD3a0F9109222D67ba71e8b109B46908f9`, + `eip155:0x2E3af36E1aC6EEEA2C0d59E43Be1926aBB9eE0BD`, + ], + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + +``` + +Allowed Options (params with _ are mandatory) +| Param | Type | Default | Remarks | +|----------|---------|---------|--------------------------------------------| +| spaceId_ | string | - | space id | +| listeners | Array | - | existing listeners that needs to be removed from the space. Don't add listeners which are not part of space | +| env | string | 'prod' | API env - 'prod', 'staging', 'dev'| + +
+ Expected response (remove Listeners from space) + +```typescript +// PushAPI_space_from_speakers | Response - 200 OK +{ + members: [{ + wallet: 'eip155:0x5908D89B1390ec5833001b86302B868A808D506D', + publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + 'xsBNBGSs6YABCADC4ldJKGpZ0Z+JJwA1t/1JWp5+dnR98nr7RHPX8eEGxIhL\n' + + 'gtx5TZmek2BcGzNcg66+GEyC4np9USaCZ4/YC9ZMLw8BQKzhOcd3ZILyGtGV\n' + + 'BijBNwjPIbQcy5/cXVtfKCvf303BDYddPYuJ1xFAh7kpvhcR4a72CSpeyEjM\n' + + 'UndteAVTIxqwdpnXIdqpwu6HrSJ089GpHV+XeaDo4Uhg+iHJsCRJy2VJ5m61\n' + + 'CwGx55f3ror6rAXQd+hEx+keLxYINNJLLvfvE9IGsIbKRFZx+emjXQZusbJp\n' + + 'zXYhJnEeHPLVDjWhzo8Q3/4gvOz8m6a+A9sl49sqodLdxVlXQ7d4CuylABEB\n' + + 'AAHNAMLAigQQAQgAPgWCZKzpgAQLCQcICZCaDezdj8j4SwMVCAoEFgACAQIZ\n' + + 'AQKbAwIeARYhBGZpOFBNtTj1Oqt695oN7N2PyPhLAACCLgf/dB412nDRcOxR\n' + + 'dNSj2AYknJ+NKeX38KuksyR6wypnaJWpapmIeZCfFjeoBjuBCPd6unvN/IlZ\n' + + 'zPwl66lO5GKJxDaDd1/infxM/dbtFQSESLXlweRLQ/v1+plsntrBUyvbY4uH\n' + + 'Mh9PImYsLY+zo8P5mpBV5AGAMA6R9qmu3axH/MnKVdB0Ky6C/jP+7lPs/QVT\n' + + 'qsISyyI1E9E6Oivzxmao1axfXLdEvICHb6uD0R4p5SUVqHJX41OwM8BFevhK\n' + + '07Hi+c7NhUWp0sxXEOs6dneJZwerCD3EahutpP1Oyt5T8MZitysn2yJ+s5ks\n' + + 'SZza+x8OmCMcMZfZnIsJNnIUvPboP87ATQRkrOmAAQgAteDgsJJ0ftPD+P15\n' + + 'rKgkLuSCD2iwQgm2k8/ZDaXJBsdm4sJYTt2y0ckx7MRpXgLuIyidOGctqVL6\n' + + '/Rl2Hfl30JQPok5cYmYLENVuFz94MEvgDOo8jacyfPdLGPMWZMLRojyM/Yvs\n' + + 'nhDZ8if3zEstP4h3HcpdT+PWSmsJWjrq57la4vKbfILtKfTBaf8sibm5UuZA\n' + + '5Y/SIPxfVC+ybCPAjo4tpDYP901V+wxXDJ8BlZ4AaVvk20MYMzuAjBna+iwD\n' + + 'f0j4CccEabd2EVtAQQcMCg2yTjOT22Dt0jfpDuohDNaXDhX2ZQlJIdlSLCEI\n' + + 'a3c7g+uU9bnNqt7LHPgMzLYKnwARAQABwsB2BBgBCAAqBYJkrOmACZCaDezd\n' + + 'j8j4SwKbDBYhBGZpOFBNtTj1Oqt695oN7N2PyPhLAAD2vQgAu9+sd4AT5b6c\n' + + 'mWOaQBXz2XVfJXYQFNlBdOF23reycF9r7vDAKSRpeyMSyOfRAi0qdLynQ1dN\n' + + 'MXV/gfO0G9dzFu513P/Y1sZxQi0uLRKL9hMcgEQ8FLo8/PGfVcoLfQASryGj\n' + + 'Z8ybCFqiXocGpt2VkkK4wwgv+ZwZ8M1ubz0Boby6A1/kTYs/6ll+QekpB4ao\n' + + 'kJKw3DWvVNR/xODFfMQcClvzAtqwfxhTZXBMbZ4vAG5m1ExGmA15cGXrAfwV\n' + + 'nR2vOhPYDeZGbBKktM3xfDts75N2NF/TBpvazV2DTKpkLqvVitFHWvSMMpVd\n' + + 'dwk9tEOmBlj2AoYATvQ9kKHRTD27Wg==\n' + + '=IXzf\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n', + isSpeaker: true, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA1klEQVR4AcXBoXHEMBRF0Zs3oqpHNYgJecZdGKYMd5GZRWaCwaohZbiAhP5d8HeC3jkfnz/fvwSTRua+DjJ1nGQ6i0iYCTNhVnjRWUSTRlTHyX90FhlhJsyEWeHFpJG5r4NMHSfRpBF1FpEwE2bCrPDGfR1E29jJPK6DqI6TjDATZsKsTBqZOk6iSa6ORmbSiISZMBNmpbOIHtcXUR0nUWeRmTSi+zqItrETCTNhJswKL7ax82wRTRqZzuLJ2MkIM2EmzApvTBpRZ5GZNKLOIiPMhJkw+wPV2i2sD43hKwAAAABJRU5ErkJggg==' + }], + pendingMembers: [{ + wallet: 'eip155:0xC1469cB7b59d16dC887D4C11faB3E3C0abBeA12C', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA30lEQVR4AcXBsWnFMBSG0e9dBAGDPUs6LeAFNIEb1x5GtRtDei3gBQzZIFtYYEj10t73CkFw8Z/z+Pj+euJs14iXlsodJfd4U7fjGWKGmCEWzjnilUzTsB60nHOk5ZwjniFmiBligTdTt+MlIt52jbRVvKnb8RIRzxAzxAyxx+/nzxMhQ8wQM8RCyT0taancUXJPiyFmiBligTdTt+NNKy/OOdIyrAct2zXiGWKGmCEW0lJ5kUe8tFT+45wjXsk9XloqniFmiBliYVgPvHOOeCX33JGWijesB54hZogZYn8uFTTKoy9pgwAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0xccF7a3131E0E73F83Bc457C27494411a57f23248', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA9ElEQVR4AcXBIWoEMRSA4X8fw6qayBW9zULVEBFygLqcqMwdhlBCbKjqXSLjY7b2UZEVpbzvu3x8vT5QShhoqUa0Yz9ZSTWiHfuJ5rNDE4wJxgRjl8/v9wdKn43/dLve0QRjgjHB2NZnQ7td72h9NrQSBis+O7Tb9Y7WZ0MTjAnGBGMbv/TZ0EoYaD47VkoYaD43VgRjgjHB2MYTqUa0Yz9ZSTWi9dlYEYwJxgRjlzf38kDx2aGVMNBSjawc+4nms0MrYaAJxgRjgrGNJ1KNaH02VlKNaH02VgRjgjHB2OazQythoKXKn5Qw0Hx2aIIxwZhg7Ae2cUcV4Bl8pAAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0x052aD82D3a7b4DAb5b9BcFED771D28703a6faadf', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAy0lEQVR4AcXBoXFDQQxF0RtlkZsQNjHICKYYV7DFCAW6II2BycfbhklCNR/sTNA75+Pn+/MXIUPMEDPEBifhSVdr0oUnO7UmXXjS1Zp0hpghZogZYoaYIWaIDU5qTbrwpHtfnuyEJ12tyY4hZogZYiM86WpNdl7Hg53wL3bCk84QM8QMscFJeNLVmnS3652dOiZdeLJjiBlihtioNenCky486eqY7IQnO7UmnSFmiBliIzzpak262/XOf7wvT7rX8aALTzpDzBAzxP4AMOQyARcWaToAAAAASUVORK5CYII=' + }, + { + wallet: 'eip155:0x956f73E5a3BF0D19299BF74bD6dc819D7f775eC7', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA20lEQVR4AcXBsYnDMBiG4dc/nsHgHeJWS1x7G6QzqNQUKlUHLn12ONdqNYTBS/ja/xqBCeF7nmFbbydODoVPSjXiGWKGmCE2Pu8vvPT45pOe9xeeIWaIGWLj0Xa8HAo9qUZ6cih0tR3PEDPEDLFhW28nTg4FL9XIO3IoeKlGPEPMEDPEhq+f3xNnWmZ6jrbTMy0zPUfb8QwxQ8wQG6dlxjvajpdq5JLKPzkUvGmZ8QwxQ8wQG4+246Ua8XIovCPViJcpeIaYIWaIDdt6O7kgh0JPqpErDDFDzBD7AzabOPmHFg/aAAAAAElFTkSuQmCC' + }, + { + wallet: 'eip155:0x19da526eD1a57E07D48aa25aDa6cbA7E41FF3129', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAyUlEQVR4AcXBsY1CQQxF0cvTFEHuNn4jxB6JJggpw5Mh/UZogmByumBTi2DQahf5nMN2vr1IjvtG1ufgL8Kc7Hm6k4liopgo1i7XB1nsG990uT7IRDFRTBRrfBDmZH0OVsKc3xDFRDFRrPFBn4MszFnpc5CFOSuimCgmih228+1Fctw3vul5upOJYqKYKNaO+0bW5yALc7I+BythTtbnIAtzMlFMFBPFGm/CnP8U5qyIYqKYKNZ40+dgJcxZ6XOwEuZkopgoJor9AIckL2mEiBQrAAAAAElFTkSuQmCC' + }, + { + wallet: 'eip155:0x77059B40Ec974883b98a23eef519b4076D1Cf9F1', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAw0lEQVR4AcXBsY0CMRRF0cuTQ6rYaQFiAvdBYMkFkFEAwWYTryxZ2kIcEE8N1MKmH4JJRuw7Z/d7uD0JRu1EuRW2GLUT5VaIhJkwE2a788/XEyNhJsyEWcqtEI3a+aTcCpEwE2bCLI3aia77E9EyT2xxvDyIvmsnEmbCTJgl3izzRDRqJ8qtsGbUzou58KLeiYSZMBNmKbfCf8qtEAkzYSbM0qidTxq1s0aYCTNhlq77E9EyT2yRW2HN8fIgEmbCTJj9AUPBKWCCQlIAAAAAAElFTkSuQmCC' + } + ], + contractAddressERC20: null, + numberOfERC20: 0, + contractAddressNFT: null, + numberOfNFTTokens: 0, + verificationProof: 'pgp:-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkrOmCCZCaDezdj8j4SxYhBGZpOFBNtTj1Oqt695oN7N2P\n' + + 'yPhLAAD+iwf/dvaRCTwXKGH6iUe49NpyTHMaD6ZwaLerk+K4Ojehbdoo0mDf\n' + + 'aOu/MR8wfqk49h2436rcMmyeM5avcMgmtGUmIdy/6hCZ6zxR/3E5t/vq5UfO\n' + + '3YFO1VLghR5cTYqR9bMLFkvvCB4P29rnaok2QVKTBZLfyAM4wu1h2DDBESoz\n' + + 'SS+ZtQLPz6/y7gOQobO0zbwBPmy8MpVVu1wxht+sneOMvZX+5al679nQbwNL\n' + + 'oCcU3UKrlqMhuFgMTCKx99VLcc4JbhBf2M+IHf78NtQ9mcQC/X+gxRfp6f+p\n' + + '2RePQzkmUH5vqXjzcUsNBWJPOyjl09/IZWWwaeiUjsPazjxqDtYNHg==\n' + + '=H4X4\n' + + '-----END PGP SIGNATURE-----\n' + + ':null', + spaceImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + spaceName: 'sheer_ivory_ox', + isPublic: true, + spaceDescription: 'specific_green_alpaca', + spaceCreator: 'eip155:0x5908D89B1390ec5833001b86302B868A808D506D', + spaceId: 'spaces:bc96011f182e2c86ad68aaf4c95c4a916c808088370cb0ba294f9168e2ff6328', + scheduleAt: '2023-07-15T14:48:00.000Z', + scheduleEnd: '2023-07-15T15:48:00.000Z', + status: 'PENDING' +} +``` + +
+ +--- + + +### **To add speakers to space** + +```typescript +const response = await PushAPI.space.addSpeakers({ + spaceId, + listeners: [ + `eip155:0x65585D8D2475194A26C0B187e6bED494E5D68d5F`, + `eip155:0xE99F29C1b2A658a478E7766D5A2bB28322326C45`, + ], + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + +``` + +Allowed Options (params with _ are mandatory) +| Param | Type | Default | Remarks | +|----------|---------|---------|--------------------------------------------| +| spaceId_ | string | - | space id | +| speakers | Array | - | new speakers that needs to be added to the space. Don't add speakers which are already part of space | +| env | string | 'prod' | API env - 'prod', 'staging', 'dev'| + +
+ Expected response (add Speakers to space) + +```typescript +// PushAPI_space_add_speakers | Response - 200 OK +{ + members: [{ + wallet: 'eip155:0x4Be8cFD08B330853A530DEBB72a2DAf4d4F3D2Ba', + publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + 'xsBNBGSs51IBCAC+y8oXbU2YvfI7Z4xnSRfcPecRR+nO/XVLDbt30mbn1NU8\n' + + 'wHSXcuHLJTuU9yJy1t9AMB2SY8n/YWMFbeNICF0OQVINkvFS+8Ec/F42IIlb\n' + + 'StUY8rLS9pxTQoI3k1LnQKNL1krGiEuDl2ZT3l304aPGkF1sowu5w6xnzl/o\n' + + 'nb6cgc48jVqIgqoVUCnEoxc3GKdSORm35nl0RBDasFdFPJctnpg2n7hLofU1\n' + + 'RGOIzf/cITY7AE3nta0cqaFgNsO4rO0fXRwgDBAu66CtBG4Px2X8hT7IYMum\n' + + 'XJtCis3KvrmQAOhWrbAwmWjHbkSDSYigd39rmlht21GKf0/kfoILBgRfABEB\n' + + 'AAHNAMLAigQQAQgAPgWCZKznUgQLCQcICZDTsTetOyJa2gMVCAoEFgACAQIZ\n' + + 'AQKbAwIeARYhBHGBWhlF6JChmgQO7tOxN607IlraAADq/Af/XWeAagX5+JCX\n' + + 'ChzadMaUtI6m2F7nT8sJcJep/a0Ldyz6kPmP9k6kmWO+QXJwl4FrP3e7HPer\n' + + 'SjTeIWm0FJ2a+pRtF+lWk7xjIWJuZxbx79nOk98arde75fT+bebne1V0raUM\n' + + 'gXPQIc60++okAPif6vJVLAaSMNbCkv8+Lsy0mJqsjY3b9iMVKWHKb8XVvTuN\n' + + 'pobxVV4dLq53lrdNDIiwAWTlbxyuKLSEF4f+hIPJX3PAhquORinOubclUwTM\n' + + '+kEmE6VI3pW4VL1VRi10cDI6ruEVwqOwQyYcp9gSDKXFR6ZXz7t0hjUUhl+3\n' + + 'z6T7yqAjExW1O4tETVSbt3jg6DjaAM7ATQRkrOdSAQgArRRrLZees3xCYyBO\n' + + '9WDzy7XCM2FxmaIJs/ibWwTtD1ZVoc9NKeOx07FYwGiYjigY6FxxJHdr20IQ\n' + + '3xieIyBLZM2XAIXrsxq4M9GLG8R6nhd35BenjcvSGiZH1Rq0aXtFt9Fd7gc6\n' + + 'E8XpMcHPH8KEnf66sPz18vrVCdstVU4Qj2ZjH25ilfeGdMj2HHfDxVN8sRhl\n' + + 'AXAcwblQ+IVXGjuKw19T4zN874bcAaOmXfzxu3+2PtxVSR5uV03x1ln3ji+b\n' + + '+GF8atJMMHCqE0FC/dEciS+BWSQtv0D93XWjzExJeyhd7Z+I3BG8JPuJT5Yj\n' + + '4PxktEgwUxQc83JFFwED9knzyQARAQABwsB2BBgBCAAqBYJkrOdSCZDTsTet\n' + + 'OyJa2gKbDBYhBHGBWhlF6JChmgQO7tOxN607IlraAABLdggAhe1KLjtHTsUI\n' + + 'SR0K25EJ+9gXC7wmebve9wNZL22/Ud9hnyS77/VUmMNBgdPyhm/9ITMhVtTt\n' + + 'rRNo1AzsVKDn3/dW1kc+nSribOufxzMoBM7Bm918Zt/0/7wCegz0bp3EAoQ8\n' + + 'KEa2KPY9lSh2WtEDoA87D8JB1xwIfcR98vg5/AZ7VdtE88foSqXAm+6F85hz\n' + + 'nAASNBO9CCDvUofR28b4exT/aWX0qZxLAukgH7fnYC3KPVv+9ug6mdyJPsOZ\n' + + 'LFjF327UKLrBuQ6VRlfKF+XULJbtNPxckgwO1V/oxycq/M67acGoXgc2MgP/\n' + + '2qOkbiQC0ZxcA+Ze5TNNhuGWKv6d9g==\n' + + '=S9Ba\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n', + isSpeaker: true, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA1UlEQVR4AcXBQU1FUQxF0f2bZ6gaIOkAC4yxUCRQHyRoqIo6wcJnesLgEgJJ17p9vDzeEe9vd046nZOo4eT59YYylhnLjGW3p8+HOwedzl9EDSfGMmOZsezim05HRQ2q0zmJGlSno6IGZSwzlhnLrk5HRQ2q01FRw0mno6IG1ekoY5mxzFh2RQ2q01FRw29EDarTUVGDMpYZy4xlV6ejogbV6aio4aTTUVGD6nSUscxYZiy7+KbT+U+dzomxzFhmLLv4QdSgnl9vHNWgOp0TY5mxzFj2BfKPPQUA5ipXAAAAAElFTkSuQmCC' + }], + pendingMembers: [{ + wallet: 'eip155:0x4d2eFB18383a48aCe19a198ae5228BB4bf854cec', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA9UlEQVR4AcXBoZHDMBCG0S87ZqEmooaiLmJJsNtwIyFuwzhERZgKmoqkhxz9HaCbmwP73u159w8iN0fVVFC5OT01FVRujqqpoIxgRjAj2JCbo6b1QE3LiDrpeywjF+vBRXOUEcwIZgQb+MW5zaiaCl3NUdN60GMEM4IZwYaaChfNUdN6cNGcnmk9UOc2o2oqKCOYEcwINuTmqJoKF835i3ObUTUVVG6OMoIZwYxgt+fdP4jHMqJe+xuVm9NTU0E9lhH12t8oI5gRzAg28OXcZlTeuKip0JObo06+7AVlBDOCGcFuz7t/6MjN+Y+aCj1GMCOYEewHE5pCbf3G8WQAAAAASUVORK5CYII=' + }, + { + wallet: 'eip155:0x8E50Bfb57f803814c242c5a25890f5F0c13304fF', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA20lEQVR4AcXBsWkDQRCG0W+Gy53pkgVVsiXYFVx2rsANiCtEmQoxbCHmYBNd6gLW6aBgjDDmf89eXr8GiW6VqIxGplslKqORccQcMUdsWued6Ho/k+lW+Yt13okcMUfMEZt4sM470YUb0XYsZC6nG9HKTsYRc8Qcsel6P5PpVnnGdixEZTQyjpgj5ohNPOhWyZTRyHSrRN0qURmNyBFzxBwx+34rg0QZjahbJVNGI+pWyThijpgjNvGLbpWojEamW+UZjpgj5ojZx/vnINiOhf90Od2IHDFHzBH7AWIQNGL6hyehAAAAAElFTkSuQmCC' + }, + { + wallet: 'eip155:0xaA6E4434D881D2bDEea891AE127313AE5515a06B', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAyklEQVR4AcXBsZGDMABE0c8OqQPGZShzCdCCVNZVIhVAYrpQ6g48lMClkgMlBPve9HjtF0bCTJgJszmXykiKgTtyqYwIM2EmzOYUAyO5VO5IMTAizISZMJu/70rrOOmkGLgjl0prXegIM2EmzKbHa79o5FIZSTEwkktlJMVAS5gJM2E282Nd6Dy3QCuXykiKgdb3XRkRZsJMmE375++isS50jpNOioGRXCqtdaFznHSEmTATZjM/nluglUvljucWaOVSaQkzYSbM/gGGCDCC/3c1nwAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0xf6106dd699B6e40f1E822c38DDA459F533470b11', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAwUlEQVR4AcXBsU2DMRSF0S9XHoIFIipmIEW2sPQ6pmGEdJa8BYXXsOgYxKF9afzrr+45l++39uSEUGenrcoZwkyYCbPCgVAna6uyE+pkbVV2hJkwE2Yl1MnaqmT364Ps5/eLnfv1QRZzkIU6mTATZsKscCDm4IXYijk4Q5gJM2FWONDeb7yYbLX3G1nMwY4wE2bCrHAg5iALdbYmpwgzYSbMLh+ff0+MhJkwE2Yl5iALdXbaquyEOjttVTJhJsyE2T84uix63kKmNgAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0xAF3d4989652a6ED5554b6191c555525977424Cc9', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA3UlEQVR4AcXBsW3DMBCG0c8/tEMmUClkBDVaQAWHIKAZWHAGAxyChZDejbOCkcrDOO3ZxQlGENx7p4/t64Gj58JfpFbxiGAimAg2cOB6uWHNy4TnernxDhFMBBPBBl70XHg2YaVW8fRcsOalYKVWsUQwEUwEGziQWsXqueBJrWL1XPCIYCKYCHb6/vl8YKRW+U89FywRTAQTwQZebOOK53zf8Wzjim/CEsFEMBFs4MD5vmP1XPCktmNt44pHBBPBRLAhtYrVc+HZipXajmcbV6x5mbBSq1gimAgmgv0CTksv6eJNDqkAAAAASUVORK5CYII=' + }, + { + wallet: 'eip155:0x2ccBeEf6e30dF46D0A7Ee79Bc66FBF3beA7EeA5A', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA00lEQVR4AcXBIW6AMBiG4XdfmnAYboLlCE3NFBLX4JB40hMsWM4x08OgNvsXUbMs//N8fH59/2DksfCfthqxhDPhTDgLvGw1Yq3nhLWnm571nLD2dNMjnAlnwlnIY8HaasQajplGpWs4ZhqVRh4LlnAmnAln4VkuGinSs54TXcdMz7NcWMKZcCachT3dWHksWM9yYQ3HTM+zXFj5oLGlG0s4E86Es8DLViONFLEyhZ493TQqXcKZcCacCWfCmXAmnAVe8lj4izwWerYasYQz4Uw4+wXktDHpzVVJlwAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0x65585D8D2475194A26C0B187e6bED494E5D68d5F', + publicKey: null, + isSpeaker: true, + image: null + }, + { + wallet: 'eip155:0xE99F29C1b2A658a478E7766D5A2bB28322326C45', + publicKey: null, + isSpeaker: true, + image: null + }, + { + wallet: 'eip155:0xa145b34443e28C8f718Cd0691Dc41A81E0d0A857', + publicKey: null, + isSpeaker: false, + image: null + } + ], + contractAddressERC20: null, + numberOfERC20: 0, + contractAddressNFT: null, + numberOfNFTTokens: 0, + verificationProof: 'pgp:-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkrOdUCZDTsTetOyJa2hYhBHGBWhlF6JChmgQO7tOxN607\n' + + 'IlraAAAqUQf9FvAtNouG7+2YSyyx7eiHRJZroDPFohH/F2xyc+oJkgh40p2y\n' + + 'hyKw+DSp0FA+IiT95/y8RbGDUrNFz+/kdMfZWCEYFim3Cy+c5k1/YNc8qxx6\n' + + 'VLwef+2YZepC1pSS9K0zbu04uVPWrNmDa5lHXqzTx/mOxWlxLD0NfpI60csE\n' + + 'iQx57duy2gMeW9MwOKSFjOSnWHKy7AySm/vBwZ9Rj4gnOhsvwbAfLprQQf4G\n' + + 'cUaxG/HOb0c/8Ugews0Z1uDJFmGKjT5R5CR63vPo5qDGQwWkm+LYpshCIV+K\n' + + 'ofLepDqQRuEFa7VyUlDOvMcF15LtlvAhwhkIVHvTGjXZC91e8/IUsQ==\n' + + '=UpR2\n' + + '-----END PGP SIGNATURE-----\n' + + ':null', + spaceImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + spaceName: 'weird_moccasin_alligator', + isPublic: true, + spaceDescription: 'equivalent_blue_armadillo', + spaceCreator: 'eip155:0x4Be8cFD08B330853A530DEBB72a2DAf4d4F3D2Ba', + spaceId: 'spaces:d37c4e303a2ff194e546d3af94353ec829324a578ebffbeadebd1ba91ab88548', + scheduleAt: '2023-07-15T14:48:00.000Z', + scheduleEnd: '2023-07-15T15:48:00.000Z', + status: 'PENDING' +} +``` + +
+ +--- + + +### **To remove speakers from space** + +```typescript +const response = await PushAPI.space.removeSpeakers({ + spaceId, + speakers: [ + `eip155:0xB12869BD3a0F9109222D67ba71e8b109B46908f9`, + `eip155:0x2E3af36E1aC6EEEA2C0d59E43Be1926aBB9eE0BD`, + ], + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + +``` + +Allowed Options (params with _ are mandatory) +| Param | Type | Default | Remarks | +|----------|---------|---------|--------------------------------------------| +| spaceId_ | string | - | space id | +| speakers | Array | - | existing speakers that needs to be removed from the space. Don't add speakers which are not part of space | +| env | string | 'prod' | API env - 'prod', 'staging', 'dev'| + +
+ Expected response (remove Speakers to space) + +```typescript +// PushAPI_space_remove_speakers | Response - 200 OK +{ + members: [{ + wallet: 'eip155:0x5908D89B1390ec5833001b86302B868A808D506D', + publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + 'xsBNBGSs6YABCADC4ldJKGpZ0Z+JJwA1t/1JWp5+dnR98nr7RHPX8eEGxIhL\n' + + 'gtx5TZmek2BcGzNcg66+GEyC4np9USaCZ4/YC9ZMLw8BQKzhOcd3ZILyGtGV\n' + + 'BijBNwjPIbQcy5/cXVtfKCvf303BDYddPYuJ1xFAh7kpvhcR4a72CSpeyEjM\n' + + 'UndteAVTIxqwdpnXIdqpwu6HrSJ089GpHV+XeaDo4Uhg+iHJsCRJy2VJ5m61\n' + + 'CwGx55f3ror6rAXQd+hEx+keLxYINNJLLvfvE9IGsIbKRFZx+emjXQZusbJp\n' + + 'zXYhJnEeHPLVDjWhzo8Q3/4gvOz8m6a+A9sl49sqodLdxVlXQ7d4CuylABEB\n' + + 'AAHNAMLAigQQAQgAPgWCZKzpgAQLCQcICZCaDezdj8j4SwMVCAoEFgACAQIZ\n' + + 'AQKbAwIeARYhBGZpOFBNtTj1Oqt695oN7N2PyPhLAACCLgf/dB412nDRcOxR\n' + + 'dNSj2AYknJ+NKeX38KuksyR6wypnaJWpapmIeZCfFjeoBjuBCPd6unvN/IlZ\n' + + 'zPwl66lO5GKJxDaDd1/infxM/dbtFQSESLXlweRLQ/v1+plsntrBUyvbY4uH\n' + + 'Mh9PImYsLY+zo8P5mpBV5AGAMA6R9qmu3axH/MnKVdB0Ky6C/jP+7lPs/QVT\n' + + 'qsISyyI1E9E6Oivzxmao1axfXLdEvICHb6uD0R4p5SUVqHJX41OwM8BFevhK\n' + + '07Hi+c7NhUWp0sxXEOs6dneJZwerCD3EahutpP1Oyt5T8MZitysn2yJ+s5ks\n' + + 'SZza+x8OmCMcMZfZnIsJNnIUvPboP87ATQRkrOmAAQgAteDgsJJ0ftPD+P15\n' + + 'rKgkLuSCD2iwQgm2k8/ZDaXJBsdm4sJYTt2y0ckx7MRpXgLuIyidOGctqVL6\n' + + '/Rl2Hfl30JQPok5cYmYLENVuFz94MEvgDOo8jacyfPdLGPMWZMLRojyM/Yvs\n' + + 'nhDZ8if3zEstP4h3HcpdT+PWSmsJWjrq57la4vKbfILtKfTBaf8sibm5UuZA\n' + + '5Y/SIPxfVC+ybCPAjo4tpDYP901V+wxXDJ8BlZ4AaVvk20MYMzuAjBna+iwD\n' + + 'f0j4CccEabd2EVtAQQcMCg2yTjOT22Dt0jfpDuohDNaXDhX2ZQlJIdlSLCEI\n' + + 'a3c7g+uU9bnNqt7LHPgMzLYKnwARAQABwsB2BBgBCAAqBYJkrOmACZCaDezd\n' + + 'j8j4SwKbDBYhBGZpOFBNtTj1Oqt695oN7N2PyPhLAAD2vQgAu9+sd4AT5b6c\n' + + 'mWOaQBXz2XVfJXYQFNlBdOF23reycF9r7vDAKSRpeyMSyOfRAi0qdLynQ1dN\n' + + 'MXV/gfO0G9dzFu513P/Y1sZxQi0uLRKL9hMcgEQ8FLo8/PGfVcoLfQASryGj\n' + + 'Z8ybCFqiXocGpt2VkkK4wwgv+ZwZ8M1ubz0Boby6A1/kTYs/6ll+QekpB4ao\n' + + 'kJKw3DWvVNR/xODFfMQcClvzAtqwfxhTZXBMbZ4vAG5m1ExGmA15cGXrAfwV\n' + + 'nR2vOhPYDeZGbBKktM3xfDts75N2NF/TBpvazV2DTKpkLqvVitFHWvSMMpVd\n' + + 'dwk9tEOmBlj2AoYATvQ9kKHRTD27Wg==\n' + + '=IXzf\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n', + isSpeaker: true, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA1klEQVR4AcXBoXHEMBRF0Zs3oqpHNYgJecZdGKYMd5GZRWaCwaohZbiAhP5d8HeC3jkfnz/fvwSTRua+DjJ1nGQ6i0iYCTNhVnjRWUSTRlTHyX90FhlhJsyEWeHFpJG5r4NMHSfRpBF1FpEwE2bCrPDGfR1E29jJPK6DqI6TjDATZsKsTBqZOk6iSa6ORmbSiISZMBNmpbOIHtcXUR0nUWeRmTSi+zqItrETCTNhJswKL7ax82wRTRqZzuLJ2MkIM2EmzApvTBpRZ5GZNKLOIiPMhJkw+wPV2i2sD43hKwAAAABJRU5ErkJggg==' + }], + pendingMembers: [{ + wallet: 'eip155:0xC1469cB7b59d16dC887D4C11faB3E3C0abBeA12C', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA30lEQVR4AcXBsWnFMBSG0e9dBAGDPUs6LeAFNIEb1x5GtRtDei3gBQzZIFtYYEj10t73CkFw8Z/z+Pj+euJs14iXlsodJfd4U7fjGWKGmCEWzjnilUzTsB60nHOk5ZwjniFmiBligTdTt+MlIt52jbRVvKnb8RIRzxAzxAyxx+/nzxMhQ8wQM8RCyT0taancUXJPiyFmiBligTdTt+NNKy/OOdIyrAct2zXiGWKGmCEW0lJ5kUe8tFT+45wjXsk9XloqniFmiBliYVgPvHOOeCX33JGWijesB54hZogZYn8uFTTKoy9pgwAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0xccF7a3131E0E73F83Bc457C27494411a57f23248', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA9ElEQVR4AcXBIWoEMRSA4X8fw6qayBW9zULVEBFygLqcqMwdhlBCbKjqXSLjY7b2UZEVpbzvu3x8vT5QShhoqUa0Yz9ZSTWiHfuJ5rNDE4wJxgRjl8/v9wdKn43/dLve0QRjgjHB2NZnQ7td72h9NrQSBis+O7Tb9Y7WZ0MTjAnGBGMbv/TZ0EoYaD47VkoYaD43VgRjgjHB2MYTqUa0Yz9ZSTWi9dlYEYwJxgRjlzf38kDx2aGVMNBSjawc+4nms0MrYaAJxgRjgrGNJ1KNaH02VlKNaH02VgRjgjHB2OazQythoKXKn5Qw0Hx2aIIxwZhg7Ae2cUcV4Bl8pAAAAABJRU5ErkJggg==' + }, + { + wallet: 'eip155:0x052aD82D3a7b4DAb5b9BcFED771D28703a6faadf', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAy0lEQVR4AcXBoXFDQQxF0RtlkZsQNjHICKYYV7DFCAW6II2BycfbhklCNR/sTNA75+Pn+/MXIUPMEDPEBifhSVdr0oUnO7UmXXjS1Zp0hpghZogZYoaYIWaIDU5qTbrwpHtfnuyEJ12tyY4hZogZYiM86WpNdl7Hg53wL3bCk84QM8QMscFJeNLVmnS3652dOiZdeLJjiBlihtioNenCky486eqY7IQnO7UmnSFmiBliIzzpak262/XOf7wvT7rX8aALTzpDzBAzxP4AMOQyARcWaToAAAAASUVORK5CYII=' + }, + { + wallet: 'eip155:0x956f73E5a3BF0D19299BF74bD6dc819D7f775eC7', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA20lEQVR4AcXBsYnDMBiG4dc/nsHgHeJWS1x7G6QzqNQUKlUHLn12ONdqNYTBS/ja/xqBCeF7nmFbbydODoVPSjXiGWKGmCE2Pu8vvPT45pOe9xeeIWaIGWLj0Xa8HAo9qUZ6cih0tR3PEDPEDLFhW28nTg4FL9XIO3IoeKlGPEPMEDPEhq+f3xNnWmZ6jrbTMy0zPUfb8QwxQ8wQG6dlxjvajpdq5JLKPzkUvGmZ8QwxQ8wQG4+246Ua8XIovCPViJcpeIaYIWaIDdt6O7kgh0JPqpErDDFDzBD7AzabOPmHFg/aAAAAAElFTkSuQmCC' + }, + { + wallet: 'eip155:0x19da526eD1a57E07D48aa25aDa6cbA7E41FF3129', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAyUlEQVR4AcXBsY1CQQxF0cvTFEHuNn4jxB6JJggpw5Mh/UZogmByumBTi2DQahf5nMN2vr1IjvtG1ufgL8Kc7Hm6k4liopgo1i7XB1nsG990uT7IRDFRTBRrfBDmZH0OVsKc3xDFRDFRrPFBn4MszFnpc5CFOSuimCgmih228+1Fctw3vul5upOJYqKYKNaO+0bW5yALc7I+BythTtbnIAtzMlFMFBPFGm/CnP8U5qyIYqKYKNZ40+dgJcxZ6XOwEuZkopgoJor9AIckL2mEiBQrAAAAAElFTkSuQmCC' + }, + { + wallet: 'eip155:0x77059B40Ec974883b98a23eef519b4076D1Cf9F1', + publicKey: '', + isSpeaker: false, + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAw0lEQVR4AcXBsY0CMRRF0cuTQ6rYaQFiAvdBYMkFkFEAwWYTryxZ2kIcEE8N1MKmH4JJRuw7Z/d7uD0JRu1EuRW2GLUT5VaIhJkwE2a788/XEyNhJsyEWcqtEI3a+aTcCpEwE2bCLI3aia77E9EyT2xxvDyIvmsnEmbCTJgl3izzRDRqJ8qtsGbUzou58KLeiYSZMBNmKbfCf8qtEAkzYSbM0qidTxq1s0aYCTNhlq77E9EyT2yRW2HN8fIgEmbCTJj9AUPBKWCCQlIAAAAAAElFTkSuQmCC' + } + ], + contractAddressERC20: null, + numberOfERC20: 0, + contractAddressNFT: null, + numberOfNFTTokens: 0, + verificationProof: 'pgp:-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkrOmCCZCaDezdj8j4SxYhBGZpOFBNtTj1Oqt695oN7N2P\n' + + 'yPhLAAD+iwf/dvaRCTwXKGH6iUe49NpyTHMaD6ZwaLerk+K4Ojehbdoo0mDf\n' + + 'aOu/MR8wfqk49h2436rcMmyeM5avcMgmtGUmIdy/6hCZ6zxR/3E5t/vq5UfO\n' + + '3YFO1VLghR5cTYqR9bMLFkvvCB4P29rnaok2QVKTBZLfyAM4wu1h2DDBESoz\n' + + 'SS+ZtQLPz6/y7gOQobO0zbwBPmy8MpVVu1wxht+sneOMvZX+5al679nQbwNL\n' + + 'oCcU3UKrlqMhuFgMTCKx99VLcc4JbhBf2M+IHf78NtQ9mcQC/X+gxRfp6f+p\n' + + '2RePQzkmUH5vqXjzcUsNBWJPOyjl09/IZWWwaeiUjsPazjxqDtYNHg==\n' + + '=H4X4\n' + + '-----END PGP SIGNATURE-----\n' + + ':null', + spaceImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + spaceName: 'sheer_ivory_ox', + isPublic: true, + spaceDescription: 'specific_green_alpaca', + spaceCreator: 'eip155:0x5908D89B1390ec5833001b86302B868A808D506D', + spaceId: 'spaces:bc96011f182e2c86ad68aaf4c95c4a916c808088370cb0ba294f9168e2ff6328', + scheduleAt: '2023-07-15T14:48:00.000Z', + scheduleEnd: '2023-07-15T15:48:00.000Z', + status: 'PENDING' +} +``` + +
+ +--- + +### **Fetching list of user spaces** + +```typescript +const spaces = await PushAPI.space.spaces({ + account: string; + pgpPrivateKey?: string; + /** + * If true, the method will return decrypted message content in response + */ + toDecrypt?: boolean; + /** + * Environment variable + */ + env?: ENV; +}); +``` + +| Param | Type | Default | Remarks | +| ------------- | ------- | ------- | ---------------------------------------------------------------------- | +| account | string | - | user address (Partial CAIP) | +| toDecrypt | boolean | false | if "true" the method will return decrypted message content in response | +| pgpPrivateKey | string | null | mandatory for users having pgp keys | +| env | string | 'prod' | API env - 'prod', 'staging', 'dev' | + +**Example normal user:** + +```typescript +// pre-requisite API calls that should be made before +// need to get user and through that encryptedPvtKey of the user +const user = await PushAPI.user.get({ + account: 'eip155:0xFe6C8E9e25f7bcF374412c5C81B2578aC473C0F7', + env: ENV.STAGING, +}) + +// need to decrypt the encryptedPvtKey to pass in the api using helper function +const pgpDecryptedPvtKey = await PushAPI.chat.decryptPGPKey(encryptedPGPPrivateKey: user.encryptedPrivateKey, signer: signer); + +// actual api +const spaces = await PushAPI.space.spaces({ + account: 'eip155:0xFe6C8E9e25f7bcF374412c5C81B2578aC473C0F7', + toDecrypt: true, + pgpPrivateKey: pgpDecryptedPvtKey, + env: ENV.STAGING, +}); +``` + +**Example NFT user:** + +```typescript +// Fetch user +const user = await PushAPI.user.get({ + account: `nft:eip155:${nftChainId}:${nftContractAddress}:${nftTokenId}`, + env: env as ENV, +}); + +// Decrypt PGP Key +const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + signer: nftSigner, +}); + +// Actual api +const spaces = await PushAPI.space.spaces({ + account: `nft:eip155:${nftChainId}:${nftContractAddress}:${nftTokenId}`, + toDecrypt: true, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, +}); +``` + +
+ Expected response (Get spaces of a specific user) + +```typescript +// PushAPI_space_spaces | Response - 200 OK +// Array of spaces +[ + + { + spaceId: 'spaces:3aa43087b8c55ed9c534dd1d0a086a3340b0d829cda0a13592651cb59f284838', + about: null, + did: null, + intent: 'eip155:0xf4c946D6bd5cF09713D27364bbEd42712Bdffa8A+eip155:0xF8aBe92d1d0706bF60509F8E9A64Ed6b8520E868', + intentSentBy: 'eip155:0xf4c946D6bd5cF09713D27364bbEd42712Bdffa8A', + intentTimestamp: '2023-07-12T01:11:32.000Z', + publicKey: null, + profilePicture: null, + threadhash: null, + wallets: null, + combinedDID: 'eip155:0x12E429E3672a02E385F9f5F75E932cC1D566EEea_eip155:0x49D407CC9D0e966CD9B22BA40685083B49bd2315_eip155:0xF8aBe92d1d0706bF60509F8E9A64Ed6b8520E868_eip155:0xf4c946D6bd5cF09713D27364bbEd42712Bdffa8A', + name: null, + spaceInformation: { + members: [Array], + pendingMembers: [Array], + contractAddressERC20: null, + numberOfERC20: 0, + contractAddressNFT: null, + numberOfNFTTokens: 0, + verificationProof: 'pgp:-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkrksbCZA3GHnYNke0AhYhBNp+D95LDfs4yU03LzcYedg2\n' + + 'R7QCAACRdAf9ELAnCLXfBiAVdbgwj81xr+w9Yzw2wXLLrPLfYY7EXfyChLzQ\n' + + 'rr9XBDdWMgtzEU1diSPMbLDh1METR7n71EjG0AoeX5A2pkHI7R1vIxXUJR3G\n' + + 'fzHENsfGaKLnhrL1wLjBQACzEsIqPrHl9RItdtKEs9izLmc+wV0GFJ5OjbAs\n' + + 'ty/1Q36nnMB7sQ7Ytb9Op+q0TtZPZ7jF9CjX8KGav3P1xDQex9nfsXiDHlLK\n' + + 'MqDePaaMO6RJUWAP2xTo2k1DDJQ2dpUhs9XyjMlvFhVbIcT1/lVRCPC8V3C8\n' + + 'fUKhUejvOjNFxf0QuR+E4xs+Q3zvR1+fXdJBxbH2Fp3kOTN1N9/LEw==\n' + + '=sLLC\n' + + '-----END PGP SIGNATURE-----\n', + spaceImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + spaceName: 'statutory_amber_roadrunner', + isPublic: true, + spaceDescription: 'continued_bronze_pigeon', + spaceCreator: 'eip155:0xf4c946D6bd5cF09713D27364bbEd42712Bdffa8A', + spaceId: 'spaces:3aa43087b8c55ed9c534dd1d0a086a3340b0d829cda0a13592651cb59f284838', + scheduleAt: '2023-07-12T06:51:32.000Z', + scheduleEnd: '2023-07-12T07:41:32.000Z', + status: 'PENDING' + }, + msg: { + fromCAIP10: 'eip155:0x1615d2D9ae82D5F0eE79298899962b237386feB7', + toCAIP10: 'eip155:0x1C48fE875590f8e366447758b13982a3Ca7d9dBE', + fromDID: 'eip155:0x1615d2D9ae82D5F0eE79298899962b237386feB7', + toDID: 'eip155:0x1C48fE875590f8e366447758b13982a3Ca7d9dBE', + messageContent: "Gm gm! It's me... Mario", + messageType: 'Text', + signature: + '-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkWKQWCZB7dzg7q3axjBYhBJFuYslzDGbuE+3FMnt3ODur\n' + + 'drGMAAAjtAf/TXjtm2qb6aSikFPKYXm0Ekws+65fisJGf7T48MYkkfcD4t2e\n' + + 'HXd9LtohzGhcztbOQfAND3yME1GWuMBIksq9rlyEA0ezwsGzCJVhBnkAHBe3\n' + + '+1v4/mNSMmInU8y6sOiLiOcW7ameJvZvDdPDJ0YHhc9dKDCIh1UAZEPAgx+z\n' + + 'Wc0DM6pW8bT70dfgnuW2LlLGF5Z23Z1vbHmeszt78+xYY3ez/hoMHXUIE25z\n' + + 'Wrnt75nasBBahtJ0mwH10ATnsQNE9hTi6XPGYxRSNDM9nyRxTQUpjhNmGS/+\n' + + '7oFyq8xTcRSaL7d3h8URp9hgFWher5ZZDyMV0jvk+HPguUX54g6Kgw==\n' + + '=dcRD\n' + + '-----END PGP SIGNATURE-----\n', + timestamp: 1683530775648, + sigType: 'pgp', + encType: 'pgp', + encryptedSecret: + '-----BEGIN PGP MESSAGE-----\n' + + '\n' + + 'wcBMA9aU+JGZVRn/AQgA1pIJHyeJinU21r6At5S5ZaWeN0OEKVB2TjpqZ0IW\n' + + 'lHLKQrQ8k3M16bN+Vf0P+DzDVOL84QRkBD56qSNVHOOCox5wcQeR01CczenV\n' + + 'LUVvVjBzR2hj7Sdw+Q+M//rgeZPPUDbNyiVmGijelhwDqWd7IOoZY26AGXlm\n' + + '7YQiElvHN2HcYXaTlLAOy36BcccwHu3Tn06F77ZXaf8FnGMWOUy7wh1/jugg\n' + + 'D17jUZGLYbmw+u5l9BOfljbw2pb4vtjWht0I1b4GYlKb+bYg/NY0UNsq7mSh\n' + + 'dGAmOhy5tC2NMjLRRLfD2qasxHoHN50onlB6HcYLl0RCf31ebOgO6rMhUnxt\n' + + '9cHATAMLWLG2xubrYAEH/2tVeq2j7nJALGSFxjJPboOY57aiFrhXNQ/e/oXH\n' + + '//TNJgGWx4Ta++OuF2Oexbh9DIZhl6DWld9adXDDtBS/fEyjNsYqwoYlNEJN\n' + + 'kLvSmokNNrE4MKC1A0GkhSh2MGQDNk42GSgz1tep8XSVc98MHqfNXCHVb5Oa\n' + + 'OBeWKLFyElT3+KuZxSkCsnoO5YjuCGbXPyG06tXMHXMTncpj1ri+vpjUSnhD\n' + + 'wn3o0zpNWu0GaWXIgTqj2ZouVwV2S1+wAJQjE8uI1JvBiMhA+X63/GCcApBu\n' + + 'C7rN0Cs5NGXCn9VWp8i1SCp2NuZ38POABwsXUUkjpF24txyUDX8dbXlkzpao\n' + + 'g93SQAElYYmyKbGp1TKhAZl2u40mgf2yCYDv2DLRfAKMJDLvmjXoUGEg2UYO\n' + + '11w6LD0pIykdKJmFtRls/uMnlcoBgDA=\n' + + '=kzUH\n' + + '-----END PGP MESSAGE-----\n', + link: 'bafyreib34jgnpp573rwquejcq5avxvydis7fbykat6dd5z7uazobucoumm', + } + } + +] +``` + +| Parameter | Type | Description | +| ---------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| msg | `IMessageIPFS` | message object | +| did | `string` | user DID | +| wallets | `string` | user wallets | +| profilePicture | `string` | user profile picture | +| publicKey | `string` | user public key | +| about | `string` | user description | +| threadhash | `string` | cid from the latest message sent on this conversation | +| intent | `string` | addresses concatenated from the users who have approved the intent | +| intentSentBy | `string` | address of the user who sent the intent | +| intentTimestamp | `number` | timestamp of the intent | +| combinedDID | `string` | concatenated addresses of the members of this space | +| cid | `string` | content identifier on IPFS | +| spaceId | `string` | space identifier | +| spaceInformation | `SpaceDTO` | all space information | + +
+ +--- + + +### **Fetching list of user space requests** + +```typescript +const spaces = await PushAPI.space.requests({ + account: string; + pgpPrivateKey?: string; + /** + * If true, the method will return decrypted message content in response + */ + toDecrypt?: boolean; + /** + * Environment variable + */ + env?: ENV; +}); +``` + +| Param | Type | Default | Remarks | +| ------------- | ------- | ------- | ---------------------------------------------------------------------- | +| account | string | - | user address (Partial CAIP) | +| toDecrypt | boolean | false | if "true" the method will return decrypted message content in response | +| pgpPrivateKey | string | null | mandatory for users having pgp keys | +| env | string | 'prod' | API env - 'prod', 'staging', 'dev' | + +**Example normal user:** + +```typescript +// pre-requisite API calls that should be made before +// need to get user and through that encryptedPvtKey of the user +const user = await PushAPI.user.get({ + account: 'eip155:0xFe6C8E9e25f7bcF374412c5C81B2578aC473C0F7', + env: ENV.STAGING, +}) + +// need to decrypt the encryptedPvtKey to pass in the api using helper function +const pgpDecryptedPvtKey = await PushAPI.chat.decryptPGPKey(encryptedPGPPrivateKey: user.encryptedPrivateKey, signer: signer); + +// actual api +const spaces = await PushAPI.space.requests({ + account: 'eip155:0xFe6C8E9e25f7bcF374412c5C81B2578aC473C0F7', + toDecrypt: true, + pgpPrivateKey: pgpDecryptedPvtKey, + env: ENV.STAGING, +}); +``` + +**Example NFT user:** + +```typescript +// Fetch user +const user = await PushAPI.user.get({ + account: `nft:eip155:${nftChainId}:${nftContractAddress}:${nftTokenId}`, + env: env as ENV, +}); + +// Decrypt PGP Key +const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + signer: nftSigner, +}); + +// Actual api +const spaces = await PushAPI.space.requests({ + account: `nft:eip155:${nftChainId}:${nftContractAddress}:${nftTokenId}`, + toDecrypt: true, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, +}); +``` + +
+ Expected response (Get spaces requests of a specific user) + +```typescript +// PushAPI_space_requests | Response - 200 OK +// Array of spaces +[ + + { + spaceId: 'spaces:3aa43087b8c55ed9c534dd1d0a086a3340b0d829cda0a13592651cb59f284838', + about: null, + did: null, + intent: 'eip155:0xf4c946D6bd5cF09713D27364bbEd42712Bdffa8A+eip155:0xF8aBe92d1d0706bF60509F8E9A64Ed6b8520E868', + intentSentBy: 'eip155:0xf4c946D6bd5cF09713D27364bbEd42712Bdffa8A', + intentTimestamp: '2023-07-12T01:11:32.000Z', + publicKey: null, + profilePicture: null, + threadhash: null, + wallets: null, + combinedDID: 'eip155:0x12E429E3672a02E385F9f5F75E932cC1D566EEea_eip155:0x49D407CC9D0e966CD9B22BA40685083B49bd2315_eip155:0xF8aBe92d1d0706bF60509F8E9A64Ed6b8520E868_eip155:0xf4c946D6bd5cF09713D27364bbEd42712Bdffa8A', + name: null, + spaceInformation: { + members: [Array], + pendingMembers: [Array], + contractAddressERC20: null, + numberOfERC20: 0, + contractAddressNFT: null, + numberOfNFTTokens: 0, + verificationProof: 'pgp:-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkrksbCZA3GHnYNke0AhYhBNp+D95LDfs4yU03LzcYedg2\n' + + 'R7QCAACRdAf9ELAnCLXfBiAVdbgwj81xr+w9Yzw2wXLLrPLfYY7EXfyChLzQ\n' + + 'rr9XBDdWMgtzEU1diSPMbLDh1METR7n71EjG0AoeX5A2pkHI7R1vIxXUJR3G\n' + + 'fzHENsfGaKLnhrL1wLjBQACzEsIqPrHl9RItdtKEs9izLmc+wV0GFJ5OjbAs\n' + + 'ty/1Q36nnMB7sQ7Ytb9Op+q0TtZPZ7jF9CjX8KGav3P1xDQex9nfsXiDHlLK\n' + + 'MqDePaaMO6RJUWAP2xTo2k1DDJQ2dpUhs9XyjMlvFhVbIcT1/lVRCPC8V3C8\n' + + 'fUKhUejvOjNFxf0QuR+E4xs+Q3zvR1+fXdJBxbH2Fp3kOTN1N9/LEw==\n' + + '=sLLC\n' + + '-----END PGP SIGNATURE-----\n', + spaceImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + spaceName: 'statutory_amber_roadrunner', + isPublic: true, + spaceDescription: 'continued_bronze_pigeon', + spaceCreator: 'eip155:0xf4c946D6bd5cF09713D27364bbEd42712Bdffa8A', + spaceId: 'spaces:3aa43087b8c55ed9c534dd1d0a086a3340b0d829cda0a13592651cb59f284838', + scheduleAt: '2023-07-12T06:51:32.000Z', + scheduleEnd: '2023-07-12T07:41:32.000Z', + status: 'PENDING' + }, + msg: { + fromCAIP10: 'eip155:0x1615d2D9ae82D5F0eE79298899962b237386feB7', + toCAIP10: 'eip155:0x1C48fE875590f8e366447758b13982a3Ca7d9dBE', + fromDID: 'eip155:0x1615d2D9ae82D5F0eE79298899962b237386feB7', + toDID: 'eip155:0x1C48fE875590f8e366447758b13982a3Ca7d9dBE', + messageContent: "Gm gm! It's me... Mario", + messageType: 'Text', + signature: + '-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkWKQWCZB7dzg7q3axjBYhBJFuYslzDGbuE+3FMnt3ODur\n' + + 'drGMAAAjtAf/TXjtm2qb6aSikFPKYXm0Ekws+65fisJGf7T48MYkkfcD4t2e\n' + + 'HXd9LtohzGhcztbOQfAND3yME1GWuMBIksq9rlyEA0ezwsGzCJVhBnkAHBe3\n' + + '+1v4/mNSMmInU8y6sOiLiOcW7ameJvZvDdPDJ0YHhc9dKDCIh1UAZEPAgx+z\n' + + 'Wc0DM6pW8bT70dfgnuW2LlLGF5Z23Z1vbHmeszt78+xYY3ez/hoMHXUIE25z\n' + + 'Wrnt75nasBBahtJ0mwH10ATnsQNE9hTi6XPGYxRSNDM9nyRxTQUpjhNmGS/+\n' + + '7oFyq8xTcRSaL7d3h8URp9hgFWher5ZZDyMV0jvk+HPguUX54g6Kgw==\n' + + '=dcRD\n' + + '-----END PGP SIGNATURE-----\n', + timestamp: 1683530775648, + sigType: 'pgp', + encType: 'pgp', + encryptedSecret: + '-----BEGIN PGP MESSAGE-----\n' + + '\n' + + 'wcBMA9aU+JGZVRn/AQgA1pIJHyeJinU21r6At5S5ZaWeN0OEKVB2TjpqZ0IW\n' + + 'lHLKQrQ8k3M16bN+Vf0P+DzDVOL84QRkBD56qSNVHOOCox5wcQeR01CczenV\n' + + 'LUVvVjBzR2hj7Sdw+Q+M//rgeZPPUDbNyiVmGijelhwDqWd7IOoZY26AGXlm\n' + + '7YQiElvHN2HcYXaTlLAOy36BcccwHu3Tn06F77ZXaf8FnGMWOUy7wh1/jugg\n' + + 'D17jUZGLYbmw+u5l9BOfljbw2pb4vtjWht0I1b4GYlKb+bYg/NY0UNsq7mSh\n' + + 'dGAmOhy5tC2NMjLRRLfD2qasxHoHN50onlB6HcYLl0RCf31ebOgO6rMhUnxt\n' + + '9cHATAMLWLG2xubrYAEH/2tVeq2j7nJALGSFxjJPboOY57aiFrhXNQ/e/oXH\n' + + '//TNJgGWx4Ta++OuF2Oexbh9DIZhl6DWld9adXDDtBS/fEyjNsYqwoYlNEJN\n' + + 'kLvSmokNNrE4MKC1A0GkhSh2MGQDNk42GSgz1tep8XSVc98MHqfNXCHVb5Oa\n' + + 'OBeWKLFyElT3+KuZxSkCsnoO5YjuCGbXPyG06tXMHXMTncpj1ri+vpjUSnhD\n' + + 'wn3o0zpNWu0GaWXIgTqj2ZouVwV2S1+wAJQjE8uI1JvBiMhA+X63/GCcApBu\n' + + 'C7rN0Cs5NGXCn9VWp8i1SCp2NuZ38POABwsXUUkjpF24txyUDX8dbXlkzpao\n' + + 'g93SQAElYYmyKbGp1TKhAZl2u40mgf2yCYDv2DLRfAKMJDLvmjXoUGEg2UYO\n' + + '11w6LD0pIykdKJmFtRls/uMnlcoBgDA=\n' + + '=kzUH\n' + + '-----END PGP MESSAGE-----\n', + link: 'bafyreib34jgnpp573rwquejcq5avxvydis7fbykat6dd5z7uazobucoumm', + } + } + +] +``` + +| Parameter | Type | Description | +| ---------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| msg | `IMessageIPFS` | message object | +| did | `string` | user DID | +| wallets | `string` | user wallets | +| profilePicture | `string` | user profile picture | +| publicKey | `string` | user public key | +| about | `string` | user description | +| threadhash | `string` | cid from the latest message sent on this conversation | +| intent | `string` | addresses concatenated from the users who have approved the intent | +| intentSentBy | `string` | address of the user who sent the intent | +| intentTimestamp | `number` | timestamp of the intent | +| combinedDID | `string` | concatenated addresses of the members of this space | +| cid | `string` | content identifier on IPFS | +| spaceId | `string` | space identifier | +| spaceInformation | `SpaceDTO` | all space information | + +
+ +--- + +### **Fetching list of trending spaces** + +```typescript +const spaces = await PushAPI.space.trending({ + env?: ENV; +}); +``` + +| Param | Type | Default | Remarks | +| ------------- | ------- | ------- | ---------------------------------------------------------------------- | +| env | string | 'prod' | API env - 'prod', 'staging', 'dev' | +| page | number | 1 | page index of the results | +| limit | number | 10 | number of items in 1 page | + + +
+ + Expected response (Get trending spaces) + +```typescript +// PushAPI_space_trending | Response - 200 OK +// Array of spaces +[ + + { + spaceId: 'spaces:3aa43087b8c55ed9c534dd1d0a086a3340b0d829cda0a13592651cb59f284838', + about: null, + did: null, + intent: 'eip155:0xf4c946D6bd5cF09713D27364bbEd42712Bdffa8A+eip155:0xF8aBe92d1d0706bF60509F8E9A64Ed6b8520E868', + intentSentBy: 'eip155:0xf4c946D6bd5cF09713D27364bbEd42712Bdffa8A', + intentTimestamp: '2023-07-12T01:11:32.000Z', + publicKey: null, + profilePicture: null, + threadhash: null, + wallets: null, + combinedDID: 'eip155:0x12E429E3672a02E385F9f5F75E932cC1D566EEea_eip155:0x49D407CC9D0e966CD9B22BA40685083B49bd2315_eip155:0xF8aBe92d1d0706bF60509F8E9A64Ed6b8520E868_eip155:0xf4c946D6bd5cF09713D27364bbEd42712Bdffa8A', + name: null, + spaceInformation: { + members: [Array], + pendingMembers: [Array], + contractAddressERC20: null, + numberOfERC20: 0, + contractAddressNFT: null, + numberOfNFTTokens: 0, + verificationProof: 'pgp:-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkrksbCZA3GHnYNke0AhYhBNp+D95LDfs4yU03LzcYedg2\n' + + 'R7QCAACRdAf9ELAnCLXfBiAVdbgwj81xr+w9Yzw2wXLLrPLfYY7EXfyChLzQ\n' + + 'rr9XBDdWMgtzEU1diSPMbLDh1METR7n71EjG0AoeX5A2pkHI7R1vIxXUJR3G\n' + + 'fzHENsfGaKLnhrL1wLjBQACzEsIqPrHl9RItdtKEs9izLmc+wV0GFJ5OjbAs\n' + + 'ty/1Q36nnMB7sQ7Ytb9Op+q0TtZPZ7jF9CjX8KGav3P1xDQex9nfsXiDHlLK\n' + + 'MqDePaaMO6RJUWAP2xTo2k1DDJQ2dpUhs9XyjMlvFhVbIcT1/lVRCPC8V3C8\n' + + 'fUKhUejvOjNFxf0QuR+E4xs+Q3zvR1+fXdJBxbH2Fp3kOTN1N9/LEw==\n' + + '=sLLC\n' + + '-----END PGP SIGNATURE-----\n', + spaceImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + spaceName: 'statutory_amber_roadrunner', + isPublic: true, + spaceDescription: 'continued_bronze_pigeon', + spaceCreator: 'eip155:0xf4c946D6bd5cF09713D27364bbEd42712Bdffa8A', + spaceId: 'spaces:3aa43087b8c55ed9c534dd1d0a086a3340b0d829cda0a13592651cb59f284838', + scheduleAt: '2023-07-12T06:51:32.000Z', + scheduleEnd: '2023-07-12T07:41:32.000Z', + status: 'PENDING' + }, + msg: { + fromCAIP10: 'eip155:0x1615d2D9ae82D5F0eE79298899962b237386feB7', + toCAIP10: 'eip155:0x1C48fE875590f8e366447758b13982a3Ca7d9dBE', + fromDID: 'eip155:0x1615d2D9ae82D5F0eE79298899962b237386feB7', + toDID: 'eip155:0x1C48fE875590f8e366447758b13982a3Ca7d9dBE', + messageContent: "Gm gm! It's me... Mario", + messageType: 'Text', + signature: + '-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'wsBzBAEBCAAnBYJkWKQWCZB7dzg7q3axjBYhBJFuYslzDGbuE+3FMnt3ODur\n' + + 'drGMAAAjtAf/TXjtm2qb6aSikFPKYXm0Ekws+65fisJGf7T48MYkkfcD4t2e\n' + + 'HXd9LtohzGhcztbOQfAND3yME1GWuMBIksq9rlyEA0ezwsGzCJVhBnkAHBe3\n' + + '+1v4/mNSMmInU8y6sOiLiOcW7ameJvZvDdPDJ0YHhc9dKDCIh1UAZEPAgx+z\n' + + 'Wc0DM6pW8bT70dfgnuW2LlLGF5Z23Z1vbHmeszt78+xYY3ez/hoMHXUIE25z\n' + + 'Wrnt75nasBBahtJ0mwH10ATnsQNE9hTi6XPGYxRSNDM9nyRxTQUpjhNmGS/+\n' + + '7oFyq8xTcRSaL7d3h8URp9hgFWher5ZZDyMV0jvk+HPguUX54g6Kgw==\n' + + '=dcRD\n' + + '-----END PGP SIGNATURE-----\n', + timestamp: 1683530775648, + sigType: 'pgp', + encType: 'pgp', + encryptedSecret: + '-----BEGIN PGP MESSAGE-----\n' + + '\n' + + 'wcBMA9aU+JGZVRn/AQgA1pIJHyeJinU21r6At5S5ZaWeN0OEKVB2TjpqZ0IW\n' + + 'lHLKQrQ8k3M16bN+Vf0P+DzDVOL84QRkBD56qSNVHOOCox5wcQeR01CczenV\n' + + 'LUVvVjBzR2hj7Sdw+Q+M//rgeZPPUDbNyiVmGijelhwDqWd7IOoZY26AGXlm\n' + + '7YQiElvHN2HcYXaTlLAOy36BcccwHu3Tn06F77ZXaf8FnGMWOUy7wh1/jugg\n' + + 'D17jUZGLYbmw+u5l9BOfljbw2pb4vtjWht0I1b4GYlKb+bYg/NY0UNsq7mSh\n' + + 'dGAmOhy5tC2NMjLRRLfD2qasxHoHN50onlB6HcYLl0RCf31ebOgO6rMhUnxt\n' + + '9cHATAMLWLG2xubrYAEH/2tVeq2j7nJALGSFxjJPboOY57aiFrhXNQ/e/oXH\n' + + '//TNJgGWx4Ta++OuF2Oexbh9DIZhl6DWld9adXDDtBS/fEyjNsYqwoYlNEJN\n' + + 'kLvSmokNNrE4MKC1A0GkhSh2MGQDNk42GSgz1tep8XSVc98MHqfNXCHVb5Oa\n' + + 'OBeWKLFyElT3+KuZxSkCsnoO5YjuCGbXPyG06tXMHXMTncpj1ri+vpjUSnhD\n' + + 'wn3o0zpNWu0GaWXIgTqj2ZouVwV2S1+wAJQjE8uI1JvBiMhA+X63/GCcApBu\n' + + 'C7rN0Cs5NGXCn9VWp8i1SCp2NuZ38POABwsXUUkjpF24txyUDX8dbXlkzpao\n' + + 'g93SQAElYYmyKbGp1TKhAZl2u40mgf2yCYDv2DLRfAKMJDLvmjXoUGEg2UYO\n' + + '11w6LD0pIykdKJmFtRls/uMnlcoBgDA=\n' + + '=kzUH\n' + + '-----END PGP MESSAGE-----\n', + link: 'bafyreib34jgnpp573rwquejcq5avxvydis7fbykat6dd5z7uazobucoumm', + } + } + +] +``` + +| Parameter | Type | Description | +| ---------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| msg | `IMessageIPFS` | message object | +| did | `string` | user DID | +| wallets | `string` | user wallets | +| profilePicture | `string` | user profile picture | +| publicKey | `string` | user public key | +| about | `string` | user description | +| threadhash | `string` | cid from the latest message sent on this conversation | +| intent | `string` | addresses concatenated from the users who have approved the intent | +| intentSentBy | `string` | address of the user who sent the intent | +| intentTimestamp | `number` | timestamp of the intent | +| combinedDID | `string` | concatenated addresses of the members of this space | +| cid | `string` | content identifier on IPFS | +| spaceId | `string` | space identifier | +| spaceInformation | `SpaceDTO` | all space information | + +
+ +--- diff --git a/packages/restapi/package-lock.json b/packages/restapi/package-lock.json index 0c5fedb68..a2cdeca0a 100644 --- a/packages/restapi/package-lock.json +++ b/packages/restapi/package-lock.json @@ -1,29 +1,31 @@ { "name": "@pushprotocol/restapi", - "version": "0.8.3", + "version": "0.0.1-alpha.13", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@pushprotocol/restapi", - "version": "0.8.3", + "version": "0.0.1-alpha.13", "dependencies": { "@metamask/eth-sig-util": "^5.0.2", "buffer": "^6.0.3", - "chai": "^4.3.7", "crypto-js": "^4.1.1", - "mocha-typescript": "^1.1.17", + "immer": "^10.0.2", "openpgp": "^5.5.0", - "ts-node": "^10.9.1", - "typescript": "^5.0.2" + "simple-peer": "^9.11.1" }, "devDependencies": { "@types/chai": "^4.3.4", "@types/chai-as-promised": "^7.1.5", "@types/crypto-js": "^4.1.1", "@types/mocha": "^10.0.1", + "chai": "^4.3.7", "chai-as-promised": "^7.1.1", - "mocha": "^10.2.0" + "mocha": "^10.2.0", + "mocha-typescript": "^1.1.17", + "ts-node": "^10.9.1", + "typescript": "^5.0.2" }, "peerDependencies": { "ethers": "^5.6.8" @@ -56,6 +58,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -804,6 +807,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, "engines": { "node": ">=6.0.0" } @@ -811,12 +815,14 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -905,22 +911,26 @@ "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true }, "node_modules/@types/chai": { "version": "4.3.4", @@ -949,10 +959,18 @@ "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", "dev": true }, + "node_modules/@types/node": { + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", + "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==", + "dev": true, + "peer": true + }, "node_modules/acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -964,6 +982,7 @@ "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -1023,7 +1042,8 @@ "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true }, "node_modules/argparse": { "version": "2.0.1", @@ -1046,6 +1066,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, "engines": { "node": "*" } @@ -1176,6 +1197,7 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", @@ -1233,6 +1255,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true, "engines": { "node": "*" } @@ -1279,6 +1302,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -1310,12 +1334,14 @@ "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true }, "node_modules/cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -1336,7 +1362,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -1352,8 +1377,7 @@ "node_modules/debug/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/decamelize": { "version": "4.0.0", @@ -1371,6 +1395,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, "dependencies": { "type-detect": "^4.0.0" }, @@ -1382,6 +1407,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, "engines": { "node": ">=0.3.1" } @@ -1411,10 +1437,16 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "dependencies": { "once": "^1.4.0" } }, + "node_modules/err-code": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", + "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -1512,6 +1544,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, "dependencies": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", @@ -1582,6 +1615,11 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/get-browser-rtc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz", + "integrity": "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==" + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1595,6 +1633,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true, "engines": { "node": "*" } @@ -1603,6 +1642,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, "dependencies": { "pump": "^3.0.0" }, @@ -1712,6 +1752,15 @@ } ] }, + "node_modules/immer": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz", + "integrity": "sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1731,6 +1780,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true, "engines": { "node": ">=4" } @@ -1808,6 +1858,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -1827,7 +1878,8 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/js-sha3": { "version": "0.8.0", @@ -1851,6 +1903,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, "dependencies": { "invert-kv": "^2.0.0" }, @@ -1893,6 +1946,7 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, "dependencies": { "get-func-name": "^2.0.0" } @@ -1900,12 +1954,14 @@ "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true }, "node_modules/map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, "dependencies": { "p-defer": "^1.0.0" }, @@ -1917,6 +1973,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, "dependencies": { "map-age-cleaner": "^0.1.1", "mimic-fn": "^2.0.0", @@ -1930,6 +1987,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, "engines": { "node": ">=6" } @@ -2011,6 +2069,7 @@ "resolved": "https://registry.npmjs.org/mocha-typescript/-/mocha-typescript-1.1.17.tgz", "integrity": "sha512-Ge6pCQkZumkkhxVNdAf3JxunskShgaynCb30HYD7TT1Yhog/7NW2+6w5RcRHI+nuQrCMTX6z1+qf2pD8qwCoQA==", "deprecated": "mocha-typescript has been deprecated, use @testdeck/mocha instead", + "dev": true, "dependencies": { "@types/mocha": "^5.2.0", "chalk": "^2.4.1", @@ -2024,12 +2083,14 @@ "node_modules/mocha-typescript/node_modules/@types/mocha": { "version": "5.2.7", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", - "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==" + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "dev": true }, "node_modules/mocha-typescript/node_modules/ansi-regex": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, "engines": { "node": ">=4" } @@ -2038,6 +2099,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -2049,6 +2111,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==", + "dev": true, "engines": { "node": ">=4" } @@ -2057,6 +2120,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -2070,6 +2134,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, "dependencies": { "string-width": "^2.1.1", "strip-ansi": "^4.0.0", @@ -2080,6 +2145,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -2087,12 +2153,14 @@ "node_modules/mocha-typescript/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/mocha-typescript/node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2101,6 +2169,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, "engines": { "node": ">=0.8.0" } @@ -2109,6 +2178,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, "dependencies": { "locate-path": "^2.0.0" }, @@ -2119,12 +2189,14 @@ "node_modules/mocha-typescript/node_modules/get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true }, "node_modules/mocha-typescript/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, "engines": { "node": ">=4" } @@ -2133,6 +2205,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, "engines": { "node": ">=4" } @@ -2141,6 +2214,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -2153,6 +2227,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, "dependencies": { "p-try": "^1.0.0" }, @@ -2164,6 +2239,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, "dependencies": { "p-limit": "^1.1.0" }, @@ -2175,6 +2251,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, "engines": { "node": ">=4" } @@ -2183,6 +2260,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -2195,6 +2273,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, "dependencies": { "ansi-regex": "^3.0.0" }, @@ -2206,6 +2285,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -2217,6 +2297,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "dev": true, "dependencies": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" @@ -2229,6 +2310,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2237,6 +2319,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, "dependencies": { "number-is-nan": "^1.0.0" }, @@ -2248,6 +2331,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dev": true, "dependencies": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -2261,6 +2345,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, "dependencies": { "ansi-regex": "^2.0.0" }, @@ -2271,12 +2356,14 @@ "node_modules/mocha-typescript/node_modules/y18n": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true }, "node_modules/mocha-typescript/node_modules/yargs": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.1.tgz", "integrity": "sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==", + "dev": true, "dependencies": { "cliui": "^4.0.0", "decamelize": "^1.1.1", @@ -2296,6 +2383,7 @@ "version": "9.0.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", "integrity": "sha512-CswCfdOgCr4MMsT1GzbEJ7Z2uYudWyrGX8Bgh/0eyCzj/DXWdKq6a/ADufkzI1WAOIW6jYaXJvRyLhDO0kfqBw==", + "dev": true, "dependencies": { "camelcase": "^4.1.0" } @@ -2330,7 +2418,8 @@ "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true }, "node_modules/normalize-path": { "version": "3.0.0", @@ -2345,6 +2434,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, "dependencies": { "path-key": "^2.0.0" }, @@ -2356,6 +2446,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2364,6 +2455,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -2383,6 +2475,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, "dependencies": { "execa": "^1.0.0", "lcid": "^2.0.0", @@ -2396,6 +2489,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", + "dev": true, "engines": { "node": ">=4" } @@ -2404,6 +2498,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "dev": true, "engines": { "node": ">=4" } @@ -2412,6 +2507,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true, "engines": { "node": ">=6" } @@ -2450,6 +2546,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, "engines": { "node": ">=4" } @@ -2476,6 +2573,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, "engines": { "node": ">=4" } @@ -2484,6 +2582,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, "engines": { "node": "*" } @@ -2504,20 +2603,52 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -2534,6 +2665,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2541,13 +2673,13 @@ "node_modules/require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==" + "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==", + "dev": true }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -2578,6 +2710,7 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, "bin": { "semver": "bin/semver" } @@ -2594,12 +2727,14 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true }, "node_modules/shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, "dependencies": { "shebang-regex": "^1.0.0" }, @@ -2611,6 +2746,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2618,7 +2754,44 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/simple-peer": { + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz", + "integrity": "sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "buffer": "^6.0.3", + "debug": "^4.3.2", + "err-code": "^3.0.1", + "get-browser-rtc": "^1.1.0", + "queue-microtask": "^1.2.3", + "randombytes": "^2.1.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } }, "node_modules/string-width": { "version": "4.2.3", @@ -2650,6 +2823,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2709,6 +2883,7 @@ "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -2761,6 +2936,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, "engines": { "node": ">=4" } @@ -2769,6 +2945,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2777,15 +2954,22 @@ "node": ">=12.20" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -2796,7 +2980,8 @@ "node_modules/which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==" + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true }, "node_modules/workerpool": { "version": "6.2.1", @@ -2824,7 +3009,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/ws": { "version": "7.4.6", @@ -2902,6 +3088,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, "engines": { "node": ">=6" } @@ -2947,6 +3134,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, "requires": { "@jridgewell/trace-mapping": "0.3.9" } @@ -3386,17 +3574,20 @@ "@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true }, "@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true }, "@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -3452,22 +3643,26 @@ "@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true }, "@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true }, "@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true }, "@tsconfig/node16": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true }, "@types/chai": { "version": "4.3.4", @@ -3496,15 +3691,24 @@ "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", "dev": true }, + "@types/node": { + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", + "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==", + "dev": true, + "peer": true + }, "acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true }, "acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true }, "aes-js": { "version": "3.0.0", @@ -3546,7 +3750,8 @@ "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true }, "argparse": { "version": "2.0.1", @@ -3568,7 +3773,8 @@ "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true }, "balanced-match": { "version": "1.0.2", @@ -3653,6 +3859,7 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", @@ -3696,7 +3903,8 @@ "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==" + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true }, "chokidar": { "version": "3.5.3", @@ -3728,7 +3936,8 @@ "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "dev": true }, "color-convert": { "version": "2.0.1", @@ -3754,12 +3963,14 @@ "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -3777,7 +3988,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "requires": { "ms": "2.1.2" }, @@ -3785,8 +3995,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" } } }, @@ -3800,6 +4009,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, "requires": { "type-detect": "^4.0.0" } @@ -3807,7 +4017,8 @@ "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true }, "elliptic": { "version": "6.5.4", @@ -3834,10 +4045,16 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "requires": { "once": "^1.4.0" } }, + "err-code": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", + "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -3912,6 +4129,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, "requires": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", @@ -3960,6 +4178,11 @@ "dev": true, "optional": true }, + "get-browser-rtc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz", + "integrity": "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==" + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3969,12 +4192,14 @@ "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==" + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, "requires": { "pump": "^3.0.0" } @@ -4051,6 +4276,11 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, + "immer": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz", + "integrity": "sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -4069,7 +4299,8 @@ "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true }, "is-binary-path": { "version": "2.1.0", @@ -4121,7 +4352,8 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true }, "is-unicode-supported": { "version": "0.1.0", @@ -4132,7 +4364,8 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "js-sha3": { "version": "0.8.0", @@ -4153,6 +4386,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, "requires": { "invert-kv": "^2.0.0" } @@ -4180,6 +4414,7 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, "requires": { "get-func-name": "^2.0.0" } @@ -4187,12 +4422,14 @@ "make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, "requires": { "p-defer": "^1.0.0" } @@ -4201,6 +4438,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, "requires": { "map-age-cleaner": "^0.1.1", "mimic-fn": "^2.0.0", @@ -4210,7 +4448,8 @@ "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true }, "minimalistic-assert": { "version": "1.0.1", @@ -4284,6 +4523,7 @@ "version": "1.1.17", "resolved": "https://registry.npmjs.org/mocha-typescript/-/mocha-typescript-1.1.17.tgz", "integrity": "sha512-Ge6pCQkZumkkhxVNdAf3JxunskShgaynCb30HYD7TT1Yhog/7NW2+6w5RcRHI+nuQrCMTX6z1+qf2pD8qwCoQA==", + "dev": true, "requires": { "@types/mocha": "^5.2.0", "chalk": "^2.4.1", @@ -4294,17 +4534,20 @@ "@types/mocha": { "version": "5.2.7", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", - "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==" + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "dev": true }, "ansi-regex": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -4312,12 +4555,14 @@ "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==" + "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==", + "dev": true }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -4328,6 +4573,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, "requires": { "string-width": "^2.1.1", "strip-ansi": "^4.0.0", @@ -4338,6 +4584,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "requires": { "color-name": "1.1.3" } @@ -4345,22 +4592,26 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, "requires": { "locate-path": "^2.0.0" } @@ -4368,22 +4619,26 @@ "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==" + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -4393,6 +4648,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, "requires": { "p-try": "^1.0.0" } @@ -4401,6 +4657,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, "requires": { "p-limit": "^1.1.0" } @@ -4408,12 +4665,14 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -4423,6 +4682,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, "requires": { "ansi-regex": "^3.0.0" } @@ -4431,6 +4691,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -4439,6 +4700,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "dev": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" @@ -4447,12 +4709,14 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4461,6 +4725,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4471,6 +4736,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4480,12 +4746,14 @@ "y18n": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true }, "yargs": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.1.tgz", "integrity": "sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==", + "dev": true, "requires": { "cliui": "^4.0.0", "decamelize": "^1.1.1", @@ -4505,6 +4773,7 @@ "version": "9.0.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", "integrity": "sha512-CswCfdOgCr4MMsT1GzbEJ7Z2uYudWyrGX8Bgh/0eyCzj/DXWdKq6a/ADufkzI1WAOIW6jYaXJvRyLhDO0kfqBw==", + "dev": true, "requires": { "camelcase": "^4.1.0" } @@ -4526,7 +4795,8 @@ "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true }, "normalize-path": { "version": "3.0.0", @@ -4538,6 +4808,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, "requires": { "path-key": "^2.0.0" } @@ -4545,12 +4816,14 @@ "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "requires": { "wrappy": "1" } @@ -4567,6 +4840,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, "requires": { "execa": "^1.0.0", "lcid": "^2.0.0", @@ -4576,17 +4850,20 @@ "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==" + "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", + "dev": true }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "dev": true }, "p-is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true }, "p-limit": { "version": "3.1.0", @@ -4609,7 +4886,8 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==" + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true }, "path-exists": { "version": "4.0.0", @@ -4626,12 +4904,14 @@ "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==" + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==" + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true }, "picomatch": { "version": "2.3.1", @@ -4643,20 +4923,35 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "requires": { "safe-buffer": "^5.1.0" } }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4669,18 +4964,19 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==" + "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==", + "dev": true }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", @@ -4696,7 +4992,8 @@ "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true }, "serialize-javascript": { "version": "6.0.0", @@ -4710,12 +5007,14 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, "requires": { "shebang-regex": "^1.0.0" } @@ -4723,12 +5022,36 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==" + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true }, "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "simple-peer": { + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz", + "integrity": "sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==", + "requires": { + "buffer": "^6.0.3", + "debug": "^4.3.2", + "err-code": "^3.0.1", + "get-browser-rtc": "^1.1.0", + "queue-microtask": "^1.2.3", + "randombytes": "^2.1.0", + "readable-stream": "^3.6.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } }, "string-width": { "version": "4.2.3", @@ -4753,7 +5076,8 @@ "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==" + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true }, "strip-hex-prefix": { "version": "1.0.0", @@ -4791,6 +5115,7 @@ "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, "requires": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -4820,22 +5145,31 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true }, "typescript": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", - "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==" + "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, "requires": { "isexe": "^2.0.0" } @@ -4843,7 +5177,8 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==" + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true }, "workerpool": { "version": "6.2.1", @@ -4865,7 +5200,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "ws": { "version": "7.4.6", @@ -4916,7 +5252,8 @@ "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true }, "yocto-queue": { "version": "0.1.0", diff --git a/packages/restapi/package.json b/packages/restapi/package.json index 143b636d7..631fbc409 100644 --- a/packages/restapi/package.json +++ b/packages/restapi/package.json @@ -1,6 +1,6 @@ { "name": "@pushprotocol/restapi", - "version": "1.3.9", + "version": "0.0.1-alpha.23", "type": "commonjs", "publishConfig": { "registry": "https://registry.npmjs.org/" @@ -9,12 +9,15 @@ "ethers": "^5.6.8" }, "dependencies": { + "@livepeer/webrtmp-sdk": "^0.2.3", "@metamask/eth-sig-util": "^5.0.2", "buffer": "^6.0.3", "crypto-js": "^4.1.1", "immer": "^10.0.2", + "livepeer": "^2.5.8", "openpgp": "^5.5.0", - "simple-peer": "^9.11.1" + "simple-peer": "^9.11.1", + "video-stream-merger": "^4.0.1" }, "scripts": { "test": "TS_NODE_PROJECT='./tsconfig.mocha.json' NODE_OPTIONS='--loader ts-node/esm' mocha -r ts-node/register 'tests/**/*.test.ts' --timeout 120000 --require tests/root.ts --serial" diff --git a/packages/restapi/src/lib/chat/addAdmins.ts b/packages/restapi/src/lib/chat/addAdmins.ts new file mode 100644 index 000000000..f45eef5b9 --- /dev/null +++ b/packages/restapi/src/lib/chat/addAdmins.ts @@ -0,0 +1,103 @@ +import { isValidETHAddress, walletToPCAIP10 } from '../helpers'; +import Constants from '../constants'; +import { EnvOptionsType, SignerType, GroupDTO } from '../types'; +import { + getMembersList, + getAdminsList, +} from './helpers'; +import { + getGroup +} from './getGroup'; +import { + updateGroup +} from './updateGroup'; +export interface AddAdminsToGroupType extends EnvOptionsType { + chatId: string; + admins: Array; + account?: string | null; + signer?: SignerType | null; + pgpPrivateKey?: string | null; +} + +export const addAdmins = async ( + options: AddAdminsToGroupType +): Promise => { + const { + chatId, + admins, + account = null, + signer = null, + env = Constants.ENV.PROD, + pgpPrivateKey = null, + } = options || {}; + try { + if (account == null && signer == null) { + throw new Error(`At least one from account or signer is necessary!`); + } + + if (!admins || admins.length === 0) { + throw new Error("Admin address array cannot be empty!"); + } + + admins.forEach((admin) => { + if (!isValidETHAddress(admin)) { + throw new Error(`Invalid admin address: ${admin}`); + } + }); + + const group = await getGroup({ + chatId: chatId, + env, + }) + + // TODO: look at user did in updateGroup + const convertedMembers = getMembersList( + group.members, group.pendingMembers + ); + + // TODO: look at user did in updateGroup + const adminsToBeAdded = admins.map((admin) => walletToPCAIP10(admin)); + + adminsToBeAdded.forEach((admin) => { + if (!convertedMembers.includes(admin)) { + convertedMembers.push(admin); + } + }); + + const convertedAdmins = getAdminsList( + group.members, group.pendingMembers + ); + + adminsToBeAdded.forEach((admin) => { + if (convertedAdmins.includes(admin)) { + throw new Error(`Admin ${admin} already exists in the list`); + } + }); + + convertedAdmins.push(...adminsToBeAdded); + + return await updateGroup({ + chatId: chatId, + groupName: group.groupName, + groupImage: group.groupImage, + groupDescription: group.groupDescription, + members: convertedMembers, + admins: convertedAdmins, + scheduleAt: group.scheduleAt, + scheduleEnd: group.scheduleEnd, + status: group.status, + account: account, + signer: signer, + env: env, + pgpPrivateKey: pgpPrivateKey + }); + } catch (err) { + console.error( + `[Push SDK] - API - Error - API ${addAdmins.name} -: `, + err + ); + throw Error( + `[Push SDK] - API - Error - API ${addAdmins.name} -: ${err}` + ); + } +}; diff --git a/packages/restapi/src/lib/chat/addMembers.ts b/packages/restapi/src/lib/chat/addMembers.ts new file mode 100644 index 000000000..0b5d07ba5 --- /dev/null +++ b/packages/restapi/src/lib/chat/addMembers.ts @@ -0,0 +1,98 @@ +import { isValidETHAddress, walletToPCAIP10 } from '../helpers'; +import Constants from '../constants'; +import { EnvOptionsType, SignerType, GroupDTO } from '../types'; +import { + getMembersList, + getAdminsList +} from './helpers'; +import { + getGroup +} from './getGroup'; +import { + updateGroup +} from './updateGroup'; +export interface AddMembersToGroupType extends EnvOptionsType { + chatId: string; + members: Array; + account?: string | null; + signer?: SignerType | null; + pgpPrivateKey?: string | null; +} + +/** + * Update Group information + */ +export const addMembers = async ( + options: AddMembersToGroupType +): Promise => { + const { + chatId, + members, + account = null, + signer = null, + env = Constants.ENV.PROD, + pgpPrivateKey = null, + } = options || {}; + try { + if (account == null && signer == null) { + throw new Error(`At least one from account or signer is necessary!`); + } + + if (!members || members.length === 0) { + throw new Error("Member address array cannot be empty!"); + } + + members.forEach((member) => { + if (!isValidETHAddress(member)) { + throw new Error(`Invalid member address: ${member}`); + } + }); + + const group = await getGroup({ + chatId: chatId, + env, + }) + + const convertedMembers = getMembersList( + group.members, group.pendingMembers + ); + + const membersToBeAdded = members.map((member) => walletToPCAIP10(member)); + + membersToBeAdded.forEach((member) => { + if (convertedMembers.includes(member)) { + throw new Error(`Member ${member} already exists in the list`); + } + }); + + convertedMembers.push(...membersToBeAdded); + + const convertedAdmins = getAdminsList( + group.members, group.pendingMembers + ); + + return await updateGroup({ + chatId: chatId, + groupName: group.groupName, + groupImage: group.groupImage, + groupDescription: group.groupDescription, + members: convertedMembers, + admins: convertedAdmins, + scheduleAt: group.scheduleAt, + scheduleEnd: group.scheduleEnd, + status: group.status, + account: account, + signer: signer, + env: env, + pgpPrivateKey: pgpPrivateKey + }); + } catch (err) { + console.error( + `[Push SDK] - API - Error - API ${addMembers.name} -: `, + err + ); + throw Error( + `[Push SDK] - API - Error - API ${addMembers.name} -: ${err}` + ); + } +}; diff --git a/packages/restapi/src/lib/chat/approveRequest.ts b/packages/restapi/src/lib/chat/approveRequest.ts index ae9364263..7d357ffb9 100644 --- a/packages/restapi/src/lib/chat/approveRequest.ts +++ b/packages/restapi/src/lib/chat/approveRequest.ts @@ -12,22 +12,21 @@ import { getUserDID, } from './helpers'; import * as CryptoJS from 'crypto-js'; -import { get } from '../user'; interface ApproveRequestOptionsType extends EnvOptionsType { /** * Chat request sender address */ senderAddress: string; - pgpPrivateKey?: string; + pgpPrivateKey?: string | null; /** * Request state. As of now, only `Approved` is allowed */ status?: 'Approved'; // sigType?: string; - account?: string; - signer?: SignerType; + account?: string | null; + signer?: SignerType | null; } /** diff --git a/packages/restapi/src/lib/chat/createGroup.ts b/packages/restapi/src/lib/chat/createGroup.ts index 6914132a1..0eca88732 100644 --- a/packages/restapi/src/lib/chat/createGroup.ts +++ b/packages/restapi/src/lib/chat/createGroup.ts @@ -10,24 +10,28 @@ import { getWallet, getUserDID, getConnectedUserV2, + validateScheduleDates, } from './helpers'; import * as CryptoJS from 'crypto-js'; export interface ChatCreateGroupType extends EnvOptionsType { - account?: string; - signer?: SignerType; + account?: string | null; + signer?: SignerType | null; groupName: string; groupDescription: string; members: Array; - groupImage: string; + groupImage: string | null; admins: Array; isPublic: boolean; contractAddressNFT?: string; numberOfNFTs?: number; contractAddressERC20?: string; numberOfERC20?: number; - pgpPrivateKey?: string; + pgpPrivateKey?: string | null; meta?: string; + groupType? : string | null, + scheduleAt ?: Date | null; + scheduleEnd?: Date | null; } export const createGroup = async ( @@ -49,6 +53,9 @@ export const createGroup = async ( env = Constants.ENV.PROD, pgpPrivateKey = null, meta, + groupType, + scheduleAt, + scheduleEnd } = options || {}; try { @@ -56,6 +63,8 @@ export const createGroup = async ( throw new Error(`At least one from account or signer is necessary!`); } + validateScheduleDates(scheduleAt, scheduleEnd) + const wallet = getWallet({ account, signer }); createGroupRequestValidator( @@ -120,7 +129,10 @@ export const createGroup = async ( numberOfNFTs, contractAddressERC20, numberOfERC20, - meta + meta, + groupType, + scheduleAt, + scheduleEnd ); return axios diff --git a/packages/restapi/src/lib/chat/helpers/inbox.ts b/packages/restapi/src/lib/chat/helpers/inbox.ts index 2f9df6c86..4df219e51 100644 --- a/packages/restapi/src/lib/chat/helpers/inbox.ts +++ b/packages/restapi/src/lib/chat/helpers/inbox.ts @@ -1,6 +1,6 @@ import Constants, { ENV } from '../../constants'; import { isValidCAIP10NFTAddress, pCAIP10ToWallet } from '../../helpers'; -import { IFeeds, IMessageIPFS, IUser } from '../../types'; +import { IFeeds, IMessageIPFS, IUser, SpaceIFeeds } from '../../types'; import { get as getUser } from '../../user'; import { getCID } from '../ipfs'; import { decryptFeeds, decryptAndVerifyMessage } from './crypto'; @@ -12,6 +12,20 @@ type InboxListsType = { pgpPrivateKey?: string; env?: ENV; }; + +type SpaceInboxListsType = { + lists: SpaceIFeeds[]; + user: string; //caip10 + toDecrypt: boolean; + pgpPrivateKey?: string; + env?: ENV; +}; + +type TrendingSpaceInboxListsType = { + lists: SpaceIFeeds[]; + env?: ENV; +}; + type DecryptConverationType = { messages: IMessageIPFS[]; connectedUser: IUser; //caip10 @@ -64,6 +78,86 @@ export const getInboxLists = async ( return feeds; }; +export const getSpaceInboxLists = async ( + options: SpaceInboxListsType +): Promise => { + const { + lists, + user, + toDecrypt, + pgpPrivateKey, + env = Constants.ENV.PROD, + } = options || {}; + const connectedUser = await getUser({ account: pCAIP10ToWallet(user), env }); + const feeds: SpaceIFeeds[] = []; + for (const list of lists) { + let message; + if (list.threadhash !== null) { + message = await getCID(list.threadhash, { env }); + } + // This is for groups that are created without any message + else { + message = { + encType: 'PlainText', + encryptedSecret: '', + fromCAIP10: '', + fromDID: '', + link: '', + messageContent: '', + messageType: '', + sigType: '', + signature: '', + toCAIP10: '', + toDID: '', + }; + } + feeds.push({ + ...list, + msg: message, + spaceInformation: list.spaceInformation, + }); + } + + if (toDecrypt) + return decryptFeeds({ feeds, connectedUser, pgpPrivateKey, env }); + return feeds; +}; + +export const getTrendingSpaceInboxLists = async ( + options: TrendingSpaceInboxListsType +): Promise => { + const { lists, env = Constants.ENV.PROD } = options || {}; + const feeds: SpaceIFeeds[] = []; + for (const list of lists) { + let message; + if (list.threadhash !== null) { + message = await getCID(list.threadhash, { env }); + } + // This is for groups that are created without any message + else { + message = { + encType: 'PlainText', + encryptedSecret: '', + fromCAIP10: '', + fromDID: '', + link: '', + messageContent: '', + messageType: '', + sigType: '', + signature: '', + toCAIP10: '', + toDID: '', + }; + } + feeds.push({ + ...list, + msg: message, + spaceInformation: list.spaceInformation, + }); + } + return feeds; +}; + export const decryptConversation = async (options: DecryptConverationType) => { const { messages, diff --git a/packages/restapi/src/lib/chat/helpers/payloadHelper.ts b/packages/restapi/src/lib/chat/helpers/payloadHelper.ts index 0ac280991..df0fd8bb2 100644 --- a/packages/restapi/src/lib/chat/helpers/payloadHelper.ts +++ b/packages/restapi/src/lib/chat/helpers/payloadHelper.ts @@ -1,5 +1,5 @@ import { isValidETHAddress, walletToPCAIP10 } from '../../helpers'; -import { IConnectedUser, GroupDTO } from '../../types'; +import { IConnectedUser, GroupDTO, SpaceDTO, ChatStatus } from '../../types'; import { getEncryptedRequest } from './crypto'; import { ENV } from '../../constants'; import * as AES from './aes'; @@ -46,9 +46,9 @@ export interface IApproveRequestPayload { export interface ICreateGroupRequestPayload { groupName: string; - groupDescription: string; + groupDescription: string | null; members: Array; - groupImage: string; + groupImage: string | null; admins: Array; isPublic: boolean; contractAddressNFT?: string; @@ -62,7 +62,7 @@ export interface ICreateGroupRequestPayload { export interface IUpdateGroupRequestPayload { groupName: string; - groupImage: string; + groupImage: string | null; members: Array; admins: Array; address: string; @@ -164,9 +164,9 @@ export const approveRequestPayload = ( export const createGroupPayload = ( groupName: string, - groupDescription: string, + groupDescription: string | null, members: Array, - groupImage: string, + groupImage: string | null, admins: Array, isPublic: boolean, groupCreator: string, @@ -175,7 +175,10 @@ export const createGroupPayload = ( numberOfNFTs?: number, contractAddressERC20?: string, numberOfERC20?: number, - meta?: string + meta?: string, + groupType?: string | null, + scheduleAt?: Date | null, + scheduleEnd?: Date | null ): ICreateGroupRequestPayload => { const body = { groupName: groupName, @@ -191,18 +194,56 @@ export const createGroupPayload = ( groupCreator: groupCreator, verificationProof: verificationProof, meta: meta, + groupType: groupType, + scheduleAt: scheduleAt, + scheduleEnd: scheduleEnd, }; return body; }; +export const groupDtoToSpaceDto = (groupDto: GroupDTO): SpaceDTO => { + const spaceDto: SpaceDTO = { + members: groupDto.members.map((member) => ({ + wallet: member.wallet, + publicKey: member.publicKey, + isSpeaker: member.isAdmin, + image: member.image, + })), + pendingMembers: groupDto.pendingMembers.map((pendingMember) => ({ + wallet: pendingMember.wallet, + publicKey: pendingMember.publicKey, + isSpeaker: pendingMember.isAdmin, + image: pendingMember.image, + })), + contractAddressERC20: groupDto.contractAddressERC20, + numberOfERC20: groupDto.numberOfERC20, + contractAddressNFT: groupDto.contractAddressNFT, + numberOfNFTTokens: groupDto.numberOfNFTTokens, + verificationProof: groupDto.verificationProof, + spaceImage: groupDto.groupImage, + spaceName: groupDto.groupName, + isPublic: groupDto.isPublic, + spaceDescription: groupDto.groupDescription, + spaceCreator: groupDto.groupCreator, + spaceId: groupDto.chatId, + scheduleAt: groupDto.scheduleAt, + scheduleEnd: groupDto.scheduleEnd, + status: groupDto.status ?? null, + }; + return spaceDto; +}; + export const updateGroupPayload = ( groupName: string, - groupImage: string, - groupDescription: string, + groupImage: string | null, + groupDescription: string | null, members: Array, admins: Array, address: string, verificationProof: string, + scheduleAt?: Date | null, + scheduleEnd?: Date | null, + status?: ChatStatus | null, meta?: string | null ): IUpdateGroupRequestPayload => { const body = { @@ -213,7 +254,110 @@ export const updateGroupPayload = ( admins: admins, address: address, verificationProof: verificationProof, + scheduleAt: scheduleAt, + scheduleEnd: scheduleEnd, + status: status, ...(meta !== undefined && { meta: meta }), }; return body; }; + +// helper.ts + +export const getAdminsList = ( + members: { + wallet: string; + publicKey: string; + isAdmin: boolean; + image: string; + }[], + pendingMembers: { + wallet: string; + publicKey: string; + isAdmin: boolean; + image: string; + }[] +): Array => { + const adminsFromMembers = members + ? convertToWalletAddressList(members.filter((admin) => admin.isAdmin)) + : []; + + const adminsFromPendingMembers = pendingMembers + ? convertToWalletAddressList( + pendingMembers.filter((admin) => admin.isAdmin) + ) + : []; + + const adminList = [...adminsFromMembers, ...adminsFromPendingMembers]; + return adminList; +}; + +export const getSpaceAdminsList = ( + members: { + wallet: string; + publicKey: string; + isSpeaker: boolean; + image: string; + }[], + pendingMembers: { + wallet: string; + publicKey: string; + isSpeaker: boolean; + image: string; + }[] +): Array => { + const adminsFromMembers = members + ? convertToWalletAddressList(members.filter((admin) => admin.isSpeaker)) + : []; + + const adminsFromPendingMembers = pendingMembers + ? convertToWalletAddressList( + pendingMembers.filter((admin) => admin.isSpeaker) + ) + : []; + + const adminList = [...adminsFromMembers, ...adminsFromPendingMembers]; + return adminList; +}; + +export const convertToWalletAddressList = ( + memberList: { wallet: string }[] +): string[] => { + return memberList ? memberList.map((member) => member.wallet) : []; +}; + +export const getMembersList = ( + members: { + wallet: string; + publicKey: string; + isAdmin: boolean; + image: string; + }[], + pendingMembers: { + wallet: string; + publicKey: string; + isAdmin: boolean; + image: string; + }[] +): Array => { + const allMembers = [...(members || []), ...(pendingMembers || [])]; + return convertToWalletAddressList(allMembers); +}; + +export const getSpacesMembersList = ( + members: { + wallet: string; + publicKey: string; + isSpeaker: boolean; + image: string; + }[], + pendingMembers: { + wallet: string; + publicKey: string; + isSpeaker: boolean; + image: string; + }[] +): Array => { + const allMembers = [...(members || []), ...(pendingMembers || [])]; + return convertToWalletAddressList(allMembers); +}; diff --git a/packages/restapi/src/lib/chat/helpers/validator.ts b/packages/restapi/src/lib/chat/helpers/validator.ts index d21a23cca..a81bfe251 100644 --- a/packages/restapi/src/lib/chat/helpers/validator.ts +++ b/packages/restapi/src/lib/chat/helpers/validator.ts @@ -4,7 +4,7 @@ import { } from '../../helpers'; export const createGroupRequestValidator = ( - groupName: string, groupDescription: string,members: Array < string > , admins: Array < string > , contractAddressNFT ? : string, + groupName: string, groupDescription: string | null,members: Array < string > , admins: Array < string > , contractAddressNFT ? : string, numberOfNFTs ? : number, contractAddressERC20 ? : string, numberOfERC20 ? : number @@ -59,8 +59,89 @@ export const createGroupRequestValidator = ( } }; +export const createSpaceRequestValidator = ( + spaceName: string, spaceDescription: string | null,members: Array < string > , admins: Array < string > , contractAddressNFT ? : string, + numberOfNFTs ? : number, + contractAddressERC20 ? : string, + numberOfERC20 ? : number +): void => { + + if (spaceName == null || spaceName.length == 0) { + throw new Error(`spaceName cannot be null or empty`); + } + + if (spaceName.length > 50) { + throw new Error(`groupName cannot be more than 50 characters`); + } + + if (spaceDescription && spaceDescription.length > 150) { + throw new Error(`spaceDescription cannot be more than 150 characters`); + } + + if (members == null) { + throw new Error(`members cannot be null`); + } + + for (let i = 0; i < members.length; i++) { + if (members[i] && !isValidETHAddress(members[i])) { + throw new Error(`Invalid member address!`); + } + } + + if (admins == null) { + throw new Error(`admins cannot be null`); + } + + for (let i = 0; i < admins.length; i++) { + if (!isValidETHAddress(admins[i])) { + throw new Error(`Invalid admin address!`); + } + } + + if (contractAddressNFT != null && contractAddressNFT?.length > 0 && !isValidNFTCAIP10Address(contractAddressNFT)) { + throw new Error(`Invalid contractAddressNFT address!`); + } + + if (numberOfNFTs != null && numberOfNFTs < 0) { + throw new Error(`numberOfNFTs cannot be negative number`); + } + + if (contractAddressERC20 != null && contractAddressERC20?.length > 0 && !isValidNFTCAIP10Address(contractAddressERC20)) { + throw new Error(`Invalid contractAddressERC20 address!`); + } + + if (numberOfERC20 != null && numberOfERC20 < 0) { + throw new Error(`numberOfERC20 cannot be negative number`); + } +}; + +export const validateScheduleDates = (scheduleAt?: Date | null, + scheduleEnd ? : Date | null): void => { + + if (scheduleAt) { + const start = new Date(scheduleAt) + const now = new Date() + + if (start < now) { + throw new Error('Schedule start time must be in the future.') + } + + if (scheduleEnd) { + const end = new Date(scheduleEnd) + + if (end < now) { + throw new Error('Schedule end time must be in the future.') + } + + if (start >= end) { + throw new Error('Schedule start time must be earlier than end time.') + } + } + } +}; + export const updateGroupRequestValidator = ( - chatId: string, groupName: string, groupDescription: string, profilePicture: string, members: Array < string > , + chatId: string, groupName: string, groupDescription: string | null, members: Array < string > , admins: Array < string > , address: string ): void => { @@ -73,10 +154,6 @@ export const updateGroupRequestValidator = ( throw new Error(`groupName cannot be null or empty`); } - if (profilePicture == null || profilePicture.length == 0) { - throw new Error(`profilePicture cannot be null or empty`); - } - if (groupName != null && groupName.length > 50) { throw new Error(`groupName cannot be more than 50 characters`); } diff --git a/packages/restapi/src/lib/chat/index.ts b/packages/restapi/src/lib/chat/index.ts index 8588cabd3..0a5c3fdbd 100644 --- a/packages/restapi/src/lib/chat/index.ts +++ b/packages/restapi/src/lib/chat/index.ts @@ -14,3 +14,7 @@ export * from './createGroup'; export * from './updateGroup'; export * from './getGroup'; export * from './getGroupByName'; +export * from './addMembers'; +export * from './addAdmins'; +export * from './removeMembers'; +export * from './removeAdmins'; diff --git a/packages/restapi/src/lib/chat/removeAdmins.ts b/packages/restapi/src/lib/chat/removeAdmins.ts new file mode 100644 index 000000000..c0d49936b --- /dev/null +++ b/packages/restapi/src/lib/chat/removeAdmins.ts @@ -0,0 +1,111 @@ +import { isValidETHAddress, walletToPCAIP10 } from '../helpers'; +import Constants from '../constants'; +import { EnvOptionsType, SignerType, GroupDTO } from '../types'; +import { + getWallet, + getMembersList, + getAdminsList +} from './helpers'; +import { + getGroup +} from './getGroup'; +import { + updateGroup +} from './updateGroup'; +export interface RemoveAdminsFromGroupType extends EnvOptionsType { + chatId: string; + admins: Array; + account?: string | null; + signer?: SignerType | null; + pgpPrivateKey?: string | null; +} + +/** + * Update Group information + */ +export const removeAdmins = async ( + options: RemoveAdminsFromGroupType +): Promise => { + const { + chatId, + admins, + account = null, + signer = null, + env = Constants.ENV.PROD, + pgpPrivateKey = null, + } = options || {}; + try { + if (account == null && signer == null) { + throw new Error(`At least one from account or signer is necessary!`); + } + + if (!admins || admins.length === 0) { + throw new Error("Admin address array cannot be empty!"); + } + + admins.forEach((admin) => { + if (!isValidETHAddress(admin)) { + throw new Error(`Invalid admin address: ${admin}`); + } + }); + + const group = await getGroup({ + chatId: chatId, + env, + }) + + let convertedMembers = getMembersList( + group.members, group.pendingMembers + ); + + const adminsToBeRemoved = admins.map((admin) => walletToPCAIP10(admin)); + + adminsToBeRemoved.forEach((admin) => { + if (!convertedMembers.includes(admin)) { + throw new Error(`Member ${admin} not present in the list`); + } + }); + + let convertedAdmins = getAdminsList( + group.members, group.pendingMembers + ); + + adminsToBeRemoved.forEach((admin) => { + if (!convertedAdmins.includes(admin)) { + throw new Error(`Admin ${admin} not present in the list`); + } + }); + + convertedMembers = convertedMembers.filter( + (member) => !adminsToBeRemoved.includes(member) + ); + + convertedAdmins = convertedAdmins.filter( + (member) => !adminsToBeRemoved.includes(member) + ); + + return await updateGroup({ + chatId: chatId, + groupName: group.groupName, + groupImage: group.groupImage, + groupDescription: group.groupDescription, + members: convertedMembers, + admins: convertedAdmins, + scheduleAt: group.scheduleAt, + scheduleEnd: group.scheduleEnd, + status: group.status, + account: account, + signer: signer, + env: env, + pgpPrivateKey: pgpPrivateKey + }); + } catch (err) { + console.error( + `[Push SDK] - API - Error - API ${removeAdmins.name} -: `, + err + ); + throw Error( + `[Push SDK] - API - Error - API ${removeAdmins.name} -: ${err}` + ); + } +}; diff --git a/packages/restapi/src/lib/chat/removeMembers.ts b/packages/restapi/src/lib/chat/removeMembers.ts new file mode 100644 index 000000000..4cc513df8 --- /dev/null +++ b/packages/restapi/src/lib/chat/removeMembers.ts @@ -0,0 +1,97 @@ +import { isValidETHAddress, walletToPCAIP10 } from '../helpers'; +import Constants from '../constants'; +import { EnvOptionsType, SignerType, GroupDTO } from '../types'; +import { + getMembersList, + getAdminsList +} from './helpers'; +import { + getGroup +} from './getGroup'; +import { + updateGroup +} from './updateGroup'; +export interface RemoveMembersFromGroupType extends EnvOptionsType { + chatId: string; + members: Array; + account?: string | null; + signer?: SignerType | null; + pgpPrivateKey?: string | null; +} + +export const removeMembers = async ( + options: RemoveMembersFromGroupType +): Promise => { + const { + chatId, + members, + account = null, + signer = null, + env = Constants.ENV.PROD, + pgpPrivateKey = null, + } = options || {}; + try { + if (account == null && signer == null) { + throw new Error(`At least one from account or signer is necessary!`); + } + + if (!members || members.length === 0) { + throw new Error("Member address array cannot be empty!"); + } + + members.forEach((member) => { + if (!isValidETHAddress(member)) { + throw new Error(`Invalid member address: ${member}`); + } + }); + + const group = await getGroup({ + chatId: chatId, + env, + }) + + let convertedMembers = getMembersList( + group.members, group.pendingMembers + ); + + const membersToBeRemoved = members.map((member) => walletToPCAIP10(member)); + + membersToBeRemoved.forEach((member) => { + if (!convertedMembers.includes(member)) { + throw new Error(`Member ${member} not present in the list`); + } + }); + + convertedMembers = convertedMembers.filter( + (member) => !membersToBeRemoved.includes(member) + ); + + const convertedAdmins = getAdminsList( + group.members, group.pendingMembers + ); + + return await updateGroup({ + chatId: chatId, + groupName: group.groupName, + groupImage: group.groupImage, + groupDescription: group.groupDescription, + members: convertedMembers, + admins: convertedAdmins, + scheduleAt: group.scheduleAt, + scheduleEnd: group.scheduleEnd, + status: group.status, + account: account, + signer: signer, + env: env, + pgpPrivateKey: pgpPrivateKey + }); + } catch (err) { + console.error( + `[Push SDK] - API - Error - API ${removeMembers.name} -: `, + err + ); + throw Error( + `[Push SDK] - API - Error - API ${removeMembers.name} -: ${err}` + ); + } +}; diff --git a/packages/restapi/src/lib/chat/send.ts b/packages/restapi/src/lib/chat/send.ts index 84d9810da..fcc1a5856 100644 --- a/packages/restapi/src/lib/chat/send.ts +++ b/packages/restapi/src/lib/chat/send.ts @@ -25,6 +25,7 @@ export const send = async ( account = null, signer = null, env = Constants.ENV.PROD, + } = options || {}; try { diff --git a/packages/restapi/src/lib/chat/updateGroup.ts b/packages/restapi/src/lib/chat/updateGroup.ts index 92c1762d9..2a381ac1f 100644 --- a/packages/restapi/src/lib/chat/updateGroup.ts +++ b/packages/restapi/src/lib/chat/updateGroup.ts @@ -1,29 +1,33 @@ import axios from 'axios'; import { getAPIBaseUrls } from '../helpers'; import Constants from '../constants'; -import { EnvOptionsType, GroupDTO, SignerType } from '../types'; +import { ChatStatus, EnvOptionsType, GroupDTO, SignerType } from '../types'; import { IUpdateGroupRequestPayload, updateGroupPayload, sign, - updateGroupRequestValidator, getWallet, getAccountAddress, getUserDID, getConnectedUserV2, + updateGroupRequestValidator, + validateScheduleDates, } from './helpers'; import * as CryptoJS from 'crypto-js'; export interface ChatUpdateGroupType extends EnvOptionsType { - account?: string; - signer?: SignerType; + account?: string | null; + signer?: SignerType | null; chatId: string; groupName: string; - groupImage: string; + groupImage: string | null; groupDescription: string; members: Array; admins: Array; - pgpPrivateKey?: string; + pgpPrivateKey?: string | null; + scheduleAt?: Date | null; + scheduleEnd?: Date | null; + status?: ChatStatus | null; // If meta is not passed, old meta is not affected // If passed as null will update to null // If passed as string will update to that value @@ -47,6 +51,9 @@ export const updateGroup = async ( signer = null, env = Constants.ENV.PROD, pgpPrivateKey = null, + scheduleAt, + scheduleEnd, + status, meta, } = options || {}; try { @@ -60,11 +67,12 @@ export const updateGroup = async ( chatId, groupName, groupDescription, - groupImage, members, admins, address ); + validateScheduleDates(scheduleAt, scheduleEnd); + const connectedUser = await getConnectedUserV2(wallet, pgpPrivateKey, env); const convertedMembersPromise = members.map(async (each) => { return getUserDID(each, env); @@ -99,6 +107,9 @@ export const updateGroup = async ( convertedAdmins, connectedUser.did, verificationProof, + scheduleAt, + scheduleEnd, + status, meta ); diff --git a/packages/restapi/src/lib/index.ts b/packages/restapi/src/lib/index.ts index e6d504b46..a1d55b3a1 100644 --- a/packages/restapi/src/lib/index.ts +++ b/packages/restapi/src/lib/index.ts @@ -4,6 +4,7 @@ import * as user from './user'; import * as utils from './utils'; import * as payloads from './payloads'; import * as chat from './chat'; +import * as space from './space'; import * as video from "./video" export * from './types'; @@ -15,5 +16,6 @@ export { utils, payloads, chat, + space, video } \ No newline at end of file diff --git a/packages/restapi/src/lib/payloads/constants.ts b/packages/restapi/src/lib/payloads/constants.ts index fc0eca252..8930689f9 100644 --- a/packages/restapi/src/lib/payloads/constants.ts +++ b/packages/restapi/src/lib/payloads/constants.ts @@ -46,6 +46,36 @@ export enum NOTIFICATION_TYPE { export enum ADDITIONAL_META_TYPE { CUSTOM = 0, PUSH_VIDEO = 1, + PUSH_SPACE = 2, +} + +// Subset of ADDITIONAL_META_TYPE, to be used exclusively for Push Video, Spaces +export enum VIDEO_CALL_TYPE { + PUSH_VIDEO = 1, + PUSH_SPACE = 2, +} + +export enum SPACE_REQUEST_TYPE { + JOIN_SPEAKER, // space has started, join as a speaker + ESTABLISH_MESH, // request to establish mesh connection + INVITE_TO_PROMOTE, // host invites someone to be promoted as the speaker + REQUEST_TO_PROMOTE, // someone requests the host to be promoted to a spaeker +} + +export enum SPACE_ACCEPT_REQUEST_TYPE { + ACCEPT_JOIN_SPEAKER, + ACCEPT_INVITE, + ACCEPT_PROMOTION, +} + +export enum SPACE_DISCONNECT_TYPE { + STOP, // space is stopped/ended + LEAVE // speaker leaves a space +} + +export enum SPACE_INVITE_ROLES { + CO_HOST, + SPEAKER, } export const DEFAULT_DOMAIN = 'push.org'; diff --git a/packages/restapi/src/lib/payloads/index.ts b/packages/restapi/src/lib/payloads/index.ts index 67ef80fe5..22436ff9a 100644 --- a/packages/restapi/src/lib/payloads/index.ts +++ b/packages/restapi/src/lib/payloads/index.ts @@ -1,2 +1,9 @@ export * from './sendNotifications'; -export {NOTIFICATION_TYPE, IDENTITY_TYPE} from './constants' +export { + NOTIFICATION_TYPE, + IDENTITY_TYPE, + ADDITIONAL_META_TYPE, + SPACE_REQUEST_TYPE, + SPACE_ACCEPT_REQUEST_TYPE, + SPACE_DISCONNECT_TYPE +} from './constants'; diff --git a/packages/restapi/src/lib/space/Space.ts b/packages/restapi/src/lib/space/Space.ts new file mode 100644 index 000000000..942271874 --- /dev/null +++ b/packages/restapi/src/lib/space/Space.ts @@ -0,0 +1,230 @@ +import { produce } from 'immer'; + +import Constants from '../constants'; +import { Video, initVideoCallData } from '../video'; +import { update } from './update'; +import { start } from './start'; +import { inviteToPromote } from './inviteToPromote'; +import { acceptPromotionInvite } from './acceptPromotionInvite'; +import { connectInvitee } from './connectInvitee'; +import { rejectPromotionInvite } from './rejectPromotionInvite'; +import { requestToBePromoted } from './requestToBePromoted'; +import { acceptPromotionRequest } from './acceptPromotionRequest'; +import { rejectPromotionRequest } from './rejectPromotionRequest'; +import { connectPromotor } from './connectPromotor'; +import { addSpeaker } from './addSpeaker'; +import { removeSpeaker } from './removeSpeaker'; +import { join } from './join'; +import { leave } from './leave'; +import { stop } from './stop'; +import { initialize } from './initialize'; +import addToMergedStream from './helpers/addToMergedStream'; + +import { VideoStreamMerger } from 'video-stream-merger'; +import { + ChatStatus, + EnvOptionsType, + SignerType, + SpaceDTO, + SpaceData, +} from '../types'; +import { VIDEO_CALL_TYPE } from '../payloads/constants'; + +const initSpaceSpecificData = { + members: [], + pendingMembers: [], + contractAddressERC20: null, + numberOfERC20: -1, + contractAddressNFT: null, + numberOfNFTTokens: -1, + verificationProof: '', + spaceImage: null, + spaceName: '', + isPublic: false, + spaceDescription: '', + spaceCreator: '', + spaceId: '', + scheduleAt: null, + scheduleEnd: null, + status: null, + inviteeDetails: {}, +}; + +export const initSpaceData = { + ...initSpaceSpecificData, + connectionData: initVideoCallData, +}; + +export interface SpaceConstructorType extends EnvOptionsType { + signer: SignerType; + pgpPrivateKey: string; + chainId: number; + address: string; + setSpaceData: (fn: (data: SpaceData) => SpaceData) => void; +} + +// declaring the Space class + export class Space extends Video { + /* + - temporarily store the streamKey on the class + - will be used by the host to cast to the stream + */ + // protected streamKey: string | null = null; + + protected mergeStreamObject: VideoStreamMerger | null = null; + + protected spaceSpecificData: SpaceDTO; + protected setSpaceSpecificData: (fn: (data: SpaceDTO) => SpaceDTO) => void; + + // will be exposed and should be used from outside the class to change state + setSpaceData: (fn: (data: SpaceData) => SpaceData) => void; + + constructor(options: SpaceConstructorType) { + const { + signer, + pgpPrivateKey, + address, + chainId, + env = Constants.ENV.PROD, + setSpaceData, // to update the 'spaceData' state maintained by the developer + } = options || {}; + + // init the Video class + super({ + signer, + chainId, + pgpPrivateKey, + env, + callType: VIDEO_CALL_TYPE.PUSH_SPACE, + onReceiveStream: (receivedStream: MediaStream) => { + // for a space, that has started broadcast & the local peer is the host + if ( + this.spaceSpecificData.status === ChatStatus.ACTIVE && + this.data.meta.broadcast?.hostAddress && + this.data.meta.broadcast.hostAddress === this.data.local.address + ) { + addToMergedStream(this.mergeStreamObject!, receivedStream); + } + }, + setData: function () { + return; + }, // setData will be overridden below + }); + + // setting state changing functions + + /* + - Will be used internally in the class + - Overriding setData (Video) + - To be used when we only want to modify video call 'data' + */ + this.setData = function (fn) { + const newVideoData = fn(this.data); + + // update the react state + setSpaceData(() => ({ + ...this.spaceSpecificData, + connectionData: newVideoData, + })); + + // update the video class variable + this.data = newVideoData; + }; + + /* + - Will be used internally in the class + - To be used when we only want to modify space specific 'data' + */ + this.setSpaceSpecificData = function (fn) { + const newSpaceSpecificData = fn(this.spaceSpecificData); + + // update the react state + setSpaceData(() => ({ + ...newSpaceSpecificData, + connectionData: this.data, + })); + + // update the video class variable + this.spaceSpecificData = newSpaceSpecificData; + }; + + // set the space state updating function + this.setSpaceData = function (fn) { + const { connectionData: newConnectionData, ...newSpaceSpecificData } = fn( + { + ...this.spaceSpecificData, + connectionData: this.data, + } + ); + + // update the space specific data + this.spaceSpecificData = newSpaceSpecificData; + + // update the video data and update the external state + this.setData(() => newConnectionData); + }; + + // initializing state + + // set the local address inside video call 'data' + this.setData((oldVideoCallData) => { + return produce(oldVideoCallData, (draft) => { + draft.local.address = address; + }); + }); + + // init the state maintained by the developer + setSpaceData(() => initSpaceData); + + // init the spaceSpecificData class variable + this.spaceSpecificData = initSpaceSpecificData; + }; + + + // adding instance methods + + public initialize = initialize; + + public update = update; + + public createAudioStream = async () => { + await this.create({ audio: true, video: false }); + }; + + public start = start; + + // to promote a listener to a speaker/co-host + public inviteToPromote = inviteToPromote; + public acceptPromotionInvite = acceptPromotionInvite; + public connectInvitee = connectInvitee; + public rejectPromotionInvite = rejectPromotionInvite; + + // listener requests to be promoted to a speaker + public requestToBePromoted = requestToBePromoted; + public acceptPromotionRequest = acceptPromotionRequest; + public connectPromotor = connectPromotor; + public rejectPromotionRequest = rejectPromotionRequest; + + /* + - add/remove speaker to the space group as admins + - these methods are only to be used when the space hasnt started yet + */ + public addSpeaker = addSpeaker; + public removeSpeaker = removeSpeaker; + + /* + - add/remove co-host to the space group as admins + - add/remove them from the meta message + - these methods are only to be used when the space hasnt started yet + */ + // public addCoHost = addCoHost; + // public removeCoHost = removeCoHost; + + // add listner to the space group as member + public join = join; + + public leave = leave; + public stop = stop; +} + +export default Space; diff --git a/packages/restapi/src/lib/space/acceptPromotionInvite.ts b/packages/restapi/src/lib/space/acceptPromotionInvite.ts new file mode 100644 index 000000000..bb7765e05 --- /dev/null +++ b/packages/restapi/src/lib/space/acceptPromotionInvite.ts @@ -0,0 +1,28 @@ +import { SPACE_ACCEPT_REQUEST_TYPE } from '../payloads/constants'; +import type Space from './Space'; + +export interface AcceptPromotionInviteType { + signalData: any; + invitorAddress: string; + spaceId: string; +} + +export async function acceptPromotionInvite( + this: Space, + options: AcceptPromotionInviteType +) { + const { signalData, invitorAddress, spaceId } = + options || {}; + + // accept the promotion invite + this.acceptRequest({ + signalData, + senderAddress: this.data.local.address, + recipientAddress: invitorAddress, + chatId: spaceId, + details: { + type: SPACE_ACCEPT_REQUEST_TYPE.ACCEPT_INVITE, + data: {}, + }, + }); +} diff --git a/packages/restapi/src/lib/space/acceptPromotionRequest.ts b/packages/restapi/src/lib/space/acceptPromotionRequest.ts new file mode 100644 index 000000000..1d733d12e --- /dev/null +++ b/packages/restapi/src/lib/space/acceptPromotionRequest.ts @@ -0,0 +1,33 @@ +import { + SPACE_ACCEPT_REQUEST_TYPE, + SPACE_INVITE_ROLES, +} from '../payloads/constants'; +import type Space from './Space'; + +export interface AcceptPromotionRequestType { + signalData: any; + promoteeAddress: string; + role: SPACE_INVITE_ROLES; + spaceId: string; +} + +export async function acceptPromotionRequest( + this: Space, + options: AcceptPromotionRequestType +) { + const { signalData, promoteeAddress, spaceId, role } = options || {}; + + // TODO: change the role of promoteeAddress from listner to 'role' + + // accept the promotion request + this.acceptRequest({ + signalData, + senderAddress: this.data.local.address, + recipientAddress: promoteeAddress, + chatId: spaceId, + details: { + type: SPACE_ACCEPT_REQUEST_TYPE.ACCEPT_PROMOTION, + data: {}, + }, + }); +} diff --git a/packages/restapi/src/lib/space/addListeners.ts b/packages/restapi/src/lib/space/addListeners.ts new file mode 100644 index 000000000..995959456 --- /dev/null +++ b/packages/restapi/src/lib/space/addListeners.ts @@ -0,0 +1,49 @@ +import Constants from '../constants'; +import { EnvOptionsType, SignerType, SpaceDTO } from '../types'; +import { + groupDtoToSpaceDto +} from '../chat/helpers'; + + +import { addMembers } from '../chat/addMembers'; + +export interface AddListenersToSpaceType extends EnvOptionsType { + spaceId: string; + listeners: Array; + account?: string; + signer?: SignerType; + pgpPrivateKey?: string; +} + +export const addListeners = async ( + options: AddListenersToSpaceType +): Promise => { + const { + spaceId, + listeners, + account = null, + signer = null, + env = Constants.ENV.PROD, + pgpPrivateKey = null, + } = options || {}; + try { + const group = await addMembers({ + chatId: spaceId, + members: listeners, + account: account, + signer: signer, + env: env, + pgpPrivateKey: pgpPrivateKey + }); + + return groupDtoToSpaceDto(group); + } catch (err) { + console.error( + `[Push SDK] - API - Error - API ${addListeners.name} -: `, + err + ); + throw Error( + `[Push SDK] - API - Error - API ${addListeners.name} -: ${err}` + ); + } +}; diff --git a/packages/restapi/src/lib/space/addSpeaker.ts b/packages/restapi/src/lib/space/addSpeaker.ts new file mode 100644 index 000000000..37924f724 --- /dev/null +++ b/packages/restapi/src/lib/space/addSpeaker.ts @@ -0,0 +1,34 @@ +import { EnvOptionsType } from '../types'; +import { groupDtoToSpaceDto } from '../chat/helpers'; +import { addAdmins } from '../chat/addAdmins'; + +import type Space from './Space'; + +export interface AddSpeakerType extends EnvOptionsType { + address: string; +} + +export async function addSpeaker( + this: Space, + options: AddSpeakerType +): Promise { + const { address } = options; + try { + const group = await addAdmins({ + chatId: this.spaceSpecificData.spaceId, + admins: [address], + signer: this.signer, + env: this.env, + pgpPrivateKey: this.pgpPrivateKey, + }); + + // update space specific data + this.setSpaceSpecificData(() => groupDtoToSpaceDto(group)); + } catch (err) { + console.error( + `[Push SDK] - API - Error - API ${addSpeaker.name} -: `, + err + ); + throw Error(`[Push SDK] - API - Error - API ${addSpeaker.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/addSpeakers.ts b/packages/restapi/src/lib/space/addSpeakers.ts new file mode 100644 index 000000000..f7121363f --- /dev/null +++ b/packages/restapi/src/lib/space/addSpeakers.ts @@ -0,0 +1,33 @@ +import Constants from '../constants'; +import { EnvOptionsType, SignerType, SpaceDTO } from '../types'; +import { groupDtoToSpaceDto } from '../chat/helpers'; +import { addAdmins } from '../chat/addAdmins'; + +export interface AddSpeakersToSpaceType extends EnvOptionsType { + spaceId: string; + speakers: Array; + signer: SignerType; + pgpPrivateKey?: string; +} + +export const addSpeakers = async ( + options: AddSpeakersToSpaceType +): Promise => { + const { + spaceId, + speakers, + signer = null, + env = options?.env ?? Constants.ENV.PROD, + pgpPrivateKey = options?.pgpPrivateKey ?? null, + } = options; + + const group = await addAdmins({ + chatId: spaceId, + admins: speakers, + signer: signer, + env: env, + pgpPrivateKey: pgpPrivateKey, + }); + + return groupDtoToSpaceDto(group); +}; diff --git a/packages/restapi/src/lib/space/approve.ts b/packages/restapi/src/lib/space/approve.ts new file mode 100644 index 000000000..61b426fcc --- /dev/null +++ b/packages/restapi/src/lib/space/approve.ts @@ -0,0 +1,58 @@ +import { + isValidETHAddress, +} from '../helpers'; +import Constants from '../constants'; +import { + EnvOptionsType, + SignerType +} from '../types'; +import { + approve as approveRequest +} from '../chat/approveRequest'; +interface ApproveRequestOptionsType extends EnvOptionsType { + senderAddress: string; + pgpPrivateKey ? : string | null; + status ? : 'Approved'; + account ? : string | null; + signer ? : SignerType | null; +} + +export const approve = async ( + options: ApproveRequestOptionsType +): Promise < string > => { + const { + status = 'Approved', + account = null, + signer = null, + senderAddress, // space id + env = Constants.ENV.PROD, + pgpPrivateKey = null, + } = options || {}; + + try { + + if (account == null && signer == null) { + throw new Error(`At least one from account or signer is necessary!`); + } + + if (!isValidETHAddress(senderAddress) && !senderAddress.startsWith("spaces:")) { + throw new Error("Not a valid spaceId or ETH address"); + } + return await approveRequest({ + status: status, + account: account, + signer: signer, + senderAddress: senderAddress, + env: env, + pgpPrivateKey: pgpPrivateKey + }) + } catch (err) { + console.error( + `[Push SDK] - API - Error - API ${approve.name} -: `, + err + ); + throw Error( + `[Push SDK] - API - Error - API ${approve.name} -: ${err}` + ); + } +}; diff --git a/packages/restapi/src/lib/space/connectInvitee.ts b/packages/restapi/src/lib/space/connectInvitee.ts new file mode 100644 index 000000000..3c25144ed --- /dev/null +++ b/packages/restapi/src/lib/space/connectInvitee.ts @@ -0,0 +1,30 @@ +import { produce } from 'immer'; +import type Space from './Space'; + +export interface ConnectInviteeType { + signalData: any; + inviteeAddress: string; +} + +export async function connectInvitee(this: Space, options: ConnectInviteeType) { + const { signalData, inviteeAddress } = options || {}; + + // check for invalid invite + if ( + !this.spaceSpecificData?.inviteeDetails || + !Object.keys(this.spaceSpecificData.inviteeDetails).includes(inviteeAddress) + ) { + return Promise.resolve(); + } + + const role = this.spaceSpecificData.inviteeDetails[inviteeAddress]; + this.setSpaceSpecificData((oldData) => { + return produce(oldData, (draft) => { + if (draft.inviteeDetails) delete draft.inviteeDetails[inviteeAddress]; + }); + }); + // TODO: On backend change the role of inviteeAddress + + // complete the webRTC connection + this.connect({ signalData, peerAddress: inviteeAddress }); +} diff --git a/packages/restapi/src/lib/space/connectPromotor.ts b/packages/restapi/src/lib/space/connectPromotor.ts new file mode 100644 index 000000000..4d3151239 --- /dev/null +++ b/packages/restapi/src/lib/space/connectPromotor.ts @@ -0,0 +1,13 @@ +import type Space from './Space'; + +export interface ConnectPromotorType { + signalData: any; + promotorAddress: string; +} + +export async function connectPromotor(this: Space, options: ConnectPromotorType) { + const { signalData, promotorAddress } = options || {}; + + // complete the webRTC connection + this.connect({ signalData, peerAddress: promotorAddress }); +} diff --git a/packages/restapi/src/lib/space/create.ts b/packages/restapi/src/lib/space/create.ts new file mode 100644 index 000000000..3a76b5d22 --- /dev/null +++ b/packages/restapi/src/lib/space/create.ts @@ -0,0 +1,70 @@ +import Constants from '../constants'; +import { EnvOptionsType, SignerType, SpaceDTO } from '../types'; +import { groupDtoToSpaceDto } from './../chat/helpers'; +import { createGroup } from '../chat/createGroup'; + +export interface ChatCreateSpaceType extends EnvOptionsType { + signer: SignerType; + spaceName: string; + spaceDescription: string; + listeners: Array; + spaceImage: string | null; + speakers: Array; + isPublic: boolean; + contractAddressNFT?: string; + numberOfNFTs?: number; + contractAddressERC20?: string; + numberOfERC20?: number; + pgpPrivateKey?: string; + meta?: string; + scheduleAt: Date; + scheduleEnd?: Date | null; +} + +export async function create(options: ChatCreateSpaceType): Promise { + const { + signer, + spaceName, + spaceDescription, + listeners, + spaceImage, + speakers, + isPublic, + contractAddressNFT, + numberOfNFTs, + contractAddressERC20, + numberOfERC20, + env = Constants.ENV.PROD, + pgpPrivateKey = null, + meta, + scheduleAt, + scheduleEnd, + } = options || {}; + + try { + const group = await createGroup({ + signer, + groupName: spaceName, + groupDescription: spaceDescription, + members: listeners, + groupImage: spaceImage, + admins: speakers, + isPublic: isPublic, + contractAddressNFT: contractAddressNFT, + numberOfNFTs: numberOfNFTs, + contractAddressERC20: contractAddressERC20, + numberOfERC20: numberOfERC20, + env, + pgpPrivateKey, + meta: meta, + groupType: 'spaces', + scheduleAt: scheduleAt, + scheduleEnd: scheduleEnd, + }); + + return groupDtoToSpaceDto(group); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${create.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${create.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/get.ts b/packages/restapi/src/lib/space/get.ts new file mode 100644 index 000000000..75a6c0e79 --- /dev/null +++ b/packages/restapi/src/lib/space/get.ts @@ -0,0 +1,39 @@ +import Constants, { + ENV +} from '../constants'; +import { + SpaceDTO +} from '../types'; +import { + groupDtoToSpaceDto +} from './../chat/helpers'; +import { + getGroup +} from '../chat/getGroup'; + +export interface GetSpaceType { + spaceId: string, + env ? : ENV +} + +export const get = async ( + options: GetSpaceType +): Promise < SpaceDTO > => { + const { + spaceId, + env = Constants.ENV.PROD + } = options || {}; + try { + if (spaceId == null || spaceId.length == 0) { + throw new Error(`spaceId cannot be null or empty`); + } + const group = await getGroup({ + chatId: spaceId, + env + }) + return groupDtoToSpaceDto(group); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${get.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${get.name} -: ${err}`); + } +}; \ No newline at end of file diff --git a/packages/restapi/src/lib/space/helpers/addToMergedStream.ts b/packages/restapi/src/lib/space/helpers/addToMergedStream.ts new file mode 100644 index 000000000..9e939e893 --- /dev/null +++ b/packages/restapi/src/lib/space/helpers/addToMergedStream.ts @@ -0,0 +1,10 @@ +import type { VideoStreamMerger } from 'video-stream-merger'; + +const addToMergedStream = ( + mergeObject: VideoStreamMerger, + streamToBeAdded: MediaStream +) => { + mergeObject.addStream(streamToBeAdded, undefined); +}; + +export default addToMergedStream; diff --git a/packages/restapi/src/lib/space/helpers/getMergeStreamObject.ts b/packages/restapi/src/lib/space/helpers/getMergeStreamObject.ts new file mode 100644 index 000000000..a1322f823 --- /dev/null +++ b/packages/restapi/src/lib/space/helpers/getMergeStreamObject.ts @@ -0,0 +1,14 @@ +import { VideoStreamMerger } from 'video-stream-merger'; + +const getMergeStreamObject = (hostStream: MediaStream) => { + const mergeStreamObject = new VideoStreamMerger(); + + // add the audio stream of host + mergeStreamObject.addStream(hostStream, undefined); + + mergeStreamObject.start(); + + return mergeStreamObject; +}; + +export default getMergeStreamObject; diff --git a/packages/restapi/src/lib/space/index.ts b/packages/restapi/src/lib/space/index.ts new file mode 100644 index 000000000..6891e3d60 --- /dev/null +++ b/packages/restapi/src/lib/space/index.ts @@ -0,0 +1,14 @@ +export * from './spaces'; +export * from './trending'; +export * from './get'; +export * from './info'; +export * from './create'; +export * from './update_out'; +export * from './addSpeakers'; +export * from './removeSpeakers'; +export * from './addListeners'; +export * from './removeListeners'; +export * from './approve'; +export * from './requests'; + +export * from './Space' diff --git a/packages/restapi/src/lib/space/info.ts b/packages/restapi/src/lib/space/info.ts new file mode 100644 index 000000000..d7363372e --- /dev/null +++ b/packages/restapi/src/lib/space/info.ts @@ -0,0 +1,33 @@ +import { + SpaceDTO +} from '../types'; +import { + groupDtoToSpaceDto +} from './../chat/helpers'; +import { GetSpaceType } from './get'; +import { + getGroup +} from '../chat/getGroup'; +import Constants from '../constants'; + +export const info = async ( + options: GetSpaceType +): Promise < SpaceDTO > => { + const { + spaceId, + env = Constants.ENV.PROD + } = options || {}; + try { + if (spaceId == null || spaceId.length == 0) { + throw new Error(`spaceId cannot be null or empty`); + } + const group = await getGroup({ + chatId: spaceId, + env + }) + return groupDtoToSpaceDto(group); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${info.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${info.name} -: ${err}`); + } +}; \ No newline at end of file diff --git a/packages/restapi/src/lib/space/initialize.ts b/packages/restapi/src/lib/space/initialize.ts new file mode 100644 index 000000000..85f3dc682 --- /dev/null +++ b/packages/restapi/src/lib/space/initialize.ts @@ -0,0 +1,17 @@ +import type Space from './Space'; +import { get } from './get'; + +export interface InitializeType { + spaceId: string; +} + +export async function initialize(this: Space, options: InitializeType) { + const { spaceId } = options || {}; + + const space = await get({ + spaceId, + env: this.env, + }); + + this.setSpaceSpecificData(() => space); +} diff --git a/packages/restapi/src/lib/space/inviteToPromote.ts b/packages/restapi/src/lib/space/inviteToPromote.ts new file mode 100644 index 000000000..dd5644be3 --- /dev/null +++ b/packages/restapi/src/lib/space/inviteToPromote.ts @@ -0,0 +1,35 @@ +import { produce } from 'immer'; +import { SPACE_INVITE_ROLES, SPACE_REQUEST_TYPE } from '../payloads/constants'; +import type Space from './Space'; + +export interface InviteToPromoteType { + inviteeAddress: string; + role: SPACE_INVITE_ROLES; +} + +export async function inviteToPromote( + this: Space, + options: InviteToPromoteType +) { + const { inviteeAddress, role } = options || {}; + + // adding address to the invitee map + this.setSpaceSpecificData((oldData) => { + return produce(oldData, (draft) => { + if (draft.inviteeDetails) draft.inviteeDetails[inviteeAddress] = role; + }); + }); + + // we send a request to 'inviteeAddress' and try to add them to the mesh connection + this.request({ + senderAddress: this.data.local.address, + recipientAddress: inviteeAddress, + chatId: this.spaceSpecificData.spaceId, + details: { + type: SPACE_REQUEST_TYPE.INVITE_TO_PROMOTE, + data: { + role, + }, + }, + }); +} diff --git a/packages/restapi/src/lib/space/join.ts b/packages/restapi/src/lib/space/join.ts new file mode 100644 index 000000000..7e3342c59 --- /dev/null +++ b/packages/restapi/src/lib/space/join.ts @@ -0,0 +1,83 @@ +import { + SPACE_REQUEST_TYPE, +} from '../payloads/constants'; +import { ChatStatus } from '../types'; +import { approve } from './approve'; +import { get } from './get'; +import type Space from './Space'; + +/** + * + * @param options + * recievedVideoData: only required when joining as a speaker + */ +export async function join(this: Space) { + try { + const space = await get({ + spaceId: this.spaceSpecificData.spaceId, + env: this.env, + }); + + if (space.status !== ChatStatus.ACTIVE) + throw new Error('Space not active yet'); + + // checking what is the current role of caller address + + let isSpeaker = false; + let isListner = false; + space.members.forEach((member) => { + if (member.wallet === this.data.local.address) { + if (member.isSpeaker) { + isSpeaker = true; + } else { + isListner = true; + } + } + }); + let isSpeakerPending = false; + space.pendingMembers.forEach((pendingMember) => { + if ( + pendingMember.wallet === this.data.local.address && + pendingMember.isSpeaker + ) { + isSpeakerPending = true; + } + }); + + // acc to the found role (speaker or listner), executing req logic + + // if speaker is pending then approve first or if listner is pending/not found then approve first + if (isSpeakerPending || !isListner) { + await approve({ + signer: this.signer, + pgpPrivateKey: this.pgpPrivateKey, + senderAddress: this.spaceSpecificData.spaceId, + env: this.env, + }); + } + + if (isSpeaker || isSpeakerPending) { + // Call the host and join the mesh connection + const hostAddress = space.spaceCreator.replace('eip155:', ''); + await this.request({ + senderAddress: this.data.local.address, + recipientAddress: hostAddress, + chatId: this.spaceSpecificData.spaceId, + details: { + type: SPACE_REQUEST_TYPE.JOIN_SPEAKER, + data: {}, + }, + }); + } + + const updatedSpace = await get({ + spaceId: this.spaceSpecificData.spaceId, + env: this.env, + }); + // update space specific data + this.setSpaceSpecificData(() => updatedSpace); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${join.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${join.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/leave.ts b/packages/restapi/src/lib/space/leave.ts new file mode 100644 index 000000000..12121a86c --- /dev/null +++ b/packages/restapi/src/lib/space/leave.ts @@ -0,0 +1,26 @@ +import type Space from './Space'; +import { SPACE_DISCONNECT_TYPE } from '../payloads/constants'; + +export async function leave(this: Space): Promise { + try { + // should be only called by the host or the speakers + + // if the host is leaving then we need to make someone else the host + + // handle the case where a listner is leaving + + // disconnect with every incoming peer in the mesh connection + this.data.incoming.forEach(({ address }) => { + this.disconnect({ + peerAddress: address, + details: { + type: SPACE_DISCONNECT_TYPE.LEAVE, + data: {}, + }, + }); + }); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${stop.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${stop.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/rejectPromotionInvite.ts b/packages/restapi/src/lib/space/rejectPromotionInvite.ts new file mode 100644 index 000000000..6eff90156 --- /dev/null +++ b/packages/restapi/src/lib/space/rejectPromotionInvite.ts @@ -0,0 +1,18 @@ +import type Space from './Space'; + +export interface RejectPromotionInviteType { + invitorAddress: string; +} + +export async function rejectPromotionInvite( + this: Space, + options: RejectPromotionInviteType +) { + const { invitorAddress } = + options || {}; + + // reject the promotion invite + this.disconnect({ + peerAddress: invitorAddress, + }); +} diff --git a/packages/restapi/src/lib/space/rejectPromotionRequest.ts b/packages/restapi/src/lib/space/rejectPromotionRequest.ts new file mode 100644 index 000000000..b4eddee56 --- /dev/null +++ b/packages/restapi/src/lib/space/rejectPromotionRequest.ts @@ -0,0 +1,17 @@ +import type Space from './Space'; + +export interface RejectPromotionRequestType { + promoteeAddress: string; +} + +export async function rejectPromotionRequest( + this: Space, + options: RejectPromotionRequestType +) { + const { promoteeAddress } = options || {}; + + // reject the promotion request + this.disconnect({ + peerAddress: promoteeAddress, + }); +} diff --git a/packages/restapi/src/lib/space/removeListeners.ts b/packages/restapi/src/lib/space/removeListeners.ts new file mode 100644 index 000000000..30ab12f5e --- /dev/null +++ b/packages/restapi/src/lib/space/removeListeners.ts @@ -0,0 +1,49 @@ +import Constants from '../constants'; +import { EnvOptionsType, SignerType, SpaceDTO } from '../types'; +import { + groupDtoToSpaceDto +} from '../chat/helpers'; +import { + removeMembers +} from '../chat/removeMembers'; + +export interface RemoveListenersFromSpaceType extends EnvOptionsType { + spaceId: string; + listeners: Array; + account?: string; + signer?: SignerType; + pgpPrivateKey?: string; +} + +export const removeListeners = async ( + options: RemoveListenersFromSpaceType +): Promise => { + const { + spaceId, + listeners, + account = null, + signer = null, + env = Constants.ENV.PROD, + pgpPrivateKey = null, + } = options || {}; + try { + const group = await removeMembers({ + chatId: spaceId, + members: listeners, + account: account, + signer: signer, + env: env, + pgpPrivateKey: pgpPrivateKey + }); + + return groupDtoToSpaceDto(group); + } catch (err) { + console.error( + `[Push SDK] - API - Error - API ${removeListeners.name} -: `, + err + ); + throw Error( + `[Push SDK] - API - Error - API ${removeListeners.name} -: ${err}` + ); + } +}; diff --git a/packages/restapi/src/lib/space/removeSpeaker.ts b/packages/restapi/src/lib/space/removeSpeaker.ts new file mode 100644 index 000000000..84c214d02 --- /dev/null +++ b/packages/restapi/src/lib/space/removeSpeaker.ts @@ -0,0 +1,37 @@ +import { EnvOptionsType } from '../types'; +import { groupDtoToSpaceDto } from '../chat/helpers'; +import { + removeAdmins +} from '../chat/removeAdmins'; +import type Space from './Space'; + +export interface RemoveSpeakerType extends EnvOptionsType { + address: string; +} + +export async function removeSpeaker( + this: Space, + options: RemoveSpeakerType +): Promise { + const { address } = options; + try { + const group = await removeAdmins({ + chatId: this.spaceSpecificData.spaceId, + admins: [address], + signer: this.signer, + env: this.env, + pgpPrivateKey: this.pgpPrivateKey, + }); + + // update space specific data + this.setSpaceSpecificData(() => groupDtoToSpaceDto(group)); + } catch (err) { + console.error( + `[Push SDK] - API - Error - API ${removeSpeaker.name} -: `, + err + ); + throw Error( + `[Push SDK] - API - Error - API ${removeSpeaker.name} -: ${err}` + ); + } +} diff --git a/packages/restapi/src/lib/space/removeSpeakers.ts b/packages/restapi/src/lib/space/removeSpeakers.ts new file mode 100644 index 000000000..e72137957 --- /dev/null +++ b/packages/restapi/src/lib/space/removeSpeakers.ts @@ -0,0 +1,41 @@ +import Constants from '../constants'; +import { EnvOptionsType, SignerType, SpaceDTO } from '../types'; +import { groupDtoToSpaceDto } from '../chat/helpers'; +import { removeAdmins } from '../chat/removeAdmins'; +export interface RemoveSpeakersFromSpaceType extends EnvOptionsType { + spaceId: string; + speakers: Array; + signer: SignerType; + pgpPrivateKey?: string; +} + +export const removeSpeakers = async ( + options: RemoveSpeakersFromSpaceType +): Promise => { + const { + spaceId, + speakers, + signer = null, + env = Constants.ENV.PROD, + pgpPrivateKey = null, + } = options || {}; + try { + const group = await removeAdmins({ + chatId: spaceId, + admins: speakers, + signer: signer, + env: env, + pgpPrivateKey: pgpPrivateKey, + }); + + return groupDtoToSpaceDto(group); + } catch (err) { + console.error( + `[Push SDK] - API - Error - API ${removeSpeakers.name} -: `, + err + ); + throw Error( + `[Push SDK] - API - Error - API ${removeSpeakers.name} -: ${err}` + ); + } +}; diff --git a/packages/restapi/src/lib/space/requestToBePromoted.ts b/packages/restapi/src/lib/space/requestToBePromoted.ts new file mode 100644 index 000000000..b52992841 --- /dev/null +++ b/packages/restapi/src/lib/space/requestToBePromoted.ts @@ -0,0 +1,28 @@ +import { SPACE_INVITE_ROLES, SPACE_REQUEST_TYPE } from '../payloads/constants'; +import type Space from './Space'; + +export interface RequestToBePromotedType { + role: SPACE_INVITE_ROLES; + spaceId: string; + promotorAddress: string; +} + +export async function requestToBePromoted( + this: Space, + options: RequestToBePromotedType +) { + const { role, spaceId, promotorAddress } = options || {}; + + // requesting host to include local computer into the mesh connection + this.request({ + senderAddress: this.data.local.address, + recipientAddress: promotorAddress, + chatId: spaceId, + details: { + type: SPACE_REQUEST_TYPE.REQUEST_TO_PROMOTE, + data: { + role, + }, + }, + }); +} diff --git a/packages/restapi/src/lib/space/requests.ts b/packages/restapi/src/lib/space/requests.ts new file mode 100644 index 000000000..6f85dd131 --- /dev/null +++ b/packages/restapi/src/lib/space/requests.ts @@ -0,0 +1,65 @@ +import axios from 'axios'; +import { getAPIBaseUrls, isValidETHAddress } from '../helpers'; +import Constants, { ENV } from '../constants'; +import { SpaceIFeeds } from '../types'; +import { getSpaceInboxLists, getUserDID } from '../chat/helpers'; + +export type RequestOptionsType = { + account: string; + pgpPrivateKey?: string; + /** + * If true, the method will return decrypted message content in response + */ + toDecrypt?: boolean; + /** + * page index - default 1 + */ + page?: number; + /** + * no of items per page - default 10 - max 30 + */ + limit?: number; + /** + * Environment variable + */ + env?: ENV; +}; + +/** + * The first time an address wants to send a message to another peer, the address sends an intent request. This first message shall not land in this peer Inbox but in its Request box. + * This function will return all the chats that landed on the address' Request box. The user can then approve the request or ignore it for now. + */ +export const requests = async ( + options: RequestOptionsType +): Promise => { + const { + account, + pgpPrivateKey, + env = Constants.ENV.PROD, + toDecrypt = false, + page = 1, + limit = 10, + } = options || {}; + const user = await getUserDID(account, env); + const API_BASE_URL = getAPIBaseUrls(env); + const apiEndpoint = `${API_BASE_URL}/v1/spaces/users/${user}/requests?page=${page}&limit=${limit}`; + try { + if (!isValidETHAddress(user)) { + throw new Error(`Invalid address!`); + } + const response = await axios.get(apiEndpoint); + const requests: SpaceIFeeds[] = response.data.requests; + const Feeds: SpaceIFeeds[] = await getSpaceInboxLists({ + lists: requests, + user, + toDecrypt, + pgpPrivateKey, + env, + }); + + return Feeds; + } catch (err) { + console.error(`[Push SDK] - API ${requests.name}: `, err); + throw Error(`[Push SDK] - API ${requests.name}: ${err}`); + } +}; diff --git a/packages/restapi/src/lib/space/spaces.ts b/packages/restapi/src/lib/space/spaces.ts new file mode 100644 index 000000000..e23253071 --- /dev/null +++ b/packages/restapi/src/lib/space/spaces.ts @@ -0,0 +1,62 @@ +import axios from 'axios'; +import { getAPIBaseUrls, isValidETHAddress } from '../helpers'; +import Constants, { ENV } from '../constants'; +import { SpaceIFeeds } from '../types'; +import { getSpaceInboxLists, getUserDID } from '../chat/helpers'; + +export type ChatsOptionsType = { + account: string; + pgpPrivateKey?: string; + /** + * If true, the method will return decrypted message content in response + */ + toDecrypt?: boolean; + /** + * page index - default 1 + */ + page?: number; + /** + * no of items per page - default 10 - max 30 + */ + limit?: number; + /** + * Environment variable + */ + env?: ENV; +}; + +/** + * Return the latest message from all wallet addresses you have talked to. This can be used when building the inbox page. + */ +export const spaces = async (options: ChatsOptionsType): Promise => { + const { + account, + pgpPrivateKey, + env = Constants.ENV.PROD, + page = 1, + limit = 10, + } = options || {}; + if (!isValidETHAddress(account)) { + throw new Error(`Invalid address!`); + } + const user = await getUserDID(account, env); + const API_BASE_URL = getAPIBaseUrls(env); + const apiEndpoint = `${API_BASE_URL}/v1/spaces/users/${user}/spaces?page=${page}&limit=${limit}`; + const requestUrl = `${apiEndpoint}`; + try { + const toDecrypt = false; + const response = await axios.get(requestUrl); + const spaces: SpaceIFeeds[] = response.data.spaces; + const feeds: SpaceIFeeds[] = await getSpaceInboxLists({ + lists: spaces, + user: user, + toDecrypt, + pgpPrivateKey, + env, + }); + return feeds; + } catch (err) { + console.error(`[Push SDK] - API ${spaces.name}: `, err); + throw Error(`[Push SDK] - API ${spaces.name}: ${err}`); + } +}; diff --git a/packages/restapi/src/lib/space/start.ts b/packages/restapi/src/lib/space/start.ts new file mode 100644 index 000000000..f15f28449 --- /dev/null +++ b/packages/restapi/src/lib/space/start.ts @@ -0,0 +1,139 @@ +import { EnvOptionsType, SignerType, ChatStatus } from '../types'; +import { + groupDtoToSpaceDto, + getSpacesMembersList, + getSpaceAdminsList, +} from './../chat/helpers'; +import { get } from './get'; +import { updateGroup } from '../chat/updateGroup'; +import getMergeStreamObject from './helpers/getMergeStreamObject'; +import axios from 'axios'; +import { Client, isSupported } from '@livepeer/webrtmp-sdk'; + +export interface StartSpaceType extends EnvOptionsType { + spaceId: string; + account?: string; + signer?: SignerType; + pgpPrivateKey?: string; +} + +import type Space from './Space'; +import { produce } from 'immer'; + +type StartType = { + livepeerApiKey: string; +}; + +export async function start(this: Space, options: StartType): Promise { + const { livepeerApiKey } = options || {}; + + try { + // TODO: Only allow the host to execute this function + + // host should have there audio stream + if (!this.data.local.stream) { + throw new Error('Local audio stream not found'); + } + + const space = await get({ + spaceId: this.spaceSpecificData.spaceId, + env: this.env, + }); + + if (space.status !== ChatStatus.PENDING) { + throw new Error( + 'Unable to start the space as it is not in the pending state' + ); + } + + const convertedMembers = getSpacesMembersList( + space.members, + space.pendingMembers + ); + const convertedAdmins = getSpaceAdminsList( + space.members, + space.pendingMembers + ); + + const group = await updateGroup({ + chatId: this.spaceSpecificData.spaceId, + groupName: space.spaceName, + groupImage: space.spaceImage, + groupDescription: space.spaceDescription, + members: convertedMembers, + admins: convertedAdmins, + signer: this.signer, + env: this.env, + pgpPrivateKey: this.pgpPrivateKey, + scheduleAt: space.scheduleAt, + scheduleEnd: space.scheduleEnd, + status: ChatStatus.ACTIVE, + }); + + // update space data + this.setSpaceData((oldSpaceData) => { + return produce(oldSpaceData, (draft) => { + draft = { + ...groupDtoToSpaceDto(group), + connectionData: draft.connectionData, + }; + draft.connectionData.meta.broadcast = { + livepeerInfo: null, + hostAddress: this.data.local.address, + }; + }); + }); + + // start the livepeer playback and store the playback URL group meta + // send a notification/meta message to all the added listeners (members) telling the space has started + + // create the mergeStream object + const mergeStreamObject = getMergeStreamObject(this.data.local.stream); + // store the mergeStreamObject + this.mergeStreamObject = mergeStreamObject; + + const url = 'https://livepeer.studio/api/stream'; + const data = { + name: this.spaceSpecificData.spaceName, + record: true, + }; + + const { data: responseData } = await axios.post(url, data, { + headers: { + Authorization: 'Bearer ' + livepeerApiKey, + }, + }); + + const { streamKey, playbackId } = responseData; + + console.log('livepeer details', streamKey, playbackId); + + // TODO: store the playbackId on group meta data, temp -> groupDescription + this.update({ spaceDescription: playbackId }); + + if (!isSupported()) { + console.log('webrtmp-sdk is not currently supported on this browser'); + } + + // cast to the stream + const client = new Client(); + const session = client.cast(mergeStreamObject.result!, streamKey); + session.on('open', () => { + console.log('Live stream started.'); + // TODO: Update the space data + }); + + session.on('close', () => { + console.log('Live stream stopped.'); + // TODO: Update the space data + }); + + session.on('error', (err) => { + console.log('Live stream error.', err.message); + // TODO: Update the space data + }); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${start.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${start.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/stop.ts b/packages/restapi/src/lib/space/stop.ts new file mode 100644 index 000000000..4f69914ec --- /dev/null +++ b/packages/restapi/src/lib/space/stop.ts @@ -0,0 +1,72 @@ +import { + groupDtoToSpaceDto, + getSpacesMembersList, + getSpaceAdminsList, +} from '../chat/helpers'; +import { updateGroup } from '../chat/updateGroup'; +import { get } from './get'; + +import type Space from './Space'; +import { ChatStatus } from '../types'; +import { SPACE_DISCONNECT_TYPE } from '../payloads/constants'; + +export async function stop(this: Space): Promise { + try { + // should be only called by the host + + const space = await get({ + spaceId: this.spaceSpecificData.spaceId, + env: this.env, + }); + + if (space.status === ChatStatus.ENDED) { + throw new Error('Space already ended'); + } + + const convertedMembers = getSpacesMembersList( + space.members, + space.pendingMembers + ); + const convertedAdmins = getSpaceAdminsList( + space.members, + space.pendingMembers + ); + + const group = await updateGroup({ + chatId: this.spaceSpecificData.spaceId, + groupName: space.spaceName, + groupImage: space.spaceImage, + groupDescription: space.spaceDescription, + members: convertedMembers, + admins: convertedAdmins, + signer: this.signer, + env: this.env, + pgpPrivateKey: this.pgpPrivateKey, + scheduleAt: space.scheduleAt, + scheduleEnd: space.scheduleEnd, + status: ChatStatus.ENDED, + }); + + // update space specific data + this.setSpaceSpecificData(() => groupDtoToSpaceDto(group)); + + // stop livepeer playback + + /* + - disconnect with every incoming peer in the mesh connection + - other peers should also end their connections as we want to destroy the mesh connection + */ + this.data.incoming.forEach(({ address }) => { + this.disconnect({ + peerAddress: address, + details: { + type: SPACE_DISCONNECT_TYPE.STOP, + data: {}, + }, + }); + }); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${stop.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${stop.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/trending.ts b/packages/restapi/src/lib/space/trending.ts new file mode 100644 index 000000000..1a81830fe --- /dev/null +++ b/packages/restapi/src/lib/space/trending.ts @@ -0,0 +1,47 @@ +import axios from 'axios'; +import { getAPIBaseUrls } from '../helpers'; +import Constants, { ENV } from '../constants'; +import { SpaceIFeeds } from '../types'; +import { getTrendingSpaceInboxLists } from '../chat/helpers'; + +export type TrendingOptionsType = { + page?: number; + /** + * no of items per page - default 10 - max 30 + */ + limit?: number; + /** + * Environment variable + */ + env?: ENV; +}; + +/** + * The first time an address wants to send a message to another peer, the address sends an intent request. This first message shall not land in this peer Inbox but in its Request box. + * This function will return all the chats that landed on the address' Request box. The user can then approve the request or ignore it for now. + */ +export const trending = async ( + options: TrendingOptionsType +): Promise => { + const { + env = Constants.ENV.PROD, + page = 1, + limit = 10, + } = options || {}; + const API_BASE_URL = getAPIBaseUrls(env); + const apiEndpoint = `${API_BASE_URL}/v1/spaces/trending?page=${page}&limit=${limit}`; + try { + + const response = await axios.get(apiEndpoint); + const spaces: SpaceIFeeds[] = response.data.spaces; + const Feeds: SpaceIFeeds[] = await getTrendingSpaceInboxLists({ + lists: spaces, + env, + }); + + return Feeds; + } catch (err) { + console.error(`[Push SDK] - API ${trending.name}: `, err); + throw Error(`[Push SDK] - API ${trending.name}: ${err}`); + } +}; diff --git a/packages/restapi/src/lib/space/update.ts b/packages/restapi/src/lib/space/update.ts new file mode 100644 index 000000000..266baf456 --- /dev/null +++ b/packages/restapi/src/lib/space/update.ts @@ -0,0 +1,71 @@ +import { ChatStatus } from '../types'; +import { + getSpaceAdminsList, + getSpacesMembersList, + groupDtoToSpaceDto, +} from './../chat/helpers'; +import { updateGroup } from '../chat/updateGroup'; +import { get } from './get'; + +import type Space from './Space'; + +export interface ChatUpdateSpaceType { + spaceName?: string; + spaceImage?: string | null; + spaceDescription?: string; + scheduleAt?: Date; + scheduleEnd?: Date | null; +} + +export async function update( + this: Space, + options: ChatUpdateSpaceType +): Promise { + const { spaceName, spaceImage, spaceDescription, scheduleAt, scheduleEnd } = + options || {}; + try { + const space = await get({ + spaceId: this.spaceSpecificData.spaceId, + env: this.env, + }); + + const convertedMembers = getSpacesMembersList( + space.members, + space.pendingMembers + ); + const convertedAdmins = getSpaceAdminsList( + space.members, + space.pendingMembers + ); + + if (space.status === ChatStatus.ACTIVE && scheduleAt) { + throw new Error('Unable change the start date/time of an active space'); + } + + if (space.status === ChatStatus.ENDED && scheduleEnd) { + throw new Error('Unable change the end date/time of an ended space'); + } + + const group = await updateGroup({ + chatId: this.spaceSpecificData.spaceId, + groupName: spaceName ? spaceName : space.spaceName, + groupImage: spaceImage ? spaceImage : space.spaceImage, + groupDescription: spaceDescription + ? spaceDescription + : space.spaceDescription, + members: convertedMembers, + admins: convertedAdmins, + signer: this.signer, + env: this.env, + pgpPrivateKey: this.pgpPrivateKey, + scheduleAt: scheduleAt ? scheduleAt : space.scheduleAt, + scheduleEnd: scheduleEnd ? scheduleEnd : space.scheduleEnd, + }); + + // update space specific data + this.setSpaceSpecificData(() => groupDtoToSpaceDto(group)); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${update.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${update.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/update_out.ts b/packages/restapi/src/lib/space/update_out.ts new file mode 100644 index 000000000..bbc7199da --- /dev/null +++ b/packages/restapi/src/lib/space/update_out.ts @@ -0,0 +1,72 @@ +import Constants from '../constants'; +import { EnvOptionsType, SpaceDTO, SignerType, ChatStatus } from '../types'; +import { groupDtoToSpaceDto } from './../chat/helpers'; +import { updateGroup } from '../chat/updateGroup'; +import { get } from './get'; + +export interface ChatUpdateSpaceType extends EnvOptionsType { + signer: SignerType; + spaceId: string; + spaceName: string; + spaceImage: string | null; + spaceDescription: string; + listeners: Array; + speakers: Array; + pgpPrivateKey?: string; + scheduleAt: Date; + scheduleEnd?: Date | null; + status: ChatStatus; +} + +export const update = async ( + options: ChatUpdateSpaceType +): Promise => { + const { + spaceId, + spaceName, + spaceImage, + spaceDescription, + listeners, + speakers, + signer, + env = Constants.ENV.PROD, + pgpPrivateKey = null, + scheduleAt, + scheduleEnd, + status, + } = options || {}; + try { + const space = await get({ + spaceId, + env, + }); + + if (space.status === ChatStatus.ACTIVE && scheduleAt) { + throw new Error('Unable change the start date/time of an active space'); + } + + if (space.status === ChatStatus.ENDED && scheduleEnd) { + throw new Error('Unable change the end date/time of an ended space'); + } + + const group = await updateGroup({ + chatId: spaceId, + groupName: spaceName, + groupImage: spaceImage, + groupDescription: spaceDescription, + members: listeners, + admins: speakers, + signer: signer, + env: env, + pgpPrivateKey: pgpPrivateKey, + scheduleAt: scheduleAt, + scheduleEnd: scheduleEnd, + status: status, + }); + + return groupDtoToSpaceDto(group); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${update.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${update.name} -: ${err}`); + } +}; diff --git a/packages/restapi/src/lib/types/index.ts b/packages/restapi/src/lib/types/index.ts index 46bdb7612..a3b440803 100644 --- a/packages/restapi/src/lib/types/index.ts +++ b/packages/restapi/src/lib/types/index.ts @@ -3,6 +3,10 @@ import { ADDITIONAL_META_TYPE, IDENTITY_TYPE, NOTIFICATION_TYPE, + SPACE_ACCEPT_REQUEST_TYPE, + SPACE_DISCONNECT_TYPE, + SPACE_INVITE_ROLES, + SPACE_REQUEST_TYPE, } from '../../lib/payloads/constants'; import { ENV, MessageType } from '../constants'; import { EthEncryptedData } from '@metamask/eth-sig-util'; @@ -209,6 +213,25 @@ export interface IFeeds { deprecated?: boolean; // scope only at sdk level deprecatedCode?: string; // scope only at sdk level } + +export interface SpaceIFeeds { + msg: IMessageIPFS; + did: string; + wallets: string; + profilePicture: string | null; + name: string | null; + publicKey: string | null; + about: string | null; + threadhash: string | null; + intent: string | null; + intentSentBy: string | null; + intentTimestamp: Date; + combinedDID: string; + cid?: string; + spaceId?: string; + spaceInformation?: SpaceDTO; +} + export interface IUser { msgSent: number; maxMsgPersisted: number; @@ -280,6 +303,11 @@ export interface Member { publicKey: string; } +export enum ChatStatus { + ACTIVE = 'ACTIVE', + PENDING = 'PENDING', + ENDED = 'ENDED' +} export interface GroupDTO { members: { wallet: string; @@ -301,12 +329,47 @@ export interface GroupDTO { groupImage: string | null; groupName: string; isPublic: boolean; - groupDescription: string | null; + groupDescription: string; groupCreator: string; chatId: string; scheduleAt?: Date | null; scheduleEnd?: Date | null; - groupType: string; + groupType?: string; + status?: ChatStatus | null; +} + +export interface SpaceDTO { + members: { + wallet: string; + publicKey: string; + isSpeaker: boolean; + image: string; + }[]; + pendingMembers: { + wallet: string; + publicKey: string; + isSpeaker: boolean; + image: string; + }[]; + contractAddressERC20: string | null; + numberOfERC20: number; + contractAddressNFT: string | null; + numberOfNFTTokens: number; + verificationProof: string; + spaceImage: string | null; + spaceName: string; + isPublic: boolean; + spaceDescription: string; + spaceCreator: string; + spaceId: string; + scheduleAt?: Date | null; + scheduleEnd?: Date | null; + status: ChatStatus | null; + inviteeDetails?: { [key: string]: SPACE_INVITE_ROLES }; +} + +export interface SpaceData extends SpaceDTO { + connectionData: VideoCallData; } export interface Subscribers { @@ -486,7 +549,7 @@ export type VideoCallData = { broadcast?: { livepeerInfo: any; hostAddress: string; - coHostAddress: string; + coHostAddress?: string; }; }; local: { @@ -495,7 +558,7 @@ export type VideoCallData = { video: boolean | null; address: string; }; - incoming: [PeerData]; + incoming: PeerData[]; }; export type VideoCreateInputOptions = { @@ -506,10 +569,14 @@ export type VideoCreateInputOptions = { export type VideoRequestInputOptions = { senderAddress: string; - recipientAddress: string; + recipientAddress: string | string[]; chatId: string; onReceiveMessage?: (message: string) => void; retry?: boolean; + details?: { + type: SPACE_REQUEST_TYPE; + data: Record; + }; }; export type VideoAcceptRequestInputOptions = { @@ -519,16 +586,31 @@ export type VideoAcceptRequestInputOptions = { chatId: string; onReceiveMessage?: (message: string) => void; retry?: boolean; + details?: { + type: SPACE_ACCEPT_REQUEST_TYPE; + data: Record; + }; }; export type VideoConnectInputOptions = { signalData: any; + peerAddress: string; +}; + +export type VideoDisconnectOptions = { + peerAddress: string; + details?: { + type: SPACE_DISCONNECT_TYPE; + data: Record; + }; }; export type EnableVideoInputOptions = { state: boolean; + peerAddress: string; }; export type EnableAudioInputOptions = { state: boolean; + peerAddress: string; }; diff --git a/packages/restapi/src/lib/video/Video.ts b/packages/restapi/src/lib/video/Video.ts index 3fd2b7913..f1d340979 100644 --- a/packages/restapi/src/lib/video/Video.ts +++ b/packages/restapi/src/lib/video/Video.ts @@ -25,7 +25,16 @@ import { VideoCallStatus, EnableAudioInputOptions, EnableVideoInputOptions, + VideoDisconnectOptions, } from '../types'; +import getIncomingIndexFromAddress from './helpers/getIncomingIndexFromAddress'; +import getConnectedAddresses from './helpers/getConnectedAddresses'; +import getConnectToAddresses from './helpers/getConnectToAddresses'; +import { + SPACE_DISCONNECT_TYPE, + SPACE_REQUEST_TYPE, + VIDEO_CALL_TYPE, +} from '../payloads/constants'; export const initVideoCallData: VideoCallData = { meta: { @@ -34,6 +43,11 @@ export const initVideoCallData: VideoCallData = { address: '', signal: null, }, + broadcast: { + livepeerInfo: null, + hostAddress: '', + coHostAddress: '', + }, }, local: { stream: null, @@ -55,34 +69,46 @@ export const initVideoCallData: VideoCallData = { export class Video { // user, call related info - private signer: SignerType; - private chainId: number; - private pgpPrivateKey: string; - private env: ENV; + protected signer: SignerType; + protected chainId: number; + protected pgpPrivateKey: string; + protected env: ENV; + protected callType: VIDEO_CALL_TYPE; + protected onReceiveStream: (receivedStream: MediaStream) => void; // storing the peer instance - private peerInstance: any = null; + private peerInstances: { + [key: string]: any; + } = {}; - private data: VideoCallData; + protected data: VideoCallData; setData: (fn: (data: VideoCallData) => VideoCallData) => void; constructor({ signer, chainId, pgpPrivateKey, - env, + env = Constants.ENV.PROD, setData, + callType = VIDEO_CALL_TYPE.PUSH_VIDEO, + onReceiveStream = () => { + return; + }, }: { signer: SignerType; chainId: number; pgpPrivateKey: string; - env?: ENV; setData: (fn: (data: VideoCallData) => VideoCallData) => void; + env?: ENV; + callType?: VIDEO_CALL_TYPE; + onReceiveStream?: (receivedStream: MediaStream) => void; }) { this.signer = signer; this.chainId = chainId; this.pgpPrivateKey = pgpPrivateKey; - this.env = env ? env : Constants.ENV.PROD; + this.env = env; + this.callType = callType; + this.onReceiveStream = onReceiveStream; // init the react state setData(() => initVideoCallData); @@ -127,165 +153,260 @@ export class Video { async request(options: VideoRequestInputOptions): Promise { const { - senderAddress, // notification sender - recipientAddress, // notification receiver + senderAddress, + recipientAddress, chatId, onReceiveMessage = (message: string) => { console.log('received a meesage', message); }, retry = false, + details, } = options || {}; - try { - console.log( - 'request', - 'options', - options, - 'localStream', - this.data.local.stream - ); - - // fetching the iceServers config - const iceServerConfig = await getIceServerConfig(this.env); + console.log('request', 'options', options); - this.peerInstance = new Peer({ - initiator: true, - trickle: false, - stream: this.data.local.stream, - config: { - iceServers: iceServerConfig, - }, - }); + const recipientAddresses = Array.isArray(recipientAddress) + ? recipientAddress + : [recipientAddress]; - this.peerInstance.on('signal', (data: any) => { + for (const recipientAddress of recipientAddresses) { + try { + // set videoCallInfo state with status 1 (call initiated) this.setData((oldData) => { return produce(oldData, (draft) => { - draft.meta.initiator.signal = data; + draft.local.address = senderAddress; + draft.meta.chatId = chatId; + draft.meta.initiator.address = senderAddress; + + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + + if (incomingIndex === -1) { + draft.incoming.push({ + stream: null, + audio: null, + video: null, + address: recipientAddress, + status: retry + ? VideoCallStatus.RETRY_INITIALIZED + : VideoCallStatus.INITIALIZED, + retryCount: retry ? 1 : 0, + }); + } else { + draft.incoming[incomingIndex].address = recipientAddress; + draft.incoming[incomingIndex].status = retry + ? VideoCallStatus.RETRY_INITIALIZED + : VideoCallStatus.INITIALIZED; + draft.incoming[incomingIndex].retryCount += retry ? 1 : 0; + } }); }); - // sending notification to the recipientAddress with video call signaling data - sendVideoCallNotification( - { - signer: this.signer, - chainId: this.chainId, - pgpPrivateKey: this.pgpPrivateKey, + // fetching the iceServers config + const iceServerConfig = await getIceServerConfig(this.env); + this.peerInstances[recipientAddress] = new Peer({ + initiator: true, + trickle: false, + stream: this.data.local.stream, + config: { + iceServers: iceServerConfig, }, - { - senderAddress, - recipientAddress, - status: retry - ? VideoCallStatus.RETRY_INITIALIZED - : VideoCallStatus.INITIALIZED, - chatId, - signalData: data, - env: this.env, - } - ); - }); + }); - this.peerInstance.on('connect', () => { - this.peerInstance.send(`initial message from ${senderAddress}`); - this.peerInstance.send( - JSON.stringify({ - type: 'isVideoOn', - isVideoOn: this.data.local.video, - }) - ); - this.peerInstance.send( - JSON.stringify({ - type: 'isAudioOn', - isAudioOn: this.data.local.audio, - }) - ); - }); + this.peerInstances[recipientAddress].on('signal', (data: any) => { + this.setData((oldData) => { + return produce(oldData, (draft) => { + draft.meta.initiator.signal = data; + }); + }); - this.peerInstance.on('data', (data: any) => { - if (isJSON(data)) { - const parsedData = JSON.parse(data); - if (parsedData.type === 'isVideoOn') { - this.setData((oldData) => { - return produce(oldData, (draft) => { - draft.incoming[0].video = parsedData.isVideoOn; + // sending notification to the recipientAddress with video call signaling data + sendVideoCallNotification( + { + signer: this.signer, + chainId: this.chainId, + pgpPrivateKey: this.pgpPrivateKey, + }, + { + senderAddress, + recipientAddress, + status: retry + ? VideoCallStatus.RETRY_INITIALIZED + : VideoCallStatus.INITIALIZED, + chatId, + signalData: data, + env: this.env, + callType: this.callType, + callDetails: details, + } + ); + }); + + this.peerInstances[recipientAddress].on('connect', () => { + this.peerInstances[recipientAddress].send( + JSON.stringify({ + type: 'isVideoOn', + value: this.data.local.video, + }) + ); + this.peerInstances[recipientAddress].send( + JSON.stringify({ + type: 'isAudioOn', + value: this.data.local.audio, + }) + ); + }); + + this.peerInstances[recipientAddress].on('data', (data: any) => { + if (isJSON(data)) { + const parsedData = JSON.parse(data); + + if (parsedData.type === 'connectedAddress') { + console.log('CONNECTED ADDRESSES', parsedData.value); + + const receivedConnectedAddresses = parsedData.value; + const localConnectedAddresses = getConnectedAddresses({ + incomingPeers: this.data.incoming, }); - }); - } - if (parsedData.type === 'isAudioOn') { - this.setData((oldData) => { - return produce(oldData, (draft) => { - draft.incoming[0].audio = parsedData.isAudioOn; + // find out the address to which local peer is not connected to but the remote peer is + // then connect with them + const connectToAddresses = getConnectToAddresses({ + localAddress: senderAddress, + localConnectedAddresses, + receivedConnectedAddresses, }); - }); - } + for (const connectToAddress of connectToAddresses) { + this.request({ + senderAddress, + recipientAddress: connectToAddress, + chatId, + details: { + type: SPACE_REQUEST_TYPE.ESTABLISH_MESH, + data: {}, + }, + }); + } + } - if (parsedData.type === 'endCall') { - // destroy the peerInstance - this.peerInstance?.destroy(); - this.peerInstance = null; + if (parsedData.type === 'isVideoOn') { + console.log('IS VIDEO ON', parsedData.value); + this.setData((oldData) => { + return produce(oldData, (draft) => { + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].video = parsedData.value; + }); + }); + } - // destroy the local stream - if (this.data.local.stream) { - endStream(this.data.local.stream); + if (parsedData.type === 'isAudioOn') { + console.log('IS AUDIO ON', parsedData.value); + this.setData((oldData) => { + return produce(oldData, (draft) => { + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].audio = parsedData.value; + }); + }); } - // reset the state - this.setData(() => initVideoCallData); + if (parsedData.type === 'endCall') { + console.log('END CALL'); + + if ( + this.callType === VIDEO_CALL_TYPE.PUSH_SPACE && + parsedData?.details?.type === SPACE_DISCONNECT_TYPE.LEAVE + ) { + // destroy connection to only the current peer + this.peerInstances[recipientAddress]?.destroy(); + this.peerInstances[recipientAddress] = null; + this.setData((oldData) => { + return produce(oldData, (draft) => { + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming.splice(incomingIndex, 1); + }); + }); + } + if ( + this.callType === VIDEO_CALL_TYPE.PUSH_SPACE && + parsedData?.details?.type === SPACE_DISCONNECT_TYPE.STOP + ) { + // destroy connection to all the peers + for (const connectedAddress in this.peerInstances) { + this.peerInstances[connectedAddress]?.destroy(); + this.peerInstances[connectedAddress] = null; + } + } + + if ( + this.callType === VIDEO_CALL_TYPE.PUSH_VIDEO || + (this.callType === VIDEO_CALL_TYPE.PUSH_SPACE && + parsedData?.details?.type === SPACE_DISCONNECT_TYPE.STOP) + ) { + // destroy the local stream + if (this.data.local.stream) { + endStream(this.data.local.stream); + } + + // reset the state + this.setData(() => initVideoCallData); + } + } + } else { + onReceiveMessage(data); } - } else { - onReceiveMessage(data); - } - }); - - this.peerInstance.on('stream', (currentStream: MediaStream) => { - this.setData((oldData) => { - return produce(oldData, (draft) => { - draft.incoming[0].stream = currentStream; - }); }); - }); - // set videoCallInfo state with status 1 (call initiated) - this.setData((oldData) => { - return produce(oldData, (draft) => { - draft.local.address = senderAddress; - draft.incoming[0].address = recipientAddress; - draft.meta.chatId = chatId; - draft.meta.initiator.address = senderAddress; - draft.incoming[0].status = retry - ? VideoCallStatus.RETRY_INITIALIZED - : VideoCallStatus.INITIALIZED; - draft.incoming[0].retryCount += retry ? 1 : 0; - }); - }); - } catch (err) { - console.log('error in request', err); + this.peerInstances[recipientAddress].on( + 'stream', + (currentStream: MediaStream) => { + console.log('received incoming stream', currentStream); + this.onReceiveStream(currentStream); + this.setData((oldData) => { + return produce(oldData, (draft) => { + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].stream = currentStream; + }); + }); + } + ); + } catch (err) { + console.log('error in request', err); + } } } async acceptRequest(options: VideoAcceptRequestInputOptions): Promise { const { signalData, - senderAddress, // notification sender - recipientAddress, // notification receiver + senderAddress, + recipientAddress, chatId, onReceiveMessage = (message: string) => { console.log('received a meesage', message); }, retry = false, + details, } = options || {}; try { - console.log( - 'accept request', - 'options', - options, - 'peerInstance', - this.peerInstance - ); + console.log('accept request', 'options', options); // if peerInstance is not null -> acceptRequest/request was called before - if (this.peerInstance !== null) { + if (this.peerInstances[recipientAddress]) { // to prevent connection error we stop the exec of acceptRequest return Promise.resolve(); } @@ -294,20 +415,39 @@ export class Video { this.setData((oldData) => { return produce(oldData, (draft) => { draft.local.address = senderAddress; - draft.incoming[0].address = recipientAddress; draft.meta.chatId = chatId; draft.meta.initiator.address = senderAddress; - draft.incoming[0].status = retry - ? VideoCallStatus.RETRY_RECEIVED - : VideoCallStatus.RECEIVED; - draft.incoming[0].retryCount += retry ? 1 : 0; + + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + + if (incomingIndex === -1) { + draft.incoming.push({ + stream: null, + audio: null, + video: null, + address: recipientAddress, + status: retry + ? VideoCallStatus.RETRY_INITIALIZED + : VideoCallStatus.INITIALIZED, + retryCount: retry ? 1 : 0, + }); + } else { + draft.incoming[incomingIndex].address = recipientAddress; + draft.incoming[incomingIndex].status = retry + ? VideoCallStatus.RETRY_RECEIVED + : VideoCallStatus.RECEIVED; + draft.incoming[incomingIndex].retryCount += retry ? 1 : 0; + } }); }); // fetching the iceServers config const iceServerConfig = await getIceServerConfig(this.env); - this.peerInstance = new Peer({ + this.peerInstances[recipientAddress] = new Peer({ initiator: false, trickle: false, stream: this.data.local.stream, @@ -317,12 +457,12 @@ export class Video { }); // setup error handler - this.peerInstance.on('error', (err: any) => { + this.peerInstances[recipientAddress].on('error', (err: any) => { console.log('error in accept request', err); if (this.data.incoming[0].retryCount >= 5) { console.log('Max retries exceeded, please try again.'); - this.disconnect(); + this.disconnect({ peerAddress: recipientAddress }); } // retrying in case of connection error @@ -343,9 +483,9 @@ export class Video { ); }); - this.peerInstance.signal(signalData); + this.peerInstances[recipientAddress].signal(signalData); - this.peerInstance.on('signal', (data: any) => { + this.peerInstances[recipientAddress].on('signal', (data: any) => { this.setData((oldData) => { return produce(oldData, (draft) => { draft.meta.initiator.signal = data; @@ -367,112 +507,225 @@ export class Video { chatId, signalData: data, env: this.env, + callType: this.callType, + callDetails: details, } ); }); - this.peerInstance.on('connect', () => { - this.peerInstance.send('initial message from receiver'); - this.peerInstance.send( + this.peerInstances[recipientAddress].on('connect', () => { + this.peerInstances[recipientAddress].send( JSON.stringify({ type: 'isVideoOn', - isVideoOn: this.data.local.video, + value: this.data.local.video, }) ); - this.peerInstance.send( + this.peerInstances[recipientAddress].send( JSON.stringify({ type: 'isAudioOn', - isAudioOn: this.data.local.audio, + value: this.data.local.audio, }) ); // set videoCallInfo state with status connected for the receiver's end this.setData((oldData) => { return produce(oldData, (draft) => { - draft.incoming[0].status = VideoCallStatus.CONNECTED; + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].status = VideoCallStatus.CONNECTED; }); }); }); - this.peerInstance.on('data', (data: any) => { + this.peerInstances[recipientAddress].on('data', (data: any) => { if (isJSON(data)) { const parsedData = JSON.parse(data); + + if (parsedData.type === 'connectedAddress') { + console.log('CONNECTED ADDRESSES', parsedData.value); + + const receivedConnectedAddresses = parsedData.value; + const localConnectedAddresses = getConnectedAddresses({ + incomingPeers: this.data.incoming, + }); + + // find out the address to which local peer is not connected to but the remote peer is + // then connect with them + const connectToAddresses = getConnectToAddresses({ + localAddress: senderAddress, + localConnectedAddresses, + receivedConnectedAddresses, + }); + for (const connectToAddress of connectToAddresses) { + this.request({ + senderAddress, + recipientAddress: connectToAddress, + chatId, + details: { + type: SPACE_REQUEST_TYPE.ESTABLISH_MESH, + data: {}, + }, + }); + } + + // send the addresses the local peer is connected to remote peer + this.peerInstances[recipientAddress].send( + JSON.stringify({ + type: 'connectedAddresses', + value: localConnectedAddresses, + }) + ); + } + if (parsedData.type === 'isVideoOn') { + console.log('IS VIDEO ON', parsedData.value); this.setData((oldData) => { return produce(oldData, (draft) => { - draft.incoming[0].video = parsedData.isVideoOn; + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].video = parsedData.value; }); }); } if (parsedData.type === 'isAudioOn') { + console.log('IS AUDIO ON', parsedData.value); this.setData((oldData) => { return produce(oldData, (draft) => { - draft.incoming[0].audio = parsedData.isAudioOn; + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].audio = parsedData.value; }); }); } if (parsedData.type === 'endCall') { - // destroy the peerInstance - this.peerInstance?.destroy(); - this.peerInstance = null; - - // destroy the local stream - if (this.data.local.stream) { - endStream(this.data.local.stream); + console.log('END CALL'); + + if ( + this.callType === VIDEO_CALL_TYPE.PUSH_SPACE && + parsedData?.details?.type === SPACE_DISCONNECT_TYPE.LEAVE + ) { + // destroy connection to only the current peer + this.peerInstances[recipientAddress]?.destroy(); + this.peerInstances[recipientAddress] = null; + this.setData((oldData) => { + return produce(oldData, (draft) => { + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming.splice(incomingIndex, 1); + }); + }); + } + if ( + this.callType === VIDEO_CALL_TYPE.PUSH_SPACE && + parsedData?.details?.type === SPACE_DISCONNECT_TYPE.STOP + ) { + // destroy connection to all the peers + for (const connectedAddress in this.peerInstances) { + this.peerInstances[connectedAddress]?.destroy(); + this.peerInstances[connectedAddress] = null; + } } - // reset the state - this.setData(() => initVideoCallData); + if ( + this.callType === VIDEO_CALL_TYPE.PUSH_VIDEO || + (this.callType === VIDEO_CALL_TYPE.PUSH_SPACE && + parsedData?.details?.type === SPACE_DISCONNECT_TYPE.STOP) + ) { + // destroy the local stream + if (this.data.local.stream) { + endStream(this.data.local.stream); + } + + // reset the state + this.setData(() => initVideoCallData); + } } } else { onReceiveMessage(data); } }); - this.peerInstance.on('stream', (currentStream: MediaStream) => { - this.setData((oldData) => { - return produce(oldData, (draft) => { - draft.incoming[0].stream = currentStream; + this.peerInstances[recipientAddress].on( + 'stream', + (currentStream: MediaStream) => { + console.log('received incoming stream', currentStream); + this.onReceiveStream(currentStream); + this.setData((oldData) => { + return produce(oldData, (draft) => { + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].stream = currentStream; + }); }); - }); - }); + } + ); } catch (err) { console.log('error in accept request', err); } } connect(options: VideoConnectInputOptions): void { - const { signalData } = options || {}; + const { signalData, peerAddress } = options || {}; try { console.log('connect', 'options', options); // setup error handler - this.peerInstance.on('error', (err: any) => { + this.peerInstances[peerAddress].on('error', (err: any) => { console.log('error in connect', err); - if (this.data.incoming[0].retryCount >= 5) { + const incomingIndex = getIncomingIndexFromAddress( + this.data.incoming, + peerAddress + ); + + if (this.data.incoming[incomingIndex].retryCount >= 5) { console.log('Max retries exceeded, please try again.'); - this.disconnect(); + this.disconnect({ peerAddress }); } // retrying in case of connection error this.request({ senderAddress: this.data.local.address, - recipientAddress: this.data.incoming[0].address, + recipientAddress: this.data.incoming[incomingIndex].address, chatId: this.data.meta.chatId, retry: true, }); }); - this.peerInstance?.signal(signalData); + this.peerInstances[peerAddress]?.signal(signalData); + + // send the addresses the local peer is connected to remote peer + const connectedAddresses = getConnectedAddresses({ + incomingPeers: this.data.incoming, + }); + this.peerInstances[peerAddress].send( + JSON.stringify({ + type: 'connectedAddresses', + value: connectedAddresses, + }) + ); // set videoCallInfo state with status connected for the caller's end this.setData((oldData) => { return produce(oldData, (draft) => { - draft.incoming[0].status = VideoCallStatus.CONNECTED; + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + peerAddress + ); + draft.incoming[incomingIndex].status = VideoCallStatus.CONNECTED; }); }); } catch (err) { @@ -480,13 +733,27 @@ export class Video { } } - disconnect(): void { + disconnect(options: VideoDisconnectOptions): void { + const { peerAddress, details } = options || {}; + try { - console.log('disconnect', 'status', this.data.incoming[0].status); - if (this.data.incoming[0].status === VideoCallStatus.CONNECTED) { - this.peerInstance?.send( - JSON.stringify({ type: 'endCall', endCall: true }) + const incomingIndex = getIncomingIndexFromAddress( + this.data.incoming, + peerAddress + ); + + console.log( + 'disconnect', + 'status', + this.data.incoming[incomingIndex].status + ); + if ( + this.data.incoming[incomingIndex].status === VideoCallStatus.CONNECTED + ) { + this.peerInstances[peerAddress]?.send( + JSON.stringify({ type: 'endCall', value: true, details }) ); + this.peerInstances[peerAddress]?.destroy(); } else { // for disconnecting during status INITIALIZED, RECEIVED, RETRY_INITIALIZED, RETRY_RECEIVED // send a notif to the other user signaling status = DISCONNECTED @@ -498,18 +765,20 @@ export class Video { }, { senderAddress: this.data.local.address, - recipientAddress: this.data.incoming[0].address, + recipientAddress: this.data.incoming[incomingIndex].address, status: VideoCallStatus.DISCONNECTED, chatId: this.data.meta.chatId, signalData: null, env: this.env, + callType: this.callType, + callDetails: details, } ); } // destroy the peerInstance - this.peerInstance?.destroy(); - this.peerInstance = null; + this.peerInstances[peerAddress]?.destroy(); + this.peerInstances[peerAddress] = null; // destroy the local stream if (this.data.local.stream) { @@ -526,16 +795,23 @@ export class Video { // functions for enabling/disabling local audio and video enableVideo(options: EnableVideoInputOptions): void { - const { state } = options || {}; + const { state, peerAddress } = options || {}; if (this.data.local.video !== state) { // need to change the video state - if (this.data.incoming[0].status === VideoCallStatus.CONNECTED) { - this.peerInstance?.send( + const incomingIndex = getIncomingIndexFromAddress( + this.data.incoming, + peerAddress + ); + + if ( + this.data.incoming[incomingIndex].status === VideoCallStatus.CONNECTED + ) { + this.peerInstances[peerAddress]?.send( JSON.stringify({ type: 'isVideoOn', - isVideoOn: state, + value: state, }) ); } @@ -555,14 +831,21 @@ export class Video { } enableAudio(options: EnableAudioInputOptions): void { - const { state } = options || {}; + const { state, peerAddress } = options || {}; if (this.data.local.audio !== state) { // need to change the audio state - if (this.data.incoming[0].status === VideoCallStatus.CONNECTED) { - this.peerInstance?.send( - JSON.stringify({ type: 'isAudioOn', isAudioOn: state }) + const incomingIndex = getIncomingIndexFromAddress( + this.data.incoming, + peerAddress + ); + + if ( + this.data.incoming[incomingIndex].status === VideoCallStatus.CONNECTED + ) { + this.peerInstances[peerAddress]?.send( + JSON.stringify({ type: 'isAudioOn', value: state }) ); } if (this.data.local.stream) { diff --git a/packages/restapi/src/lib/video/helpers/getConnectToAddresses.ts b/packages/restapi/src/lib/video/helpers/getConnectToAddresses.ts new file mode 100644 index 000000000..6731ef169 --- /dev/null +++ b/packages/restapi/src/lib/video/helpers/getConnectToAddresses.ts @@ -0,0 +1,17 @@ +const getConnectToAddresses = ({ + localAddress, + localConnectedAddresses, + receivedConnectedAddresses, +}: { + localAddress: string; + localConnectedAddresses: string[]; + receivedConnectedAddresses: string[]; +}): string[] => { + return receivedConnectedAddresses.filter( + (receivedConnectedAddress) => + !localConnectedAddresses.includes(receivedConnectedAddress) && + receivedConnectedAddress !== localAddress + ); +}; + +export default getConnectToAddresses; diff --git a/packages/restapi/src/lib/video/helpers/getConnectedAddresses.ts b/packages/restapi/src/lib/video/helpers/getConnectedAddresses.ts new file mode 100644 index 000000000..7e9d9a149 --- /dev/null +++ b/packages/restapi/src/lib/video/helpers/getConnectedAddresses.ts @@ -0,0 +1,17 @@ +import { PeerData, VideoCallStatus } from '../../types'; + +const getConnectedAddresses = ({ + incomingPeers, +}: { + incomingPeers: PeerData[]; +}): string[] => { + const connectedAddresses: string[] = []; + incomingPeers.forEach((incomingPeer) => { + if (incomingPeer.status === VideoCallStatus.CONNECTED) { + connectedAddresses.push(incomingPeer.address); + } + }); + return connectedAddresses; +}; + +export default getConnectedAddresses; diff --git a/packages/restapi/src/lib/video/helpers/getIceServerConfig.ts b/packages/restapi/src/lib/video/helpers/getIceServerConfig.ts index 8e7acdad8..cb0d5ebaa 100644 --- a/packages/restapi/src/lib/video/helpers/getIceServerConfig.ts +++ b/packages/restapi/src/lib/video/helpers/getIceServerConfig.ts @@ -1,10 +1,20 @@ import axios from 'axios'; import { getAPIBaseUrls } from '../../helpers'; import Constants from '../../constants'; +import * as CryptoJS from 'crypto-js'; + +const ENCRYPTION_KEY = 'turnserversecret'; export const getIceServerConfig = async (env = Constants.ENV.PROD) => { const API_BASE_URL = getAPIBaseUrls(env); const apiEndpoint = `${API_BASE_URL}/v1/turnserver/iceconfig`; - const { data } = await axios.get(apiEndpoint); - return data; + const { data: encryptedData } = await axios.get(apiEndpoint); + + const { config: decryptedData } = JSON.parse( + CryptoJS.AES.decrypt(encryptedData, ENCRYPTION_KEY).toString( + CryptoJS.enc.Utf8 + ) + ); + + return decryptedData; }; diff --git a/packages/restapi/src/lib/video/helpers/getIncomingIndexFromAddress.ts b/packages/restapi/src/lib/video/helpers/getIncomingIndexFromAddress.ts new file mode 100644 index 000000000..e4c61cf44 --- /dev/null +++ b/packages/restapi/src/lib/video/helpers/getIncomingIndexFromAddress.ts @@ -0,0 +1,7 @@ +import { PeerData } from "../../types"; + +const getIncomingIndexFromAddress = (incomingPeers: PeerData[], address: string) => { + return incomingPeers.findIndex(incomingPeer => incomingPeer.address === address); +} + +export default getIncomingIndexFromAddress; diff --git a/packages/restapi/src/lib/video/helpers/sendVideoCallNotification.ts b/packages/restapi/src/lib/video/helpers/sendVideoCallNotification.ts index 07beed66c..935375d6e 100644 --- a/packages/restapi/src/lib/video/helpers/sendVideoCallNotification.ts +++ b/packages/restapi/src/lib/video/helpers/sendVideoCallNotification.ts @@ -1,9 +1,20 @@ import Constants, { ENV } from '../../constants'; import { getCAIPWithChainId } from '../../helpers'; import { sendNotification } from '../../payloads'; -import { ADDITIONAL_META_TYPE } from '../../payloads/constants'; +import { + NOTIFICATION_TYPE, + SPACE_ACCEPT_REQUEST_TYPE, + SPACE_DISCONNECT_TYPE, + SPACE_REQUEST_TYPE, + VIDEO_CALL_TYPE, +} from '../../payloads/constants'; import { SignerType, VideoCallStatus } from '../../types'; +interface CallDetailsType { + type: SPACE_REQUEST_TYPE | SPACE_ACCEPT_REQUEST_TYPE | SPACE_DISCONNECT_TYPE; + data: Record; +}; + interface VideoCallInfoType { recipientAddress: string; senderAddress: string; @@ -11,6 +22,8 @@ interface VideoCallInfoType { signalData: any; status: VideoCallStatus; env?: ENV; + callType?: VIDEO_CALL_TYPE; + callDetails?: CallDetailsType; } interface UserInfoType { @@ -19,12 +32,13 @@ interface UserInfoType { pgpPrivateKey: string; } -interface VideoDataType { +export interface VideoDataType { recipientAddress: string; senderAddress: string; chatId: string; signalData?: any; status: VideoCallStatus; + callDetails?: CallDetailsType; } const sendVideoCallNotification = async ( @@ -33,9 +47,11 @@ const sendVideoCallNotification = async ( recipientAddress, senderAddress, chatId, - signalData = null, status, + signalData = null, env = Constants.ENV.PROD, + callType = VIDEO_CALL_TYPE.PUSH_VIDEO, + callDetails }: VideoCallInfoType ) => { try { @@ -45,6 +61,7 @@ const sendVideoCallNotification = async ( chatId, signalData, status, + callDetails }; console.log('sendVideoCallNotification', 'videoData', videoData); @@ -57,12 +74,14 @@ const sendVideoCallNotification = async ( const notificationText = `Video Call from ${senderAddress}`; + const notificationType = NOTIFICATION_TYPE.TARGETTED; + await sendNotification({ senderType: 1, // for chat notification signer, pgpPrivateKey, chatId, - type: 3, + type: notificationType, identityType: 2, notification: { title: notificationText, @@ -74,9 +93,10 @@ const sendVideoCallNotification = async ( cta: '', img: '', additionalMeta: { - type: `${ADDITIONAL_META_TYPE.PUSH_VIDEO}+1`, + // type: `${callType}+1`, + type: `${VIDEO_CALL_TYPE.PUSH_VIDEO}+1`, data: JSON.stringify(videoData), - } + }, }, recipients: recipientAddressInCaip, channel: senderAddressInCaip, diff --git a/packages/restapi/src/lib/video/index.ts b/packages/restapi/src/lib/video/index.ts index b157270a0..ac0701b1a 100644 --- a/packages/restapi/src/lib/video/index.ts +++ b/packages/restapi/src/lib/video/index.ts @@ -1 +1,2 @@ export * from './Video'; +export { VideoDataType } from './helpers/sendVideoCallNotification'; diff --git a/packages/restapi/yarn.lock b/packages/restapi/yarn.lock index 84c19b69e..5bb63c29d 100644 --- a/packages/restapi/yarn.lock +++ b/packages/restapi/yarn.lock @@ -44,348 +44,6 @@ "@ethereumjs/rlp" "^4.0.1" ethereum-cryptography "^1.1.2" -"@ethersproject/abi@^5.7.0", "@ethersproject/abi@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz" - integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/abstract-provider@^5.7.0", "@ethersproject/abstract-provider@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz" - integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - -"@ethersproject/abstract-signer@^5.7.0", "@ethersproject/abstract-signer@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz" - integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/address@^5.7.0", "@ethersproject/address@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz" - integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - -"@ethersproject/base64@^5.7.0", "@ethersproject/base64@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz" - integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - -"@ethersproject/basex@^5.7.0", "@ethersproject/basex@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz" - integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/bignumber@^5.7.0", "@ethersproject/bignumber@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz" - integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - bn.js "^5.2.1" - -"@ethersproject/bytes@^5.7.0", "@ethersproject/bytes@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz" - integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/constants@^5.7.0", "@ethersproject/constants@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz" - integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - -"@ethersproject/contracts@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz" - integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - -"@ethersproject/hash@^5.7.0", "@ethersproject/hash@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz" - integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/hdnode@^5.7.0", "@ethersproject/hdnode@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz" - integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/json-wallets@^5.7.0", "@ethersproject/json-wallets@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz" - integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/keccak256@^5.7.0", "@ethersproject/keccak256@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz" - integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - js-sha3 "0.8.0" - -"@ethersproject/logger@^5.7.0", "@ethersproject/logger@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz" - integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== - -"@ethersproject/networks@^5.7.0", "@ethersproject/networks@5.7.1": - version "5.7.1" - resolved "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz" - integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/pbkdf2@^5.7.0", "@ethersproject/pbkdf2@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz" - integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - -"@ethersproject/properties@^5.7.0", "@ethersproject/properties@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz" - integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/providers@5.7.2": - version "5.7.2" - resolved "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz" - integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/random@^5.7.0", "@ethersproject/random@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz" - integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/rlp@^5.7.0", "@ethersproject/rlp@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz" - integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/sha2@^5.7.0", "@ethersproject/sha2@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz" - integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - hash.js "1.1.7" - -"@ethersproject/signing-key@^5.7.0", "@ethersproject/signing-key@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz" - integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - bn.js "^5.2.1" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/solidity@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz" - integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/strings@^5.7.0", "@ethersproject/strings@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz" - integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/transactions@^5.7.0", "@ethersproject/transactions@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz" - integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - -"@ethersproject/units@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz" - integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/wallet@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz" - integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/json-wallets" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/web@^5.7.0", "@ethersproject/web@5.7.1": - version "5.7.1" - resolved "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz" - integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== - dependencies: - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/wordlists@^5.7.0", "@ethersproject/wordlists@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz" - integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@jridgewell/resolve-uri@^3.0.3": version "3.1.0" resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" @@ -404,6 +62,24 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@livepeer/core@^1.5.8": + version "1.5.8" + resolved "https://registry.yarnpkg.com/@livepeer/core/-/core-1.5.8.tgz#c048bffb216a7d0dc831d2de2956652262b318de" + integrity sha512-h/afwfan0y5DugHz/lZhsTzTeDs2lzVFuuHyJrU3EPZl0SvHHFT0cI47/vRjLY6aV1UfJglQwZAa6auPrVXM9w== + dependencies: + cross-fetch "^3.1.5" + ms "^3.0.0-canary.1" + multiformats "9.9.0" + tus-js-client "^3.0.1" + zustand "^4.3.2" + +"@livepeer/webrtmp-sdk@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@livepeer/webrtmp-sdk/-/webrtmp-sdk-0.2.3.tgz#10c5baca5517b8f14ec766df15be467d14e7c8d7" + integrity sha512-tJ2gGhUZfbeXmIkZHxY/WNS0C9SYUhJ/6QlYhot1CJlBuXkuoki9gSGhYhS3G7Vu/HchL1HU/DXWKhrQhlogXg== + dependencies: + events "3.3.0" + "@metamask/eth-sig-util@^5.0.2": version "5.0.2" resolved "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-5.0.2.tgz" @@ -416,12 +92,12 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" -"@noble/hashes@~1.2.0", "@noble/hashes@1.2.0": +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz" integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== -"@noble/secp256k1@~1.7.0", "@noble/secp256k1@1.7.1": +"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": version "1.7.1" resolved "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz" integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== @@ -448,6 +124,11 @@ "@noble/hashes" "~1.2.0" "@scure/base" "~1.1.0" +"@stitches/core@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@stitches/core/-/core-1.2.8.tgz#dce3b8fdc764fbc6dbea30c83b73bfb52cf96173" + integrity sha512-Gfkvwk9o9kE9r9XNBmJRfV8zONvXThnm1tcuojL04Uy5uRyqg93DC83lDebl0rocZCfKSjUv+fWYtMQmEDJldg== + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz" @@ -495,11 +176,6 @@ resolved "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz" integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== -"@types/node@*": - version "20.2.4" - resolved "https://registry.npmjs.org/@types/node/-/node-20.2.4.tgz" - integrity sha512-ni5f8Xlf4PwnT/Z3f0HURc3ZSw8UyrqMqmM3L5ysa7VjHu8c3FOmIo1nKCcLrV/OAmtf3N4kFna/aJqxsfEtnA== - acorn-walk@^8.1.1: version "8.2.0" resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" @@ -510,11 +186,6 @@ acorn@^8.4.1: resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz" - integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== - ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" @@ -592,26 +263,16 @@ base64-js@^1.3.1: resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -bech32@1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz" - integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== - binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bn.js@^4.0.0, bn.js@^4.11.8, bn.js@^4.11.9: +bn.js@^4.0.0, bn.js@^4.11.8: version "4.12.0" resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" @@ -634,16 +295,16 @@ braces@~3.0.2: dependencies: fill-range "^7.0.1" -brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" - integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== - browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== +buffer-from@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + buffer@^6.0.3: version "6.0.3" resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" @@ -674,7 +335,7 @@ chai-as-promised@^7.1.1: dependencies: check-error "^1.0.2" -chai@^4.3.7, "chai@>= 2.1.2 < 5": +chai@^4.3.7: version "4.3.7" resolved "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz" integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== @@ -761,26 +422,46 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + color-name@~1.1.4: version "1.1.4" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== +combine-errors@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/combine-errors/-/combine-errors-3.0.3.tgz#f4df6740083e5703a3181110c2b10551f003da86" + integrity sha512-C8ikRNRMygCwaTx+Ek3Yr+OuZzgZjduCOfSQBjbM8V3MfgcjSTeto/GXP6PAwKvJz/v15b7GHZvx5rOlczFw/Q== + dependencies: + custom-error-instance "2.1.1" + lodash.uniqby "4.5.0" concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +core-js@^3.27.2: + version "3.31.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.31.0.tgz#4471dd33e366c79d8c0977ed2d940821719db344" + integrity sha512-NIp2TQSGfR6ba5aalZD+ZQ1fSxGhDo/s1w0nx3RYzf2pnJxt7YynxFlFScP6eV7+GZsKO95NSjGxyJsU3DZgeQ== + create-require@^1.1.0: version "1.1.1" resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-fetch@^3.1.5: + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + dependencies: + node-fetch "^2.6.12" + cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz" @@ -797,7 +478,12 @@ crypto-js@^4.1.1: resolved "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz" integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== -debug@^4.3.2, debug@4.3.4: +custom-error-instance@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/custom-error-instance/-/custom-error-instance-2.1.1.tgz#3cf6391487a6629a6247eb0ca0ce00081b7e361a" + integrity sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg== + +debug@4.3.4, debug@^4.3.2: version "4.3.4" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -821,28 +507,15 @@ deep-eql@^4.1.2: dependencies: type-detect "^4.0.0" -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - diff@5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== -elliptic@6.5.4: - version "6.5.4" - resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== emoji-regex@^8.0.0: version "8.0.0" @@ -866,16 +539,16 @@ escalade@^3.1.1: resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - escape-string-regexp@4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + ethereum-cryptography@^1.1.2: version "1.2.0" resolved "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz" @@ -886,42 +559,6 @@ ethereum-cryptography@^1.1.2: "@scure/bip32" "1.1.5" "@scure/bip39" "1.1.1" -ethers@^5.6.8: - version "5.7.2" - resolved "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz" - integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.1" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.2" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.1" - "@ethersproject/wordlists" "5.7.0" - ethjs-util@^0.1.6: version "0.1.6" resolved "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz" @@ -930,6 +567,11 @@ ethjs-util@^0.1.6: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" +events@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + execa@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz" @@ -950,13 +592,6 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" - integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== - dependencies: - locate-path "^2.0.0" - find-up@5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" @@ -965,6 +600,13 @@ find-up@5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + dependencies: + locate-path "^2.0.0" + flat@^5.0.2: version "5.0.2" resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" @@ -1026,6 +668,11 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" +graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" @@ -1036,27 +683,15 @@ has-flag@^4.0.0: resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -hash.js@^1.0.0, hash.js@^1.0.3, hash.js@1.1.7: - version "1.1.7" - resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - he@1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" - integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" +hls.js@^1.4.0: + version "1.4.8" + resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-1.4.8.tgz#6fedcb5224d7361e4f38046ffd45286d8a645df8" + integrity sha512-wYL7W49M6oKv0+P4RW50YkJaxDzgnHMMrN+YoLpow07hVgaedAdX9HfKkehTb04UEfeJhNSef5ucICYPsHOfqg== ieee754@^1.2.1: version "1.2.1" @@ -1076,7 +711,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@2: +inherits@2, inherits@^2.0.1, inherits@^2.0.3: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -1142,6 +777,11 @@ is-stream@^1.1.0: resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + is-unicode-supported@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" @@ -1152,10 +792,10 @@ isexe@^2.0.0: resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -js-sha3@0.8.0: - version "0.8.0" - resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== +js-base64@^3.7.2: + version "3.7.5" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.5.tgz#21e24cf6b886f76d6f5f165bfcd69cc55b9e3fca" + integrity sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA== js-yaml@4.1.0: version "4.1.0" @@ -1171,6 +811,21 @@ lcid@^2.0.0: dependencies: invert-kv "^2.0.0" +livepeer@^2.5.8: + version "2.5.8" + resolved "https://registry.yarnpkg.com/livepeer/-/livepeer-2.5.8.tgz#afce72633bb1036d1fe3c837ad997a5dce957b54" + integrity sha512-V+VZVXjEo47A0hxUAB6HLGSBjEvksBXJyFTatkYqarfU6T8gMk+37RugEOsZn6dDj9up4+6A7xWygKoC1zu+ow== + dependencies: + "@livepeer/core" "^1.5.8" + "@stitches/core" "^1.2.8" + core-js "^3.27.2" + cross-fetch "^3.1.5" + hls.js "^1.4.0" + ms "^3.0.0-canary.1" + multiformats "9.9.0" + tus-js-client "^3.0.1" + zustand "^4.3.2" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" @@ -1186,6 +841,56 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash._baseiteratee@~4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash._baseiteratee/-/lodash._baseiteratee-4.7.0.tgz#34a9b5543572727c3db2e78edae3c0e9e66bd102" + integrity sha512-nqB9M+wITz0BX/Q2xg6fQ8mLkyfF7MU7eE+MNBNjTHFKeKaZAPEzEg+E8LWxKWf1DQVflNEn9N49yAuqKh2mWQ== + dependencies: + lodash._stringtopath "~4.8.0" + +lodash._basetostring@~4.12.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz#9327c9dc5158866b7fa4b9d42f4638e5766dd9df" + integrity sha512-SwcRIbyxnN6CFEEK4K1y+zuApvWdpQdBHM/swxP962s8HIxPO3alBH5t3m/dl+f4CMUug6sJb7Pww8d13/9WSw== + +lodash._baseuniq@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" + integrity sha512-Ja1YevpHZctlI5beLA7oc5KNDhGcPixFhcqSiORHNsp/1QTv7amAXzw+gu4YOvErqVlMVyIJGgtzeepCnnur0A== + dependencies: + lodash._createset "~4.0.0" + lodash._root "~3.0.0" + +lodash._createset@~4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" + integrity sha512-GTkC6YMprrJZCYU3zcqZj+jkXkrXzq3IPBcF/fIPpNEAB4hZEtXU8zp/RwKOvZl43NUmwDbyRk3+ZTbeRdEBXA== + +lodash._root@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + integrity sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ== + +lodash._stringtopath@~4.8.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/lodash._stringtopath/-/lodash._stringtopath-4.8.0.tgz#941bcf0e64266e5fc1d66fed0a6959544c576824" + integrity sha512-SXL66C731p0xPDC5LZg4wI5H+dJo/EO4KTqOMwLYCH3+FmmfAKJEZCm6ohGpI+T1xwsDsJCfL4OnhorllvlTPQ== + dependencies: + lodash._basetostring "~4.12.0" + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +lodash.uniqby@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.5.0.tgz#a3a17bbf62eeb6240f491846e97c1c4e2a5e1e21" + integrity sha512-IRt7cfTtHy6f1aRVA5n7kT8rgN3N1nH6MOWLcHfpWG2SH19E3JksLK38MktLxZDhlAjCP9jpIXkOnRXlu6oByQ== + dependencies: + lodash._baseiteratee "~4.7.0" + lodash._baseuniq "~4.6.0" + log-symbols@4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" @@ -1227,15 +932,17 @@ mimic-fn@^2.0.0: resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: +minimalistic-assert@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" minimatch@^3.0.4: version "3.1.2" @@ -1244,13 +951,6 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimatch@5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== - dependencies: - brace-expansion "^2.0.1" - mocha-typescript@^1.1.17: version "1.1.17" resolved "https://registry.npmjs.org/mocha-typescript/-/mocha-typescript-1.1.17.tgz" @@ -1298,6 +998,16 @@ ms@2.1.3: resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +ms@^3.0.0-canary.1: + version "3.0.0-canary.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-3.0.0-canary.1.tgz#c7b34fbce381492fd0b345d1cf56e14d67b77b80" + integrity sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g== + +multiformats@9.9.0: + version "9.9.0" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" + integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== + nanoid@3.3.3: version "3.3.3" resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz" @@ -1308,6 +1018,13 @@ nice-try@^1.0.4: resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-fetch@^2.6.12: + version "2.6.12" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" + integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + dependencies: + whatwg-url "^5.0.0" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" @@ -1426,6 +1143,15 @@ picomatch@^2.0.4, picomatch@^2.2.1: resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +proper-lockfile@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== + dependencies: + graceful-fs "^4.2.4" + retry "^0.12.0" + signal-exit "^3.0.2" + pump@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" @@ -1434,6 +1160,11 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + queue-microtask@^1.2.3: version "1.2.3" resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" @@ -1472,6 +1203,16 @@ require-main-filename@^1.0.1: resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz" integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" @@ -1482,11 +1223,6 @@ safer-buffer@^2.1.0: resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -scrypt-js@3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz" - integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== - semver@^5.5.0: version "5.7.1" resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" @@ -1516,7 +1252,7 @@ shebang-regex@^1.0.0: resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== -signal-exit@^3.0.0: +signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.7" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -1534,13 +1270,6 @@ simple-peer@^9.11.1: randombytes "^2.1.0" readable-stream "^3.6.0" -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - string-width@^1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" @@ -1567,6 +1296,13 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" @@ -1605,6 +1341,13 @@ strip-json-comments@3.1.1: resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" @@ -1619,13 +1362,6 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-color@8.1.1: - version "8.1.1" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" @@ -1633,6 +1369,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + ts-node@^10.9.1: version "10.9.1" resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz" @@ -1652,6 +1393,19 @@ ts-node@^10.9.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" +tus-js-client@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/tus-js-client/-/tus-js-client-3.1.0.tgz#20af57d06c23823fbe108ccb3a3dcb7503968cb4" + integrity sha512-Hfpc8ho4C9Lhs/OflPUA/nHUHZJUrKD5upoPBq7dYJJ9DQhWocsjJU2RZYfN16Y5n19j9dFDszwCvVZ5sfcogw== + dependencies: + buffer-from "^1.1.2" + combine-errors "^3.0.3" + is-stream "^2.0.0" + js-base64 "^3.7.2" + lodash.throttle "^4.1.1" + proper-lockfile "^4.1.2" + url-parse "^1.5.7" + tweetnacl-util@^0.15.1: version "0.15.1" resolved "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz" @@ -1667,11 +1421,24 @@ type-detect@^4.0.0, type-detect@^4.0.5: resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -typescript@^5.0.2, typescript@>=2.7: +typescript@^5.0.2: version "5.0.2" resolved "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz" integrity sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw== +url-parse@^1.5.7: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +use-sync-external-store@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" @@ -1682,6 +1449,24 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +video-stream-merger@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/video-stream-merger/-/video-stream-merger-4.0.1.tgz#b0061251bd211121d1256ccf9e2be9477e59d5cb" + integrity sha512-VazYSr8tk6S/zkOq5jpR/ryy1HnGxm5XCw+d2Ejpqy1m6d71oZpyFG82dUkgAo7dg/lk3k4TqvJPtuRUtR8URA== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz" @@ -1721,11 +1506,6 @@ wrappy@1: resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@7.4.6: - version "7.4.6" - resolved "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== - y18n@^3.2.1: version "3.2.2" resolved "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz" @@ -1736,7 +1516,7 @@ y18n@^5.0.5: resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yargs-parser@^20.2.2, yargs-parser@20.2.4: +yargs-parser@20.2.4, yargs-parser@^20.2.2: version "20.2.4" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== @@ -1758,6 +1538,19 @@ yargs-unparser@2.0.0: flat "^5.0.2" is-plain-obj "^2.1.0" +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yargs@^11.0.0: version "11.1.1" resolved "https://registry.npmjs.org/yargs/-/yargs-11.1.1.tgz" @@ -1776,19 +1569,6 @@ yargs@^11.0.0: y18n "^3.2.1" yargs-parser "^9.0.2" -yargs@16.2.0: - version "16.2.0" - resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - yn@3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" @@ -1798,3 +1578,10 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zustand@^4.3.2: + version "4.3.9" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.9.tgz#a7d4332bbd75dfd25c6848180b3df1407217f2ad" + integrity sha512-Tat5r8jOMG1Vcsj8uldMyqYKC5IZvQif8zetmLHs9WoZlntTHmIoNM8TpLRY31ExncuUvUOXehd0kvahkuHjDw== + dependencies: + use-sync-external-store "1.2.0" diff --git a/packages/uiweb/package.json b/packages/uiweb/package.json index 091b6cec3..6d0ba1a94 100644 --- a/packages/uiweb/package.json +++ b/packages/uiweb/package.json @@ -5,6 +5,7 @@ "registry": "https://registry.npmjs.org/" }, "dependencies": { + "@livepeer/react": "^2.6.0", "@pushprotocol/socket": "^0.5.0", "@unstoppabledomains/resolution": "^8.5.0", "date-fns": "^2.28.0", diff --git a/packages/uiweb/src/lib/components/chatAndNotification/ChatAndNotification.tsx b/packages/uiweb/src/lib/components/chatAndNotification/ChatAndNotification.tsx index 5e0d92db2..1af763bba 100644 --- a/packages/uiweb/src/lib/components/chatAndNotification/ChatAndNotification.tsx +++ b/packages/uiweb/src/lib/components/chatAndNotification/ChatAndNotification.tsx @@ -177,6 +177,7 @@ export const ChatAndNotification = () => { })(); }, [activeChat,env,account]); + const onMaximizeMinimizeToggle = () => { setModalOpen(!modalOpen); }; @@ -187,6 +188,7 @@ export const ChatAndNotification = () => { } }; + return ( { maxHeight="600px" position="fixed" background="#fff" - right="12px" bottom="18px" overflow="hidden" - onMouseEnter={() => toggleOverflow('hidden')} - onMouseLeave={() => toggleOverflow('unset')} + + // onMouseEnter={() => toggleOverflow('hidden')} + // onMouseLeave={() => toggleOverflow('auto')} > void; + onJoin?: any; +} + +/** + * @interface IThemeProps + * this interface is used for defining the props for styled components + */ +interface IThemeProps { + theme?: ISpacesTheme; + orientation?: string; + status?: string; + clickable?: boolean; +} + +export const SpaceBanner: React.FC = ({ + spaceId, + orientation, + isInvite, + onBannerClick, + onJoin, +}) => { + const theme = React.useContext(ThemeContext); + const spaceData = useGetSpaceInfo(spaceId); + + const spaceStatus = getSpaceStatus(spaceData?.status); + + const handleClick = () => { + if (onBannerClick) { + onBannerClick(spaceData?.spaceId || ''); + } + }; + + // Check if the spaceData is not available, show the skeleton loading effect + if (!spaceData) { + return ; + } + + return ( + + {orientation === 'maximized' && ( + + )} + {orientation === 'maximized' ? null : ( + + )} + + {orientation === 'pill' + ? `${spaceData?.spaceName.slice(0, 20)}...` + : spaceData?.spaceName} + + + + + + {isInvite === true && spaceStatus === 'Live' ? ( + Join this space + ) : isInvite === true && + spaceStatus === 'Scheduled' ? ( + Remind Me + ) : null} + + ); +}; + +// Styling +const Container = styled.div` + display: flex; + flex-direction: ${(props) => + props.orientation === 'maximized' ? 'column' : 'row'}; + justify-content: ${(props) => + props.orientation === 'maximized' ? 'space-between' : 'space-between'}; + align-items: ${(props) => + props.orientation === 'maximized' ? 'flex-start' : 'center'}; + padding: ${(props) => + props.orientation === 'maximized' + ? '16px' + : props.orientation === 'minimized' + ? '0 20px' + : '0 11px'}; + gap: ${(props) => (props.orientation === 'maximized' ? '16px' : '8px')}; + width: ${(props) => + props.orientation === 'maximized' + ? 'inherit' + : props.orientation === 'minimized' + ? 'inherit' + : 'fit-content'}; + height: ${(props) => + props.orientation === 'maximized' + ? 'auto' + : props.orientation === 'minimized' + ? '40px' + : '63px'}; + background: ${(props) => + props.status === 'Live' + ? props.theme.titleBg + : props.theme.bgColorSecondary}; + border-radius: ${(props) => + props.orientation === 'maximized' + ? '17px' + : props.orientation === 'minimized' + ? '12px' + : '24px'}; + color: ${(props) => (props.status === 'Live' ? '#f5f5f5' : '#1E1E1E')}; + min-width: 0; + text-overflow: ellipsis; + overflow: hidden; + cursor: ${props => props.clickable && 'pointer'}; +`; + +const Title = styled.div<{ orientation?: string }>` + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + font-family: Strawford; + font-weight: ${(props) => + props.orientation === 'maximized' ? '700' : '500'}; + font-size: ${(props) => + props.orientation === 'maximized' + ? '20px' + : props.orientation === 'minimized' + ? '16px' + : '12px'}; + line-height: 130%; + width: 90%; + line-clamp: ${(props) => (props.orientation === 'maximized' ? '3' : '2')}; + + @media (max-width: 425px) { + width: 95%; + } +`; + +const Status = styled.div` + display: flex; + flex-direction: row; + width: ${(props) => + props.orientation === 'maximized' ? '100%' : 'fit-content'}; + justify-content: space-between; + align-items: center; +`; + +const Time = styled.div<{ orientation?: string }>` + display: ${(props) => (props.orientation === 'maximized' ? 'flex' : 'none')}; + flex-direction: row; + justify-content: center; + align-items: center; +`; + +const Icon = styled.img` + height: 24px; + width: 24px; + padding: 0 11px 0 0; + align-self: center; +`; + +const TimeText = styled.div<{ status?: string }>` + font-weight: 500; + font-size: 14px; + line-height: 150%; + color: ${(props) => (props.status === 'Live' ? '#fff' : '#71717A')}; +`; + +const InviteButton = styled.button<{ status?: string }>` + display: flex; + justify-content: center; + align-items: center; + height: 36px; + width: 100%; + color: ${(props) => (props.status === 'Live' ? '#FFF' : '#8B5CF6')}; + border-radius: 8px; + border: ${(props) => + props.status === 'Live' ? '1px solid #FFF' : '1px solid #8B5CF6'}; + background: transparent; + cursor: pointer; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceBanner/SpaceBannerLoadingSkeleton.tsx b/packages/uiweb/src/lib/components/space/SpaceBanner/SpaceBannerLoadingSkeleton.tsx new file mode 100644 index 000000000..013d43705 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceBanner/SpaceBannerLoadingSkeleton.tsx @@ -0,0 +1,137 @@ +import React from 'react'; +import styled from 'styled-components'; + +export const SpaceBannerLoadingSkeleton: React.FC = () => { + return ( + + + + + + + + + + + + + + + + + + + ); +}; + +const SkeletonContainer = styled.div` + display: flex; + flex-direction: column; + gap: 24px; + padding: 16px; + background-color: #f1f1f1; + border-radius: 17px; + border: 1px solid lightgrey; + position: relative; + + &:after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: 17px; + background-color: #f1f1f1; + opacity: 0.5; + transition: opacity 0.8s ease-in-out infinite alternate; + } + + &:hover:after { + opacity: 0.3; + } +`; + +const SkeletonContent = styled.div` + display: flex; + align-items: center; + gap: 10px; +`; + +const SkeletonProfilePic = styled.div` + width: 48px; + height: 48px; + border-radius: 50%; + border: 1px solid lightgrey; + background-color: #d9d9d9; + transition: opacity 0.8s ease-in-out infinite alternate; + + &:hover { + opacity: 0.5; + } +`; + +const SkeletonProfileInfo = styled.div` + display: flex; + flex-direction: column; + gap: 5px; + width: 100%; +`; + +const SkeletonText = styled.div` + width: 100%; + height: 18px; + background-color: #d9d9d9; + border-radius: 8px; + border: 1px solid lightgrey; + transition: opacity 0.8s ease-in-out infinite alternate; + + &:hover { + opacity: 0.5; + } +`; + +const SkeletonName = styled(SkeletonText)` + width: 30%; +`; + +const SkeletonHandle = styled(SkeletonText)` + width: 40%; +`; + +const SkeletonSpaceInfo = styled(SkeletonText)` + width: 100%; + height: 30px; +`; + +const SkeletonLine = styled.div` + display: flex; + align-items: center; + width: 100%; +`; + +const SkeletonLeftSquare = styled(SkeletonText)` + width: 10%; + height: 32px; +`; + +const SkeletonOverlap = styled.div` + display: flex; + align-items: flex-start; + justify-content: right; + width: 100%; + margin-top: 8px; +`; + +const SkeletonOverlapProfilePic = styled(SkeletonProfilePic)` + height: 48px; + border: 1px solid lightgrey; + margin-left: -24px; + transition: opacity 0.8s ease-in-out infinite alternate; + &:nth-child(2) { + margin-left: -24px; + } + &:nth-child(3) { + margin-left: -24px; + } +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceBanner/index.ts b/packages/uiweb/src/lib/components/space/SpaceBanner/index.ts new file mode 100644 index 000000000..72fd7241f --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceBanner/index.ts @@ -0,0 +1 @@ +export * from "./SpaceBanner"; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/SCWButton.tsx b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/SCWButton.tsx new file mode 100644 index 000000000..ee1244992 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/SCWButton.tsx @@ -0,0 +1,57 @@ +import React, { MouseEventHandler, useContext } from 'react' +import styled from 'styled-components'; + +import { ISpacesTheme } from '../../theme'; +import { ThemeContext } from '../../theme/ThemeProvider'; + +export interface ISCWButtonProps { // Space Creation Widget Button Interface + btnText?: string; + customStyle?: any; + theme?: ISpacesTheme; + onCreate?: MouseEventHandler; +} + +const defaultProps: ISCWButtonProps = { + btnText: 'Create your Space', + customStyle: { + padding: '20px', + borderRadius: '12px', + border: '0px solid transparent', + fontSize: '1rem', + }, +} + +export const SCWButton: React.FC = (props) => { + const { btnText, customStyle, onCreate } = props; + + const theme = useContext(ThemeContext); + + return ( +
+ + {btnText} + +
+ ) +} + +/* styling */ +const CreateButton = styled.button` + padding: ${props => props.customStyle.padding}; + border-radius: ${props => props.customStyle.borderRadius}; + border: ${props => props.customStyle.border}; + font-size: ${props => props.customStyle.fontSize}; + + background-image: ${(props) => props.theme.titleBg}; + color: ${(props) => props.theme.titleTextColor}; + + cursor: pointer; +`; + +SCWButton.defaultProps = defaultProps; + +export default SCWButton; diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/index.ts b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/index.ts new file mode 100644 index 000000000..905744434 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/index.ts @@ -0,0 +1 @@ +export * from './SCWButton'; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/SCWCreateModal.tsx b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/SCWCreateModal.tsx new file mode 100644 index 000000000..5054e6235 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/SCWCreateModal.tsx @@ -0,0 +1,90 @@ +import React, { MouseEventHandler } from 'react' +import styled from 'styled-components' + +import { Modal } from '../../reusables/Modal' +import { Button } from '../../reusables/Button'; +import { ModalHeader } from '../../reusables/ModalHeader'; +import { TextInputWithCounter } from '../../reusables/TextInput'; + +import { CalendarPurple } from '../../../../icons/CalendarPurple'; + +export interface ISCWCModalProps { // Space Creation Widget Create Modal Interface + isInviteVisible?: any; + closeCreateModal?: MouseEventHandler; + handleNameChange?: any; + handleDescriptionChange?: any; + nameValue?: any; + descriptionValue?: any; + isDescriptionEnabled: boolean; + isScheduleVisible?: any; + onClose: () => void; +} + +export const SCWCreateModal: React.FC = (props) => { + const { + isInviteVisible, closeCreateModal, handleNameChange, + handleDescriptionChange, nameValue, descriptionValue, + isDescriptionEnabled, isScheduleVisible, onClose, + } = props; + + const secBtn = { + background: 'transparent', + borderColor: '#8b5cf6' + } + + return ( + + + + + + { + isDescriptionEnabled ? + + : null + } + + + + +
+ +
+
+
+ ) +} + +/* styling */ +const ButtonContainer = styled.div` + display: flex; + justify-content: space-between; + width: 100%; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/index.ts b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/index.ts new file mode 100644 index 000000000..aae6e3038 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/index.ts @@ -0,0 +1 @@ +export * from './SCWCreateModal' diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/SCWInviteModal.tsx b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/SCWInviteModal.tsx new file mode 100644 index 000000000..94c8ac684 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/SCWInviteModal.tsx @@ -0,0 +1,423 @@ +/* eslint-disable no-prototype-builtins */ +import React, { useState, MouseEventHandler, useContext, useEffect } from 'react' +import styled from 'styled-components' +import * as PushAPI from '@pushprotocol/restapi'; + +import { ModalHeader } from '../../reusables/ModalHeader'; +import { Modal } from '../../reusables/Modal'; +import { Button } from '../../reusables/Button'; +import { SearchInput } from '../../reusables/SearchInput'; +import { ProfileContainer } from '../../reusables/ProfileContainer'; +import { ThemeContext } from '../../theme/ThemeProvider'; +import { Spinner } from '../../reusables/Spinner'; + +import CircularProgressSpinner from '../../../loader/loader'; + +import { useSpaceData } from '../../../../hooks'; +import SettingsIcon from '../../../../icons/settingsBlack.svg'; +import { Image } from '../../../../config'; + +import { createIcon } from '../../helpers/blockies'; + +export interface ISCWIModalProps { // Space Creation Widget Create Modal Interface + closeInviteModal?: MouseEventHandler; + makeScheduleVisible?: MouseEventHandler; + createSpace?: MouseEventHandler; + isLoading?: boolean; + invitedMembersList?: any; + setInvitedMembersList?: any; + invitedAddressList?: any; + setInvitedAddressList?: any; + adminsList?: any; + setAdminsList?: any; + adminsAddressList?: any; + setAdminsAddressList?: any; + onClose: () => void; +} + +interface User { + handle: string; + name: string; +} + +export const SCWInviteModal: React.FC = (props) => { + const { + closeInviteModal, makeScheduleVisible, createSpace, isLoading, + invitedMembersList, + setInvitedMembersList, + invitedAddressList, + setInvitedAddressList, + adminsList, + setAdminsList, + adminsAddressList, + setAdminsAddressList, + onClose + } = props; + const theme = useContext(ThemeContext); + + const { env, account } = useSpaceData(); + + const [invitedMember, setInvitedMember] = useState('') + const [loadingAccount, setLoadingAccount] = useState(false) + + const [searchedUser, setSearchedUser]= useState({}); + const [errorMsg, setErrorMsg] = useState(''); + + const searchMember = async (event: any) => { + setInvitedMember(event.target.value) + + if (event.target.value === account) { + handleError('Cannot add Host to members'); + return; + } + + try { + setLoadingAccount(true); + const response = await PushAPI.user.get({ + account: event.target.value, + env, + }); + + if(response === null) { + const icon = createIcon({ + seed: event.target.value, + size: 10, + scale: 3, + }); + + const nullUser = { + walletAddress: event.target.value, + name: event.target.value, + image: icon.toDataURL(), + }; + + setSearchedUser(nullUser) + } else { + setSearchedUser(response); + } + setErrorMsg(''); + } catch (e:any) { + console.error(e.message); + setSearchedUser({}); + setErrorMsg(e.message); + } finally { + setLoadingAccount(false); + } + } + + const clearInput = () => { + setInvitedMember(''); + setSearchedUser({}); + setErrorMsg(''); + } + + const handleError = (errMsg: string) => { + setErrorMsg(errMsg); + setTimeout(() => { + setErrorMsg('') + }, 2000); + } + + const handleInviteMember = (user: any) => { + if( + (invitedAddressList.length !== 0 && adminsAddressList.length !== 0) + && (invitedAddressList.includes(user.did.substring(7)) || adminsAddressList.includes(user.did.substring(7))) + ) { + handleError('Already Invited'); + return; + } + + if (user.did) { + setInvitedAddressList([...invitedAddressList, user.did.substring(7)]) + setInvitedMembersList([...invitedMembersList, user]); + } else { + setInvitedAddressList([...invitedAddressList, user.walletAddress]) + setInvitedMembersList([...invitedMembersList, user]); + } + + clearInput(); + } + + const handlePromoteToAdmin = (user: any) => { + if (user.did) { + setAdminsList([...adminsList, user]) + setAdminsAddressList([...adminsAddressList, user.did.substring(7)]); + } else { + setAdminsList([...adminsList, user]) + setAdminsAddressList([...adminsAddressList, user.walletAddress]); + } + + const updatedArray = invitedMembersList.filter((item: any) => item !== user) + setInvitedMembersList(updatedArray); + + if (user.did) { + const updateAddressArray = invitedAddressList.filter((item: string) => item !== user.did.substring(7)) + setInvitedAddressList(updateAddressArray); + } else { + const updateAddressArray = invitedAddressList.filter((item: string) => item !== user.walletAddress) + setInvitedAddressList(updateAddressArray); + } + + clearInput(); + } + + const handleDeleteInvitedUser = (user: any) => { + const updatedArray = invitedMembersList.filter((item: any) => item !== user) + setInvitedMembersList(updatedArray); + + if (user.did) { + const updateAddressArray = invitedAddressList.filter((item: string) => item !== user.did.substring(7)) + setInvitedAddressList(updateAddressArray); + } else { + const updateAddressArray = invitedAddressList.filter((item: string) => item !== user.walletAddress) + setInvitedAddressList(updateAddressArray); + } + }; + + const handleDeleteInvitedAdmin = (user: any) => { + const updatedArray = adminsList.filter((item: any) => item !== user) + setAdminsList(updatedArray); + + if (user.did) { + const updateAdminAddressArray = adminsAddressList.filter((item: string) => item !== user.did.substring(7)) + setAdminsAddressList(updateAdminAddressArray); + } else { + const updateAddressArray = adminsAddressList.filter((item: string) => item !== user.walletAddress) + setAdminsAddressList(updateAddressArray); + } + }; + + const tempImageUrl = "https://imgv3.fotor.com/images/blog-richtext-image/10-profile-picture-ideas-to-make-you-stand-out.jpg"; + + return ( +
+ + + + + + {errorMsg} + + + {loadingAccount && } + { + Object.keys(searchedUser).length === 0 ? + null + : searchedUser.hasOwnProperty('walletAddress') ? + Add +} + btnCallback={() => handleInviteMember(searchedUser)} + border + /> + : Add +} + btnCallback={() => handleInviteMember(searchedUser)} + border + /> + } + + + { + invitedMembersList.length ? + + Invited Members {invitedMembersList.length} + { + invitedMembersList.map((item: any) => { + if (item.hasOwnProperty('walletAddress')) { + return + Settings icon + + } + // btnCallback={() => handleDeleteInvitedUser(item)} + removeCallback={() => handleDeleteInvitedUser(item)} + promoteCallback={() => handlePromoteToAdmin(item)} + border + /> + } else { + return + Settings icon + + } + // btnCallback={() => handleDeleteInvitedUser(item)} + removeCallback={() => handleDeleteInvitedUser(item)} + promoteCallback={() => handlePromoteToAdmin(item)} + border + /> + } + }) + } + + : null + } + + { + adminsList.length ? + + Speakers {adminsList.length} + { + adminsList.map((item: any) => { + if (item.hasOwnProperty('walletAddress')) { + return + Settings icon + + } + // btnCallback={() => handleDeleteInvitedUser(item)} + removeCallback={() => handleDeleteInvitedAdmin(item)} + // promoteCallback={() => handlePromoteToAdmin(item)} + border + /> + } else { + return + Settings icon + + } + // btnCallback={() => handleDeleteInvitedUser(item)} + removeCallback={() => handleDeleteInvitedAdmin(item)} + // promoteCallback={() => handlePromoteToAdmin(item)} + border + /> + } + }) + } + + : null + } + + + +
+ ) +} + + +const MembersList = styled.div` + width: 100%; + display: flex; + flex-direction: column; + gap: 8px; +`; + +const InvitedList = styled.div` + width: 100%; + display: flex; + flex-direction: column; + gap: 8px; + + margin-top: 28px; +`; + +const Heading = styled.div` + display: flex; + align-items: center; +`; + +const PendingCount = styled.div` + background: ${(props => props.theme.btnColorPrimary)}; + border-radius: 8px; + padding: 4px 10px; + margin-left: 6px; + font-size: 13px; + color: ${(props => props.theme.titleTextColor)}; +`; + +const SettingsCont = styled.div` + display: flex; + justify-content: center; + align-items: center; + + cursor: pointer; +`; + +const ContBtn = styled.button` + display: flex; + flex-direction: row; + align-items: center; + margin-left: 8px; + line-height: 18px; + width: max-content; + background: transparent; + color: #8B5CF6; + border-radius: 6px; + font-weight: 500; + font-size: 12px; + padding: 4px 8px; + border-radius: 8px; + border: 1px solid #8B5CF6; + cursor: pointer; +`; + +const ErrorMessage = styled.div` + color: #E93636; + font-size: 14px; + margin-bottom: 8px; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/index.ts b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/index.ts new file mode 100644 index 000000000..ce11a56b2 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/index.ts @@ -0,0 +1 @@ +export * from './SCWInviteModal'; diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/SCWScheduleModal.tsx b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/SCWScheduleModal.tsx new file mode 100644 index 000000000..063d2222d --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/SCWScheduleModal.tsx @@ -0,0 +1,59 @@ +import React, { MouseEventHandler } from 'react' +import styled from 'styled-components'; + +import DateTimePicker from '../../reusables/DateTimePicker'; + +import { Modal } from '../../reusables/Modal'; +import { ModalHeader } from '../../reusables/ModalHeader'; +import { Button } from '../../reusables/Button'; + +export interface ISCWSModalProps { // Space Creation Widget Schedule Modal Interface + closeScheduleModal?: MouseEventHandler; + makeCreateVisible?: MouseEventHandler; + makeInviteVisible?: MouseEventHandler; + + dateValue?: any; + onDateChange?: any; + timeValue?: any; + onTimeChange?: any; + + onClose: () => void; +} + +export const SCWScheduleModal: React.FC = (props) => { + + const { closeScheduleModal, makeCreateVisible, makeInviteVisible, dateValue, timeValue, onDateChange, onTimeChange, onClose } = props; + + return ( + + + + + + + + + + ) +} + +const ButtonContainer = styled.div` + display: flex; + justify-content: space-between; + width: 100%; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/index.ts b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/index.ts new file mode 100644 index 000000000..9b907490d --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/index.ts @@ -0,0 +1 @@ +export * from './SCWScheduleModal'; diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SpaceCreationWidget.tsx b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SpaceCreationWidget.tsx new file mode 100644 index 000000000..54bee046c --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SpaceCreationWidget.tsx @@ -0,0 +1,192 @@ +import { useState } from 'react' +import styled from 'styled-components'; +import * as PushAPI from '@pushprotocol/restapi'; + +import { SCWCreateModal } from './SCWCreateModal/SCWCreateModal' +import { SCWScheduleModal } from './SCWScheduleModal/SCWScheduleModal'; +import { SCWInviteModal } from './SCWInviteModal/SCWInviteModal'; +import { SCWButton } from './SCWButton'; + +import { useSpaceData } from '../../../hooks'; + +export interface ISpaceCreateWidgetProps { + CustomComponent?: any; +} + +export const SpaceCreationWidget:React.FC = (props) => { + const { CustomComponent } = props; + + const [isCreateModalVisible, setIsCreateModalVisible] = useState(false); + const [isScheduleModalVisible, setIsScheduleModalVisible] = useState(false); + const [isInviteModalVisible, setIsInviteModalVisible] = useState(false); + + const [invitedMembersList, setInvitedMembersList] = useState([]) + const [invitedAddressList, setInvitedAddressList] = useState([]) + + const [adminsList, setAdminsList] = useState([]) + const [adminsAddressList, setAdminsAddressList] = useState([]) + + const [isLoading, setLoading] = useState(false); + + const [spaceState, setSpaceState] = useState({ + spaceName: '', + spaceDescription: '', + date: new Date(), + time: Date.now(), + }) + + const { signer, env, account } = useSpaceData(); + + const handleNameChange = (event: any) => { + setSpaceState((prevState) => ({...prevState, spaceName: event.target.value})) + }; + + const handleDescriptionChange = (event: any) => { + setSpaceState((prevState) => ({...prevState, spaceDescription: event.target.value})) + }; + + const onDateChange = (dateValue: any) => { + setSpaceState((prevState) => ({...prevState, date: dateValue})) + }; + + const onTimeChange = (timeValue: any) => { + setSpaceState((prevState) => ({...prevState, time: timeValue})) + }; + + const showCreateSpace = () => { + setIsCreateModalVisible(!isCreateModalVisible); + setIsScheduleModalVisible(false); + setIsInviteModalVisible(false); + } + + const showScheduleSpace = () => { + setIsScheduleModalVisible(!isScheduleModalVisible); + setIsCreateModalVisible(false); + setIsInviteModalVisible(false); + } + + const showInviteSpace = () => { + setIsInviteModalVisible(!isInviteModalVisible); + setIsScheduleModalVisible(false); + setIsCreateModalVisible(false); + } + + const closeCreateModal = () => { + setIsCreateModalVisible(false); + } + + const closeScheduleModal = () => { + setIsScheduleModalVisible(false); + } + + const closeInviteModal = () => { + setIsInviteModalVisible(false); + } + + const clearAllState = () => { + setIsCreateModalVisible(false) + setIsScheduleModalVisible(false) + setIsInviteModalVisible(false) + setInvitedMembersList([]) + setInvitedAddressList([]) + setAdminsList([]) + setAdminsAddressList([]) + setLoading(false) + setSpaceState({ + spaceName: '', + spaceDescription: '', + date: new Date(), + time: Date.now(), + }) + } + + const testCreateSpace = async () => { + const spaceCreate = { + spaceName: spaceState.spaceName.length === 0 ? `${account}'s Space` : spaceState.spaceName, + spaceDescription: 'Push Space', + listeners: invitedAddressList, + spaceImage: 'asd', + speakers: adminsAddressList, + isPublic: true, + scheduleAt: spaceState.time > Date.now() ? new Date(spaceState.time) : new Date(Date.now() + 120000), + signer: signer as PushAPI.SignerType, + env + } + + try { + setLoading(true); + const response = await PushAPI.space.create(spaceCreate); + + console.log(response); + } catch (e:any) { + console.error(e.message); + } finally { + setLoading(false); + closeInviteModal(); + clearAllState(); + } + }; + + return ( + + { + CustomComponent + ? + + : + + } + + {isCreateModalVisible && + + } + + {isScheduleModalVisible && + + } + + {isInviteModalVisible && + + } + + ) +} + +const SCWContainer = styled.div` + font-family: 'Strawford'; // update to fontFamily theme +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/index.ts b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/index.ts new file mode 100644 index 000000000..7f6d6d24e --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/index.ts @@ -0,0 +1 @@ +export * from './SpaceCreationWidget'; diff --git a/packages/uiweb/src/lib/components/space/SpaceFeed/SpaceFeed.tsx b/packages/uiweb/src/lib/components/space/SpaceFeed/SpaceFeed.tsx new file mode 100644 index 000000000..1cb55ff6f --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceFeed/SpaceFeed.tsx @@ -0,0 +1,478 @@ +import React, { useState } from 'react'; +import styled from 'styled-components'; + +import { SpaceIFeeds } from '@pushprotocol/restapi'; + +import { SpaceBanner } from '../SpaceBanner'; + +import { Spinner } from '../reusables/Spinner'; + +import { + useSpaceData, + useFeedScroll, + useMySpaces, + usePopularSpaces, + useSpaceRequests, +} from '../../../hooks'; + +import { ISpacePaginationData } from '../../../context/spacesContext'; +import spacesIcon from '../../../icons/Spaces.svg'; + +enum OrientationEnums { + Horizontal = 'horizontal', + Vertical = 'vertical', +} + +enum Tabs { + ForYou = 'For You', + Popular = 'Popular', + HostedByYou = 'Hosted by you', +} + +enum FilterEnums { + All = 'All', + Live = 'Live', + Scheduled = 'Scheduled', +} +export interface ISpaceFeedProps { + orientation?: 'horizontal' | 'vertical'; + height?: number; + width?: number; + sortingOrder?: string[]; + showTabs?: boolean; + filter?: FilterEnums.All | FilterEnums.Live | FilterEnums.Scheduled; + showFilter?: boolean; + onBannerClickHandler?: (arg: string) => void; +} + +export const SpaceFeed: React.FC = ({ + orientation = 'veritcal', + height, + width, + sortingOrder = [Tabs.Popular, Tabs.ForYou, Tabs.HostedByYou], + showTabs = true, + filter = FilterEnums.All, + showFilter = true, + onBannerClickHandler, +}) => { + const [tab, setTab] = useState(sortingOrder[0]); + const [filterTab, setFilterTab] = useState(filter); + + const { + account, + mySpaces, + setMySpaces, + popularSpaces, + setPopularSpaces, + spaceRequests, + setSpaceRequests, + } = useSpaceData(); + + const listInnerRef = useFeedScroll(mySpaces.apiData?.length); + + const handleTabChange = (tab: string) => { + setTab(tab); + }; + + const handleFilterData = (spacesList: SpaceIFeeds[]) => { + if (filterTab === FilterEnums.All) { + return spacesList; + } else if (filterTab === FilterEnums.Live) { + return spacesList.filter( + (space: SpaceIFeeds) => space.spaceInformation?.status === 'ACTIVE' + ); + } else if (filterTab === FilterEnums.Scheduled) { + return spacesList.filter( + (space: SpaceIFeeds) => space.spaceInformation?.status === 'PENDING' + ); + } else { + return spacesList; + } + }; + + const handleMySpacesFilter = (spacesList: SpaceIFeeds[]) => { + if (tab === Tabs.HostedByYou) { + return spacesList.filter( + (space: SpaceIFeeds) => + space.spaceInformation?.spaceCreator.slice(7).toUpperCase() === + account?.toUpperCase() + ); + } + if (tab === Tabs.ForYou) { + return spacesList.filter( + (space: SpaceIFeeds) => + space.spaceInformation?.spaceCreator.slice(7).toUpperCase() !== + account?.toUpperCase() + ); + } else { + return handleFilterData(spacesList); + } + }; + + const handleClick = (spaceId: string) => { + if (onBannerClickHandler) { + return onBannerClickHandler(spaceId || ''); + } + }; + + const incrementSpacePage = async (spaces: ISpacePaginationData) => { + if ( + loading === false && + spaces.currentPage && + spaces.lastPage && + spaces.currentPage < spaces.lastPage + ) { + if (spaces === mySpaces) + spaces.currentPage && + console.log('spaces.currentPage', spaces.currentPage, Date.now()); + setMySpaces({ + currentPage: spaces.currentPage + 1, + lastPage: spaces.lastPage + 1, + }); + if (spaces === popularSpaces) + spaces.currentPage && + setPopularSpaces({ + currentPage: spaces.currentPage + 1, + lastPage: spaces.lastPage + 1, + }); + if (spaces === spaceRequests) + spaces.currentPage && + setSpaceRequests({ + currentPage: spaces.currentPage + 1, + lastPage: spaces.lastPage + 1, + }); + } else { + return; + } + }; + + const loadMoreData = async () => { + if (tab === Tabs.ForYou) { + incrementSpacePage(mySpaces); + } + if (tab === Tabs.Popular) { + incrementSpacePage(popularSpaces); + } + if (tab === Tabs.HostedByYou) { + incrementSpacePage(spaceRequests); + } + }; + + console.log(account); + + const onScroll = () => { + if (listInnerRef.current) { + const { scrollTop } = listInnerRef.current; + const { offsetHeight } = listInnerRef.current; + const { scrollHeight } = listInnerRef.current; + + if (scrollTop + offsetHeight + 1 >= scrollHeight) { + loadMoreData(); + } + } + }; + + //API calls + + const mySpaceLoading = useMySpaces(account); + const popularSpaceLoading = usePopularSpaces(); + const spaceRequestsLoading = useSpaceRequests(account); + const { loading } = + mySpaceLoading || popularSpaceLoading || spaceRequestsLoading; + + return ( +
+ {orientation === OrientationEnums.Horizontal ? ( + + {orientation === OrientationEnums.Horizontal + ? mySpaces && + mySpaces.apiData?.map((space: SpaceIFeeds) => { + return ( + + ); + }) + : mySpaces && + mySpaces.apiData?.map((space: SpaceIFeeds) => { + return ( + + ); + })} + + ) : ( + <> + + + {sortingOrder.map((tabName: string) => { + return ( + handleTabChange(tabName)} + > + {tabName} + + ); + })} + + + + setFilterTab(FilterEnums.All)} + > + All + + setFilterTab(FilterEnums.Live)} + > + Live + + setFilterTab(FilterEnums.Scheduled)} + > + Scheduled + + + + + {tab === Tabs.ForYou ? ( + + {mySpaces.apiData && + (handleFilterData( + handleMySpacesFilter(mySpaces.apiData as SpaceIFeeds[]) + ).length === 0 ? ( + + + Join a space + + Get started by joining a space + + + ) : ( + handleFilterData( + handleMySpacesFilter(mySpaces.apiData as SpaceIFeeds[]) + ).map((space: SpaceIFeeds) => { + return ( + + ); + }) + ))} + + ) : tab === Tabs.Popular ? ( + + Popular Spaces + {popularSpaces && + handleFilterData( + popularSpaces.apiData as SpaceIFeeds[] + ).map((space: SpaceIFeeds) => { + return ( + + ); + })} + + ) : ( + + {mySpaces.apiData && + (handleFilterData( + handleMySpacesFilter(mySpaces.apiData as SpaceIFeeds[]) + ).length === 0 ? ( + + + Create a space + + Get started by creating a space + + + ) : ( + handleFilterData( + handleMySpacesFilter(mySpaces.apiData as SpaceIFeeds[]) + ).map((space: SpaceIFeeds) => { + return ( + + ); + }) + ))} + + )} + {loading && } + + + + )} +
+ ); +}; + +//Styling +const ScrollContainer = styled.div<{ height?: number; width?: number }>` + width: ${(props) => (props.width ? `${props.width}px` : 'inherit')}; + height: ${(props) => (props.height ? `${props.height}px` : 'auto')}; + overflow-y: auto; +}`; +const Container = styled.div` + display: flex; + flex-direction: column; + align-items: center; + background: #ffffff; + border: 1px solid #dcdcdf; + border-radius: 12px; + padding: 24px 32px; +}`; + +const Navigation = styled.div<{ + showTabs?: boolean; + showFilter?: boolean; + width?: number; +}>` + display: ${(props) => (props.showTabs ? 'flex' : 'none')}; + flex-direction: row; + justify-content: space-between; + align-items: center; + width: ${(props) => (props.width ? `${props.width}px` : 'inherit')}; + border-bottom: 1px solid #DCDCDF; + margin-bottom: ${(props) => (props.showFilter ? '0' : '27px')}; +}`; + +const NavButtonWrapper = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +}`; + +const NavButton = styled.button<{ active?: boolean }>` + padding: 10px 30px; + font-weight: 450; + font-size: 14px; + border: none; + border-bottom: ${(props) => (props.active ? '2px solid #8B5CF6' : 'none')}; + background: none; + color : ${(props) => (props.active ? '#000000' : '#71717A')}; + + &:hover { + cursor: pointer; + } +}`; + +const Spaces = styled.div<{ orientation?: string }>` + display: flex; + flex-direction: ${(props) => + props.orientation === 'horizontal' ? 'row' : 'column'}; + justify-content: flex-start; + align-items: center; + background: #ffffff; + width: ${(props) => + props.orientation === 'horizontal' ? 'inherit' : '100%'}; + height: auto; + gap: 16px; +}`; + +const PopularSpaces = styled.div` + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + background: #ffffff; + width: 100%; + height: auto; + gap: 16px; +}`; + +const Text = styled.div` + width: 100%; + text-align: left; + font-family: 'Strawford'; + font-weight: 450; + font-size: 18px; +}`; + +const Filter = styled.div<{ showFilter?: boolean }>` + display: ${(props) => (props.showFilter ? 'flex' : 'none')}; + flex-direction: row; + justify-content: flex-start; + align-items: center; + background: #ffffff; + width: 100%; + margin: 22px 0; +}`; + +const FilterButton = styled.button<{ active: boolean }>` + display: inline-flex; + height: 30px; + padding: 0px 16px; + justify-content: center; + align-items: center; + border-radius: 99px; + border: 1px solid #C4B5FD; + background: ${(props) => (props.active ? '#8B5CF6' : '#EDE9FE')}; + color: ${(props) => (!props.active ? '#8B5CF6' : '#FFF')}; + margin-right: 8px; + font-size: 14px; + + &:hover { + cursor: pointer; + } +}`; + +const NoSpaces = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin: 130px 0; +}`; + +const SpacesIcon = styled.img` + width: 36px; + height: 36px; +}`; + +const NoSpacesTextV1 = styled.div` + font-family: 'Strawford'; + font-weight: 450; + font-size: 16px; + color: #000; +}`; + +const NoSpacesTextV2 = styled.div` + font-family: 'Strawford'; + font-weight: 450; + color: #71717A; + font-size: 14px; +}`; diff --git a/packages/uiweb/src/lib/components/space/SpaceFeed/index.ts b/packages/uiweb/src/lib/components/space/SpaceFeed/index.ts new file mode 100644 index 000000000..506cf05f5 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceFeed/index.ts @@ -0,0 +1 @@ +export * from "./SpaceFeed"; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceInvites/SpaceInvites.tsx b/packages/uiweb/src/lib/components/space/SpaceInvites/SpaceInvites.tsx new file mode 100644 index 000000000..6e808f5fa --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceInvites/SpaceInvites.tsx @@ -0,0 +1,174 @@ +import React, { useEffect, useState } from 'react'; +import styled from 'styled-components'; +import { Modal } from '../reusables/Modal'; +import { Spinner } from '../reusables/Spinner'; +import { ModalHeader } from '../reusables/ModalHeader'; +import { useFeedScroll, useSpaceData, useSpaceRequests } from '../../../hooks'; +import { SpaceBanner } from '../SpaceBanner'; + +export interface ISpaceInvitesProps { + children?: React.ReactNode; +} + +// temp +let spaceId = ""; + +export const SpaceInvites: React.FC = ({ + children, +}: ISpaceInvitesProps) => { + const [modalOpen, setModalOpen] = useState(false); + const { spaceRequests, setSpaceRequests } = useSpaceData(); + + const containerRef = useFeedScroll(spaceRequests.apiData?.length); + + const [playBackUrl, setPlayBackUrl] = useState(''); + const { + spacesObjectRef, + spaceObjectData, + initSpaceObject, + setSpaceWidgetId, + isSpeaker, + isListener, + account, + } = useSpaceData(); + + const handleJoinSpace = async (space: any) => { + await initSpaceObject(space?.spaceId as string); + + if (isSpeaker) { + // create audio stream + await spacesObjectRef.current.createAudioStream(); + spaceId = space?.spaceId; // temp + } + if (isListener) { + await spacesObjectRef?.current?.join(); + const playBackUrl = spaceObjectData.spaceDescription; + setPlayBackUrl(playBackUrl); + handleCloseModal(); + setSpaceWidgetId(space?.spaceId as string); + console.log('space joined'); + } + }; + + useEffect(() => { + if (!spaceObjectData?.connectionData?.local.stream || !isSpeaker) return; + const joinSpaceAsSpeaker = async () => { + console.log('joining as a speaker'); + await spacesObjectRef?.current?.join(); + setSpaceWidgetId(spaceId); + console.log('space joined'); + handleCloseModal(); + }; + joinSpaceAsSpeaker(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [spaceObjectData?.connectionData?.local.stream]); + + const handleOpenModal = () => { + setModalOpen(true); + }; + + const handleCloseModal = () => { + setModalOpen(false); + }; + + const loadMoreData = () => { + if ( + loading === false && + spaceRequests.currentPage && + spaceRequests.lastPage && + spaceRequests.currentPage < spaceRequests.lastPage + ) { + console.log('Load More Data'); + setSpaceRequests({ + currentPage: spaceRequests.currentPage + 1, + lastPage: spaceRequests.lastPage + 1, + }); + } + }; + + const onScrollContainer = () => { + if (containerRef.current) { + const { scrollTop, scrollHeight, clientHeight } = containerRef.current; + if (scrollTop + clientHeight >= scrollHeight) { + loadMoreData(); + } + } + }; + + const { loading } = useSpaceRequests(account); + return ( + <> + {!children && } + + {children &&
{children}
} + + {modalOpen && ( + + 0 + ? spaceRequests.apiData?.length + : undefined + } + closeCallback={handleCloseModal} + /> + + + {spaceRequests.apiData + ? spaceRequests.apiData.map((space: any) => { + return ( + handleJoinSpace(space)} + /> + ); + }) + : null} + {loading ? : null} + + + + )} + + ); +}; + +const Button = styled.button` + padding: 8px 16px; + background-color: #8b5cf6; + color: #fff; + border: none; + border-radius: 4px; + cursor: pointer; +`; + +const ScrollContainer = styled.div` + max-height: 400px; + width: inherit; + margin-top: 24px; + overflow-y: scroll; + + &::-webkit-scrollbar { + margin-left: 10px; + width: 8px; + height: 8px; + } + + &::-webkit-scrollbar-thumb { + -webkit-appearance: none; + width: 4px; + height: auto; + background: #8b5cf6; + border-radius: 99px; + } +`; + +const InviteContainer = styled.div` + display: flex; + flex-direction: column; + gap: 16px; + margin: 0 10px; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceInvites/index.ts b/packages/uiweb/src/lib/components/space/SpaceInvites/index.ts new file mode 100644 index 000000000..43c623f28 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceInvites/index.ts @@ -0,0 +1 @@ +export * from "./SpaceInvites"; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/LiveSpaceProfileContainer.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/LiveSpaceProfileContainer.tsx new file mode 100644 index 000000000..c7cf15281 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/LiveSpaceProfileContainer.tsx @@ -0,0 +1,90 @@ +import { IMediaStream } from '@pushprotocol/restapi'; +import { Image, Item, Text } from '../../../config'; + +import HandIcon from '../../../icons/hand.svg'; +import MicOffIcon from '../../../icons/micoff.svg'; +import { VideoPlayer } from './VideoPlayer'; + +export interface ILiveSpaceProfileContainerProps { + wallet: string; + isHost?: boolean; + isSpeaker?: boolean; + image: string; + requested?: boolean; + mic?: boolean; + stream?: IMediaStream; +} + +export const LiveSpaceProfileContainer = ( + options: ILiveSpaceProfileContainerProps +) => { + const { + wallet, + isHost, + isSpeaker, + image, + requested = false, + mic = true, + stream, + } = options || {}; + + return ( + + Profile pic + + {wallet.slice(7, 12).concat('...')} + {stream && } + + {requested ? ( + + + Requested + + Hand Icon + + ) : ( + + + {isHost ? 'Host' : isSpeaker ? 'Speaker' : 'Listener'} + + {!mic && ( + Mic Off Icon + )} + + )} + + ); +}; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/LiveWidgetContent.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/LiveWidgetContent.tsx new file mode 100644 index 000000000..93c056e70 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/LiveWidgetContent.tsx @@ -0,0 +1,229 @@ +import React, { useEffect, useState } from 'react'; +import styled from 'styled-components'; + +import { LiveSpaceProfileContainer } from './LiveSpaceProfileContainer'; +import { SpaceMembersSectionModal } from './SpaceMembersSectionModal'; + +import { Button, Image, Item, Text } from '../../../config'; +import MicOnIcon from '../../../icons/micon.svg'; +import MicEngagedIcon from '../../../icons/MicEngage.svg'; +import MuteIcon from '../../../icons/Muted.svg'; +import ShareIcon from '../../../icons/Share.svg'; +import MembersIcon from '../../../icons/Members.svg'; +import { SpaceDTO } from '@pushprotocol/restapi'; + +import { useSpaceData } from '../../../hooks'; +import { Player } from '@livepeer/react'; + +interface LiveWidgetContentProps { + spaceData?: SpaceDTO; + // temp props only for testing demo purpose for now + isHost?: boolean; +} +export const LiveWidgetContent: React.FC = ({ + spaceData, + isHost, +}) => { + const tempImageUrl = + 'https://imgv3.fotor.com/images/blog-richtext-image/10-profile-picture-ideas-to-make-you-stand-out.jpg'; + const [showMembersModal, setShowMembersModal] = useState(false); + const [isMicOn, setIsMicOn] = useState(true); + const [playBackUrl, setPlayBackUrl] = useState(''); + const { + spacesObjectRef, + spaceObjectData, + isSpeaker, + isListener, + setSpaceWidgetId, + isJoined, + initSpaceObject, + } = useSpaceData(); + + const handleJoinSpace = async () => { + if (!spaceData) { + return; + } + + await initSpaceObject(spaceData?.spaceId as string); + + if (isListener) { + console.log('joining as a listner'); + await spacesObjectRef?.current?.join(); + setSpaceWidgetId(spaceData?.spaceId as string); + console.log('space joined'); + } + }; + + useEffect(()=>{ + const createAudioStream = async () => { + console.log("isSpeaker", isSpeaker); + if (isSpeaker) { + // create audio stream as we'll need it to start the mesh connection + console.log('creating audio stream'); + await spacesObjectRef.current.createAudioStream(); + } + } + createAudioStream(); + }, [isSpeaker]) + + useEffect(() => { + if (!spaceObjectData?.connectionData?.local.stream || !isSpeaker) return; + const joinSpaceAsSpeaker = async () => { + console.log('joining as a speaker'); + await spacesObjectRef?.current?.join(); + setSpaceWidgetId(spaceData?.spaceId as string); + console.log('space joined'); + }; + joinSpaceAsSpeaker(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [spaceObjectData?.connectionData?.local.stream]); + + useEffect(() => { + if (!spaceObjectData.spaceDescription) return; + const playBackUrl = spaceObjectData.spaceDescription; + setPlayBackUrl(playBackUrl); + }, [spaceObjectData.spaceDescription]); + + // console.log('spaceObjectData', spaceObjectData); + // console.log('playBackUrl', playBackUrl); + // console.log('isListener', isListener); + + return ( + <> + + {isSpeaker && + spaceObjectData.connectionData.incoming.map((profile) => ( + + ))} + {isListener && + spaceObjectData.members.map((profile) => ( + + ))} + + + {isJoined ? ( + + + isHost || isSpeaker ? setIsMicOn(!isMicOn) : null + } + > + Mic Icon + + {isHost || isSpeaker + ? isMicOn + ? 'Speaking' + : 'Muted' + : 'Request'} + + + + setShowMembersModal(true)} + alt="Members Icon" + /> + Share Icon + + + {isListener && playBackUrl.length > 0 && ( + + )} + + ) : ( + + )} + {showMembersModal ? ( + setShowMembersModal(false)} + /> + ) : null} + + + ); +}; + +const PeerPlayer = styled(Player)` + width: 0; + height: 0; +}`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/ScheduledWidgetContent.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/ScheduledWidgetContent.tsx new file mode 100644 index 000000000..8b041f9c3 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/ScheduledWidgetContent.tsx @@ -0,0 +1,231 @@ +import styled from 'styled-components'; + +import { Button, Container, Image, Item, Text } from '../../../config'; +import { formatDate } from '../../../helpers'; + +import SpacesIcon from '../../../icons/Spaces.svg'; +import TwitterIcon from '../../../icons/twitterVector.svg'; +import CopyIcon from '../../../icons/copyVector.svg'; +import AtIcon from '../../../icons/atVector.svg'; +import { SpaceDTO } from '@pushprotocol/restapi'; +import { useSpaceData } from '../../../hooks'; +import { useEffect, useState } from 'react'; + +interface ScheduledWidgetContentProps { + account?: string; + spaceData?: SpaceDTO; + shareUrl?: string; + + // temp props only for testing demo purpose for now + isHost?: boolean; + isTimeToStartSpace?: boolean; + isMember?: boolean; + isSpaceLive: boolean; + setIsSpaceLive: React.Dispatch>; +} +export const ScheduledWidgetContent: React.FC = ({ + account, + spaceData, + shareUrl, + isHost, + isMember, + isSpaceLive, + setIsSpaceLive, +}: ScheduledWidgetContentProps) => { + const isTimeToStartSpace = true; + const { + spacesObjectRef, + initSpaceObject, + spaceObjectData, + } = useSpaceData(); + const [isStarted, setIsStarted] = useState(false); + + const handleStartSpace = async () => { + console.log('initializing space object'); + await initSpaceObject(spaceData?.spaceId as string); + + console.log('creating audio stream'); + await spacesObjectRef.current.createAudioStream(); + + setIsStarted(true); + console.log('Space Started'); + }; + + const handleShareTweet = () => { + if (!shareUrl) return; + const url = shareUrl; + const tweetText = 'Join this Space:'; // Replace with your desired tweet text + + const tweetUrl = `https://twitter.com/intent/tweet?text=${encodeURIComponent( + tweetText + )}&url=${encodeURIComponent(url)}`; + + window.open(tweetUrl, '_blank'); + }; + + const handleCopyLink = async () => { + try { + if (!shareUrl) return; + const url = shareUrl; + await navigator.clipboard.writeText(url); + // add a success toast here + console.log('URL copied to clipboard:', url); + } catch (error) { + console.error('Failed to copy URL:', error); + } + }; + + useEffect(() => { + async function startSpace() { + if(isSpaceLive) return; + if (!spaceObjectData?.connectionData?.local.stream || !isStarted) return; + await spacesObjectRef.current.start({ + livepeerApiKey: '2638ace1-0a3a-4853-b600-016e6125b9bc', + }); + setIsStarted(false); + setIsSpaceLive && setIsSpaceLive(true); + } + startSpace(); + }, [isStarted]); + + console.log('Rendering ScheduledWidgetContent'); + console.log('isStarted?', isStarted); + + return ( + + Spaces Icon + {isHost ? ( + isTimeToStartSpace ? ( + It’s time to start your space + ) : ( + + Your space is scheduled.
Share and let people know when to + join! +
+ ) + ) : ( + + This space will go live on{' '} + {formatDate((spaceData?.scheduleAt as any) || new Date())} + + )} + {isHost && isTimeToStartSpace && ( + + )} + {!isHost && !isMember && ( + + )} + {!isHost && isMember && ( + + )} + {(!isHost || (isHost && !isTimeToStartSpace)) && shareUrl && ( + + + + Twitter Icon + + + Twitter + + + + + Copy Icon + + + Copy Link + + + + + At Icon + + + Email + + + + )} +
+ ); +}; + +const SpaceInfoText = styled.span` + font-size: 18px; + font-weight: 600; + text-align: center; +`; + +const ShareLinkItem = styled.div` + display: flex; + flex-direction: column; + gap: 8px; + align-items: center; +`; + +const ShareLinkButton = styled.button` + background: #e4e4e7; + border-radius: 14px; + padding: 16px; + border: none; + cursor: pointer; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/SpaceMembersSectionModal.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/SpaceMembersSectionModal.tsx new file mode 100644 index 000000000..a1c43966b --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/SpaceMembersSectionModal.tsx @@ -0,0 +1,256 @@ +import React, { ReactNode, useState } from 'react'; +import styled from 'styled-components'; + +import { Modal } from '../reusables/Modal'; +import { ModalHeader } from '../reusables/ModalHeader'; +import { ProfileContainer } from '../reusables/ProfileContainer'; + +import { Button, Container, Image, Text } from '../../../config'; +import SettingsIcon from '../../../icons/settingsBlack.svg'; + +const tempImageUrl = "https://imgv3.fotor.com/images/blog-richtext-image/10-profile-picture-ideas-to-make-you-stand-out.jpg"; +const Requests: React.FC = () => { + return ( + + + + + ) +} + +const Speakers: React.FC = () => { + return ( + + + + + Settings icon + + + + + + Settings icon + + + + ) +} + +const CoHosts: React.FC = () => { + return ( + + + + + Settings icon + + + + + + Settings icon + + + + ) +} + +const Listeners: React.FC = () => { + return ( + + + + + Settings icon + + + + + + Settings icon + + + + ) +} + +interface ISpaceMembersModalProps { + onClose: () => void; +} +enum MemberTabsEnum { + CoHost = 'Co-Host', + Speakers = 'Speakers', + Requests = 'Requests', + Listeners = 'Listeners', +} + +export const SpaceMembersSectionModal: React.FC = ({ onClose }: ISpaceMembersModalProps) => { + + const [activeTab, setActiveTab] = useState(MemberTabsEnum.CoHost); + + const handleTabClick = (index: MemberTabsEnum) => { + setActiveTab(index); + }; + + const renderTabs = (): ReactNode => { + return Object.values(MemberTabsEnum).map((tab) => ( + handleTabClick(tab)} + > + {tab} + + )); + }; + + return ( + + + + + + + + {renderTabs()} + + + {activeTab === MemberTabsEnum.CoHost && } + {activeTab === MemberTabsEnum.Speakers && } + {activeTab === MemberTabsEnum.Requests && } + {activeTab === MemberTabsEnum.Listeners && } + + + + + + ) +} + +/* styling */ +// const ButtonContainer = styled.div` +// display: flex; +// justify-content: space-between; +// width: 100%; +// `; +const SpacesMembersContainer = styled.div` + color: black; + display: flex; + flex-direction: column; + margin-top: 28px; + gap: 16px; + width: 100%; +`; + +const ProfileWithSettingsContainer = styled.div` + display: flex; + justify-content: space-between; +`; + +const SettingsIconContainer = styled.div` + display: flex; + margin: 0px 16px; + align-items: center; + cursor: pointer; +` + +const TabContainer = styled.div` + display: flex; + padding: 0px 10px; +`; + +const Tab = styled.div<{active: boolean}>` + flex: 1; + padding: 10px; + text-align: center; + border-bottom: ${(props) => + props.active ? '1px solid #8B5CF6' : '1px solid #82828A26'}; + cursor: pointer; + color: ${(props) => (props.active ? '#8B5CF6' : '#82828A')}; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/SpaceWidget.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/SpaceWidget.tsx new file mode 100644 index 000000000..a93c9054a --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/SpaceWidget.tsx @@ -0,0 +1,145 @@ +import React, { MouseEventHandler, useEffect, useState } from 'react'; +import styled from 'styled-components'; +import { SpaceDTO } from '@pushprotocol/restapi'; +import * as PushAPI from '@pushprotocol/restapi'; + +import { WidgetContent } from './WidgetContent'; +import { WidgetHeader } from './WidgetHeader'; + +import { ISpaceWidgetProps } from '../exportedTypes'; +import { isLiveSpace, isHostOfSpace, isMemberOfSpace } from './helpers/utils'; + +import { useSpaceData } from '../../../hooks'; + +const DEFAULT_OFFSET = 16; +const DEFAULT_MAXWIDTH = 415; + +export const SpaceWidget: React.FC = ( + options: ISpaceWidgetProps +) => { + const { + bottomOffset = DEFAULT_OFFSET, + rightOffset = DEFAULT_OFFSET, + width, + zIndex = 1000, + spaceId, + shareUrl, + onClose = (() => { + /** */ + }) as MouseEventHandler, + isTimeToStartSpace, + } = options || {}; + const [widgetHidden, setWidgetHidden] = useState(!spaceId); + const { account, spaceObjectData, initSpaceObject, env } = useSpaceData(); + + const [isMinimized, setIsMinimized] = useState(false); + const { getSpaceInfo, setSpaceInfo } = useSpaceData(); + const [spaceData, setSpaceData] = useState(); + + const isLive = spaceData && spaceData?.status === 'ACTIVE' ? true : false; + // console.log('isLiveInWidget', isLive) + + useEffect(() => { + if (!spaceId) { + return; + } + setWidgetHidden(!spaceId); + const fetchData = async () => { + try { + if (getSpaceInfo(spaceId)) { + setSpaceData(getSpaceInfo(spaceId)); + return; + } + const response = await PushAPI.space.get({ spaceId, env }); + setSpaceInfo(spaceId, response); + setSpaceData(response); + } catch (error) { + console.error(error); + } + }; + + fetchData(); + }, [spaceId]); + + // To Be Implemented Later via Meta messages. + // useEffect(() => { + // (async () => { + // if (!spaceData) { + // return; + // } + // if (isLiveSpace(spaceData as SpaceDTO)) { + // await initSpaceObject(spaceData?.spaceId as string); + // } + // })(); + // }, [spaceData]); + + const isHost = isHostOfSpace(account, spaceData as SpaceDTO); + const isMember = isMemberOfSpace(account, spaceData as SpaceDTO); + + const toggleWidgetVisibility = () => { + setWidgetHidden(!widgetHidden); + }; + + // console.log('Rendering SpaceWidget'); + + // Implement the SpaceWidget component + return ( + + ); +}; + +interface WidgetContainerProps { + bottomOffset: number; + rightOffset: number; + width?: number; + zIndex?: number; + hidden: boolean; +} + +const Container = styled.div` + font-family: 'Strawford'; // update to fontFamily theme + border-radius: 12px; // update acc to theme + border: 1px solid #dcdcdf; // update acc to theme + display: flex; + flex-direction: column; + width: ${(props) => (props.width ? `${props.width}px` : 'auto')}; + max-width: ${(props) => + props.width ? `${props.width}px` : `${DEFAULT_MAXWIDTH}px`}; + min-width: 320px; + background: white; + justify-content: flex-start; + position: fixed; + bottom: ${(props) => props.bottomOffset}px; + right: ${(props) => props.rightOffset}px; + visibility: ${(props) => (props.hidden ? 'hidden' : 'visible')}; + opacity: ${(props) => (props.hidden ? 0 : 1)}; + transition: opacity 0.3s ease; + z-index: ${(props) => props.zIndex ?? '1000'}; + overflow: hidden; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/SpacesInfo.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/SpacesInfo.tsx new file mode 100644 index 000000000..15a363597 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/SpacesInfo.tsx @@ -0,0 +1,124 @@ +import React, { useContext, MouseEventHandler } from 'react' +import styled from 'styled-components'; + +import { Modal } from '../reusables/Modal' +import { ModalHeader } from '../reusables/ModalHeader' +import { IThemeProviderProps, ThemeContext } from '../theme/ThemeProvider'; +import { Button } from '../reusables/Button'; +import { ProfileContainer } from '../reusables/ProfileContainer'; +import Accordion from '../reusables/Accordion'; + +export interface ISpacesInfoProps { + closeSpacesInfo: MouseEventHandler; +} + +interface IThemeProps { + theme: IThemeProviderProps; +} + +export const SpacesInfo: React.FC = (props) => { + const tempImageUrl = "https://imgv3.fotor.com/images/blog-richtext-image/10-profile-picture-ideas-to-make-you-stand-out.jpg"; + + const theme = useContext(ThemeContext); + + const customStyle = { + color: theme.textColorPrimary, + background: theme.bgColorPrimary, + borderColor: theme.borderColor, + fontWeight: '500', + padding: '14px', + } + + const TEMP_MEMBERS = [ + { + handle: 's4m4', + name: 'Samarendra' + }, + { + handle: 'aamsa', + name: 'Aam Saltman' + }, + { + handle: 's4m4', + name: 'Samarendra' + }, + { + handle: 'aamsa', + name: 'Aam Saltman' + }, + ] + + return ( + + + + + + + + larryscruff's space + Ac orci quam cras in placerat. Sollicitudin tristique sed nisi proin duis. + + + + + + { + TEMP_MEMBERS.map((item) => { + return + }) + } + + + + + + + ) +} + + +/** styling */ +const SpacesInfoContainer = styled.div` + color: black; +`; + +const SpacesDetailsContainer = styled.div` + padding: 0 16px; + margin: 24px 0; +`; + +const Title = styled.div` + font-weight: 500; +`; + +const Description = styled.div` + color: ${(props => props.theme.textColorSecondary)}; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/VideoPlayer.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/VideoPlayer.tsx new file mode 100644 index 000000000..3156b2065 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/VideoPlayer.tsx @@ -0,0 +1,25 @@ +import { IMediaStream } from '@pushprotocol/restapi'; +import React, { useEffect, useRef } from 'react'; +import styled from 'styled-components'; + +export interface IVideoPlayerProps { + videoCallData: IMediaStream; +} + +export const VideoPlayer: React.FC = ({ videoCallData }) => { + const incomingVideoRef = useRef(null); + + useEffect(() => { + if (!incomingVideoRef.current) return; + const video = incomingVideoRef.current; + video.srcObject = videoCallData; + video.play(); + }, [incomingVideoRef, videoCallData]); + + return ; +}; + +const Video = styled.video` + height:0; + width:0; +}`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/WidgetContent.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/WidgetContent.tsx new file mode 100644 index 000000000..a5ee0c810 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/WidgetContent.tsx @@ -0,0 +1,82 @@ +import React, { useEffect, useState } from 'react'; +import styled from 'styled-components'; + +import { LiveWidgetContent } from './LiveWidgetContent'; +import { ScheduledWidgetContent } from './ScheduledWidgetContent'; +import { SpaceDTO } from '@pushprotocol/restapi'; +import { useSpaceData } from '../../../hooks'; + +const LIVE_WIDGET_CONTENT_FIXED_HEIGHT = '485px'; +const SCHEDULED_WIDGET_CONTENT_FIXED_HEIGHT = '350px'; + +interface WidgetContentProps { + account?: string; //Temp Prop to Test Host functionality + spaceData?: SpaceDTO; + shareUrl?: string; + isMinimized: boolean; + + // temp props only for testing demo purpose for now + isHost?: boolean; + isLive: boolean; + isTimeToStartSpace?: boolean; + isMember?: boolean; +} +export const WidgetContent: React.FC = ({ + account, + spaceData, + shareUrl, + isHost, + isTimeToStartSpace, + isMember, + isMinimized, + isLive, +}: WidgetContentProps) => { + // const { isLive } = useSpaceData(); + console.log('isLiveInWidgetContent', isLive); + const [isSpaceLive, setIsSpaceLive] = useState(false); + console.log('isSpaceLive', isSpaceLive); + + console.log('Rendering WidgetContent'); + useEffect(() => { + setIsSpaceLive(isLive); + }, [isLive]); + + return ( + + {isSpaceLive ? ( + + ) : ( + + )} + + ); +}; + +//styles +const Container = styled.div<{ height: string; isMinimized: boolean }>` + display: flex; + flex-direction: column; + border-bottom: ${(props) => props.theme.border}; + + height: ${(props) => (props.isMinimized ? '0' : props.height)}; + transition: height 200ms ease-out; + overflow: hidden; + + align-items: center; + justify-content: space-between; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/WidgetHeader.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/WidgetHeader.tsx new file mode 100644 index 000000000..7a3068ad4 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/WidgetHeader.tsx @@ -0,0 +1,213 @@ +import React, { useState, MouseEventHandler, useContext } from 'react'; +import styled from 'styled-components'; + +import { Item, Text } from '../../../config'; +import { formatDate } from '../../../helpers'; + +import SettingsIcon from '../../../icons/settings.svg'; +import CaretDownIcon from '../../../icons/CaretDown.svg'; +import CaretUpIcon from '../../../icons/CaretUp.svg'; +import CalendarIcon from '../../../icons/calendar.svg'; +import LiveIcon from '../../../icons/live.svg'; +import { CloseSvg } from '../../../icons/CloseSvg'; +import { HostPfpContainer, ParticipantContainer } from '../reusables'; +import { SpacesInfo } from './SpacesInfo'; +import { ThemeContext } from '../theme/ThemeProvider'; +import { useSpaceData } from '../../../hooks'; + +export interface IWidgetHeaderProps { + onClose: MouseEventHandler; + spaceData?: any; + isMinimized: boolean; + setIsMinimized: React.Dispatch>; + toggleWidgetVisibility: () => void; + + // temp props + isLive?: boolean; + isHost?: boolean; +} + +export const WidgetHeader: React.FC = ({ + onClose, + isMinimized, + isHost, + setIsMinimized, + toggleWidgetVisibility, + spaceData, + isLive, +}: IWidgetHeaderProps) => { + const theme = useContext(ThemeContext); + // const { isLive } = useSpaceData(); + + const tempImageUrl = + 'https://imgv3.fotor.com/images/blog-richtext-image/10-profile-picture-ideas-to-make-you-stand-out.jpg'; + + const [isSpacesInfoVisible, setIsSpacesInfoVisible] = useState(false); + const handleCloseWidget: React.MouseEventHandler = ( + event + ) => { + // Call for hiding the widget + toggleWidgetVisibility(); + + // Call for running onClose handler from prop + onClose(event); + }; + + const showSpacesInfo = () => { + setIsSpacesInfoVisible(!isSpacesInfoVisible); + console.log(isSpacesInfoVisible); + }; + + const closeSpacesInfo = () => { + setIsSpacesInfoVisible(false); + }; + + return ( + + {!isLive && ( +
+ + + + + {isHost && } + + Settings icon + + + setIsMinimized(!isMinimized)} + src={isMinimized ? CaretUpIcon : CaretDownIcon} + alt="Maximize/Minimize icon" + /> + + + + + +
+ )} +
+ + {spaceData?.spaceName || 'Test Space'} + + {isLive && ( + + + Settings icon + + + setIsMinimized(!isMinimized)} + src={isMinimized ? CaretUpIcon : CaretDownIcon} + alt="Maximize/Minimize icon" + /> + + + + + + )} +
+ {!isLive && ( + + Calendar Icon + + {formatDate(spaceData?.scheduleAt || new Date())} + + + )} + {isLive && ( +
+ + Calendar Icon + + Live + + + + + + + {/* + +190 Listeners + */} + +
+ )} + {isSpacesInfoVisible ? ( + + ) : null} +
+ ); +}; + +//styles +const Container = styled.div` + display: flex; + flex-direction: column; + color: ${(props) => props.theme.titleTextColor}; + padding: 16px 24px; + background: ${(props) => props.theme.titleBg}; +`; + +const Image = styled.img` + display: flex; + max-height: initial; + vertical-align: middle; + overflow: initial; + cursor: pointer; + height: ${(props: any): string => props.height || '24px'}; + width: ${(props: any): string => props.width || '20px'}; + align-self: center; +`; + +const Section = styled.div<{ marginTop?: string }>` + display: flex; + justify-content: space-between; + margin-top: ${(props) => props.marginTop}; +`; + +const Button = styled.button<{ + padding?: string; + color?: string; +}>` + padding: ${(props) => props.padding ?? '0px'}; + color: ${(props) => props.color ?? 'inherit'}; + margin-left: 10px; + background: rgba(255, 255, 255, 0.2); + border-radius: 6px; + border: none; + cursor: pointer; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/helpers/utils.ts b/packages/uiweb/src/lib/components/space/SpaceWidget/helpers/utils.ts new file mode 100644 index 000000000..bc518b603 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/helpers/utils.ts @@ -0,0 +1,31 @@ +import { SpaceDTO } from '@pushprotocol/restapi'; +import { getSpaceStatus } from '../../helpers/space'; + +export const isHostOfSpace = (account: string, spaceData: SpaceDTO) => { + return ( + account.toUpperCase() === spaceData?.spaceCreator.slice(7).toUpperCase() + ); +}; + +export const isMemberOfSpace = (account: string, spaceData: SpaceDTO) => { + const isMemberArr = spaceData?.members.filter( + (member) => member.wallet.slice(7).toUpperCase() === account.toUpperCase() + ); + return isMemberArr?.length > 0; +}; + +export const isLiveSpace = (spaceData: SpaceDTO) => { + return getSpaceStatus(spaceData?.status) === 'Live'; +}; + +export const isTimeToStart = (spaceData: SpaceDTO, now: Date) => { + const isScheduled = spaceData?.status === 'PENDING'; + const scheduledTime = spaceData?.scheduleAt as Date; + + //true 15 min before scheduledTime + if (scheduledTime && isScheduled) { + return now.getTime() >= new Date(scheduledTime).getTime() - 15 * 60 * 1000; + } else { + return false; + } +}; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/index.ts b/packages/uiweb/src/lib/components/space/SpaceWidget/index.ts new file mode 100644 index 000000000..06fa7de30 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/index.ts @@ -0,0 +1 @@ +export * from "./SpaceWidget"; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpacesUI.tsx b/packages/uiweb/src/lib/components/space/SpacesUI.tsx new file mode 100644 index 000000000..0db6e0989 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpacesUI.tsx @@ -0,0 +1,78 @@ +import React, { useEffect, useState } from 'react'; + +import { ISpaceBannerProps, SpaceBanner } from './SpaceBanner'; +import { SpaceWidget } from './SpaceWidget'; +import { ISpaceFeedProps, SpaceFeed } from './SpaceFeed'; +import { ISpaceInvitesProps, SpaceInvites } from './SpaceInvites'; +import { SpaceCreationWidget } from './SpaceCreationWidget'; + +import { SignerType } from '../../types'; +import { ENV } from '../../config'; +import { useSpaceData } from '../../hooks'; +import { ISpacesUIProps, ISpaceWidgetProps } from './exportedTypes'; + +export class SpacesUI { + public account: string; + public signer: SignerType; + public pgpPrivateKey: string; + public env: ENV; + + constructor(props: ISpacesUIProps) { + this.account = props.account; + this.signer = props.signer; + this.pgpPrivateKey = props.pgpPrivateKey; + this.env = props.env; + } + + SpaceBanner: React.FC = (options: ISpaceBannerProps) => { + const { spaceInfo, setSpaceInfo } = useSpaceData(); + + // Use spaceBannerData and setSpaceBannerData in your component + + return ; + }; + + SpaceWidget: React.FC = (options: ISpaceWidgetProps) => { + const { spaceId } = options; + const { spaceWidgetId } = useSpaceData(); + const [SpaceId, setSpaceId] = useState(spaceId); + + useEffect(() => { + setSpaceId(spaceId); + }, [spaceId, setSpaceId]); + + useEffect(() => { + setSpaceId(spaceWidgetId); + }, [spaceWidgetId, setSpaceId]); + + return ; + } + + SpaceFeed: React.FC = (options: ISpaceFeedProps) => { + return ; + }; + + SpaceInvites: React.FC = (options: ISpaceInvitesProps) => { + return ; + }; + + SpaceCreationButtonWidget = () => { + return + } + + connectToSockets = () => { + // Connect to sockets and listen for events + // Update spaceBannerData or trendingListData based on events + const { setSpaceInfo, setTrendingListData } = useSpaceData(); + + // Example of updating spaceBannerData + //setSpaceBannerData(); + }; + + init = () => { + // Initialization logic + + // Call connectToSockets or any other initialization tasks + this.connectToSockets(); + }; +} diff --git a/packages/uiweb/src/lib/components/space/exportedTypes.ts b/packages/uiweb/src/lib/components/space/exportedTypes.ts new file mode 100644 index 000000000..9c4aaf140 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/exportedTypes.ts @@ -0,0 +1,30 @@ +import { MouseEventHandler } from "react"; + +import { ENV } from "../../config"; +import { SignerType } from "../../types"; + +export interface ISpacesUIProps { + account: string; + signer: SignerType; + pgpPrivateKey: string; + env: ENV; +} + +export interface ISpaceWidgetProps { + // Add props specific to the SpaceWidget class method + account?: string; + bottomOffset?: number; + rightOffset?: number; + zIndex?: number; + spaceId?: string; + width?: number; + shareUrl?: string; + onClose?: MouseEventHandler; + + // props only for testing demo purpose for now + isHost?: boolean; + isLive?: boolean; + isJoined?: boolean; + isTimeToStartSpace? :boolean; + isMember?: boolean; +} diff --git a/packages/uiweb/src/lib/components/space/helpers/blockies.ts b/packages/uiweb/src/lib/components/space/helpers/blockies.ts new file mode 100644 index 000000000..7cfb98eb3 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/helpers/blockies.ts @@ -0,0 +1,119 @@ +const randseed: number[] = new Array(4); // Xorshift: [x, y, z, w] 32 bit values + +function seedrand(seed: string) { + randseed.fill(0); + + for (let i = 0; i < seed.length; i++) { + randseed[i % 4] = ((randseed[i % 4] << 5) - randseed[i % 4]) + seed.charCodeAt(i); + } +} + +function rand(): number { + // based on Java's String.hashCode(), expanded to 4 32bit values + const t = randseed[0] ^ (randseed[0] << 11); + + randseed[0] = randseed[1]; + randseed[1] = randseed[2]; + randseed[2] = randseed[3]; + randseed[3] = (randseed[3] ^ (randseed[3] >> 19) ^ t ^ (t >> 8)); + + return (randseed[3] >>> 0) / ((1 << 31) >>> 0); +} + +function createColor(): string { + // saturation is the whole color spectrum + const h = Math.floor(rand() * 360); + // saturation goes from 40 to 100, it avoids grayish colors + const s = `${Math.floor(rand() * 60) + 40}%`; + // lightness can be anything from 0 to 100, but probabilities are a bell curve around 50% + const l = `${Math.floor((rand() + rand() + rand() + rand()) * 25)}%`; + + return `hsl(${h},${s},${l})`; +} + +function createImageData(size: number): number[] { + const width = size; // Only support square icons for now + const height = size; + + const dataWidth = Math.ceil(width / 2); + const mirrorWidth = width - dataWidth; + + const data: number[] = []; + for (let y = 0; y < height; y++) { + let row: number[] = []; + for (let x = 0; x < dataWidth; x++) { + // this makes foreground and background color have a 43% (1/2.3) probability + // spot color has a 13% chance + row[x] = Math.floor(rand() * 2.3); + } + const r = row.slice(0, mirrorWidth); + r.reverse(); + row = row.concat(r); + + for (let i = 0; i < row.length; i++) { + data.push(row[i]); + } + } + + return data; +} + +interface Options { + seed?: string; + size?: number; + scale?: number; + color?: string; + bgcolor?: string; + spotcolor?: string; +} + +function buildOpts(opts: Options): Options { + const newOpts: Options = {}; + + newOpts.seed = opts.seed || Math.floor((Math.random() * Math.pow(10, 16))).toString(16); + + seedrand(newOpts.seed); + + newOpts.size = opts.size || 8; + newOpts.scale = opts.scale || 4; + newOpts.color = opts.color || createColor(); + newOpts.bgcolor = opts.bgcolor || createColor(); + newOpts.spotcolor = opts.spotcolor || createColor(); + + return newOpts; +} + +export function renderIcon(opts: Options, canvas: HTMLCanvasElement): HTMLCanvasElement { + opts = buildOpts(opts || {}); + const imageData = createImageData(opts.size!); + const width = Math.sqrt(imageData.length); + + canvas.width = canvas.height = opts.size! * opts.scale!; + + const cc = canvas.getContext('2d')!; + cc.fillStyle = opts.bgcolor!; + cc.fillRect(0, 0, canvas.width, canvas.height); + cc.fillStyle = opts.color!; + + for (let i = 0; i < imageData.length; i++) { + // if data is 0, leave the background + if (imageData[i]) { + const row = Math.floor(i / width); + const col = i % width; + + // if data is 2, choose spot color, if 1 choose foreground + cc.fillStyle = imageData[i] === 1 ? opts.color! : opts.spotcolor!; + cc.fillRect(col * opts.scale!, row * opts.scale!, opts.scale!, opts.scale!); + } + } + + return canvas; +} + +export function createIcon(opts: Options): HTMLCanvasElement { + const canvas = document.createElement('canvas'); + + renderIcon(opts, canvas); + + return canvas; +} diff --git a/packages/uiweb/src/lib/components/space/helpers/date.ts b/packages/uiweb/src/lib/components/space/helpers/date.ts new file mode 100644 index 000000000..fc9bcd62a --- /dev/null +++ b/packages/uiweb/src/lib/components/space/helpers/date.ts @@ -0,0 +1,48 @@ +/** + * Get Date and Time in Day. + * @param {string | Date} datestring - The JavaScript Date String or Date Object. + * @returns {string} - The Date and Time in Day, DD Month at HH:MM AM format. + */ + +export function getDateAndTime(datestring: string | Date) { + const date = new Date(datestring); + + //Day of Week + const dayOfWeek = date.getDay(); + const weekdays = [ + 'Sunday', + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday', + ]; + const weekday = weekdays[dayOfWeek]; + + //Date + const day = date.getDate(); + const monthIndex = date.getMonth(); + const months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', + ]; + const month = months[monthIndex]; + + //Time + const amOrPm = date.getHours() >= 12 ? 'PM' : 'AM'; + const hour = amOrPm === 'PM' ? date.getHours() % 12 : date.getHours(); + const minute = date.getMinutes(); + + return `${weekday}, ${day} ${month} at ${hour}:${minute} ${amOrPm}`; + } diff --git a/packages/uiweb/src/lib/components/space/helpers/space.ts b/packages/uiweb/src/lib/components/space/helpers/space.ts new file mode 100644 index 000000000..57eb76703 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/helpers/space.ts @@ -0,0 +1,12 @@ +/** + * Get Status of the Space. + * @param {string | Date} datestring - The JavaScript Date String or Date Object. + * @returns {string} - The Status of the Space. + */ + +export type ISpaceStatus = 'Live' | 'Scheduled' | 'Ended'; +export function getSpaceStatus(status: any): ISpaceStatus { + if (status === 'ACTIVE') return 'Live'; + if (status === 'PENDING') return 'Scheduled'; + return 'Ended'; +} diff --git a/packages/uiweb/src/lib/components/space/index.ts b/packages/uiweb/src/lib/components/space/index.ts new file mode 100644 index 000000000..6d9bc714a --- /dev/null +++ b/packages/uiweb/src/lib/components/space/index.ts @@ -0,0 +1,15 @@ +import { ISpaceBannerProps } from "./SpaceBanner"; +import { ISpaceFeedProps } from "./SpaceFeed"; +import { SpacesUI } from "./SpacesUI"; +import { ISpaceInvitesProps } from "./SpaceInvites"; +import { ISpaceCreateWidgetProps } from "./SpaceCreationWidget"; + +export { + SpacesUI, + ISpaceBannerProps, + ISpaceFeedProps, + ISpaceInvitesProps, + ISpaceCreateWidgetProps +} + +export * from './exportedTypes'; diff --git a/packages/uiweb/src/lib/components/space/reusables/Accordion.tsx b/packages/uiweb/src/lib/components/space/reusables/Accordion.tsx new file mode 100644 index 000000000..d962d5fdd --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/Accordion.tsx @@ -0,0 +1,89 @@ +import React, { useState, useContext } from 'react'; +import styled from 'styled-components'; + +import CaretDownIcon from '../../../icons/CaretDownGrey.svg'; +import CaretUpIcon from '../../../icons/CaretUpGrey.svg'; +import { ThemeContext } from '../theme/ThemeProvider'; + +interface IAccordionProps { + title: string; + items?: number; + children: React.ReactNode; +} + +const Accordion: React.FC = ({ title, items, children }) => { + const theme = useContext(ThemeContext) + + const [isOpen, setIsOpen] = useState(true); + + const toggleAccordion = () => { + setIsOpen((prevIsOpen) => !prevIsOpen); + }; + + return ( + + + + <div>{title}</div> + { items ? <PendingCount theme={theme}>{items}</PendingCount> : null } + + Maximize/Minimize icon + + {children} + + ); +}; + +export default Accordion; + +/* styling */ +const AccordionParent = styled.div` + border: 1px solid #E4E4E7; + border-radius: 8px; + padding: 6.5px 0; + margin: 16px 0; +`; + +const AccordionBody = styled.div<{ isOpen: boolean }>` + overflow-y: scroll; + max-height: ${({ isOpen }) => (isOpen ? '200px' : '0')}; + transition: max-height 200ms ease-out; +`; + +const AccordionTitle = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + + padding: 8px 16px; + + cursor: pointer; +`; + +const Title = styled.div` + display: flex; + align-items: center; +`; + +const PendingCount = styled.div` + background: ${(props => props.theme.btnColorPrimary)}; + border-radius: 8px; + padding: 4px 10px; + margin-left: 6px; + font-size: 13px; + color: ${(props => props.theme.titleTextColor)}; +`; + +const Image = styled.img` + display: flex; + max-height: initial; + vertical-align: middle; + overflow: initial; + cursor: pointer; + height: ${(props: any): string => props.height || '24px'}; + width: ${(props: any): string => props.width || '20px'}; + align-self: center; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/reusables/Button.tsx b/packages/uiweb/src/lib/components/space/reusables/Button.tsx new file mode 100644 index 000000000..8ae710ad7 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/Button.tsx @@ -0,0 +1,82 @@ +/** + * @file Button + * generic button component for spaces + * Represents the props for the Button component. + * @interface IButtonProps + * @property {string} [width] - The width of the button. Optional. + * @property {React.ReactNode} children - The content of the button. + * @property {React.MouseEventHandler} [onClick] - The click event handler for the button. Optional. + * @property {ISpacesTheme} [theme] - The theme for the button. Optional. + * @property {any} [customStyle] - Custom styles for the button. Optional. + */ + +import { MouseEventHandler, useContext } from 'react' +import styled from 'styled-components'; + +import { ISpacesTheme } from '../theme'; +import { ThemeContext } from '../theme/ThemeProvider'; + +export interface IButtonProps { + width?: string; + height?: string; + children: any; + onClick?: MouseEventHandler; + theme?: ISpacesTheme; + customStyle?: any; +} + +/** + * A button component. + * @function Button + * @param {IButtonProps} props - The props for the Button component. + * @returns {JSX.Element} The rendered Button component. + */ +export const Button: React.FC = (props) => { + const theme = useContext(ThemeContext); + + const { onClick, width, height, customStyle } = props; + + return ( + + { props.children } + + ) +} + +/* styling */ +const SpacesButton = styled.button` + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: ${(props => props.customStyle ? props.customStyle.padding : '10px 16px')}; + margin-top: 12px; + + background: ${(props => props.customStyle ? props.customStyle.background : props.theme.btnColorPrimary)}; + border: 2px solid ${(props => props.customStyle ? props.customStyle.borderColor : props.theme.btnOutline)}; + color: ${(props => props.customStyle ? props.customStyle.color : props.theme.titleTextColor)}; + border-radius: 8px; + font-size: 14px; + font-weight: ${(props => props.customStyle ? props.customStyle.fontWeight : '700')}; + font-family: 'Strawford'; // update to fontFamily theme + + /* Inside auto layout */ + flex: none; + order: 0; + flex-grow: 0; + + transition: 150ms ease-in-out; + + &:hover { + cursor: pointer; + } + + width: ${(props => props.width ? props.width : '100%')}; + height: ${(props => props.height ? props.height : '100%')}; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/reusables/Checkbox.tsx b/packages/uiweb/src/lib/components/space/reusables/Checkbox.tsx new file mode 100644 index 000000000..6bfb07c13 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/Checkbox.tsx @@ -0,0 +1,18 @@ +export const Checkbox = (props: { + id: string; + label: string; + value?: boolean; + onChange: () => void; +}) => { + return ( +
+ + +
+ ); +}; diff --git a/packages/uiweb/src/lib/components/space/reusables/DateTimePicker.tsx b/packages/uiweb/src/lib/components/space/reusables/DateTimePicker.tsx new file mode 100644 index 000000000..1938bf21b --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/DateTimePicker.tsx @@ -0,0 +1,149 @@ +/* eslint-disable prefer-const */ +import React, { useContext, useState, useEffect } from 'react'; +import styled from 'styled-components'; + +import { ThemeContext } from '../theme/ThemeProvider'; + +interface DateTimePickerProps { + propsDate: Date; + propsTime: string; + onDateChange?: any; + onTimeChange?: any; +} + +const DateTimePicker: React.FC = (props) => { + const { + propsDate, onDateChange, onTimeChange, + } = props; + const theme = useContext(ThemeContext); + + const [selectedHours, setSelectedHours] = useState('0'); + const [selectedMinutes, setSelectedMinutes] = useState('0'); + const [selectedAMPM, setSelectedAMPM] = useState('AM'); + const [timeHumanReadable, setTimeHumanReadable] = useState(0); + console.log("🚀 ~ file: DateTimePicker.tsx:24 ~ timeHumanReadable:", timeHumanReadable) + + const handleDateChange = (event: React.ChangeEvent) => { + const date = new Date(event.target.value); + onDateChange(date); + }; + + const getTime = (hours: number, minutes: number, ampm: string, propsDate: Date) => { + let totalMinutes = hours * 60 + minutes; + + if (ampm === 'PM' && hours !== 12) { + totalMinutes += 12 * 60; + } else if (ampm === 'AM' && hours === 12) { + totalMinutes -= 12 * 60; + } + + const date = new Date(propsDate); + date.setHours(0, 0, 0, 0); + date.setMinutes(totalMinutes); + + return date.getTime(); + }; + + useEffect(() => { + const hours = parseInt(selectedHours, 10); + const minutes = parseInt(selectedMinutes, 10); + const ampm = selectedAMPM; + + const newTimeEpoch = getTime(hours, minutes, ampm, propsDate); + setTimeHumanReadable(newTimeEpoch); + + onTimeChange(newTimeEpoch) + }, [selectedHours, selectedMinutes, selectedAMPM, propsDate]); + + return ( + +
Select date and time
+ + + + + + +
+ ); +}; + +const DateTimeCont = styled.div` + display: flex; + flex-direction: column; + + margin-top: 24px; +`; + +const Input = styled.input` + padding: 16px; + margin-top: 12px; + + width: 330px; + + background: #FFFFFF; + border: 1px solid ${(props => props.theme.btnOutline)}; + box-shadow: -1px -1px 2px ${(props => props.theme.btnOutline)}, 1px 1px 2px ${(props => props.theme.btnOutline)}; + border-radius: 12px; + + font-size: 16px; + font-family: 'Strawford'; +`; + +const TimeContainer = styled.div` + display: flex; + width: 100%; + gap: 12px; +`; + +const Select = styled.select<{ width?: string }>` + padding: 16px; + margin-top: 12px; + + background: #FFFFFF; + border: 1px solid ${(props => props.theme.btnOutline)}; + box-shadow: -1px -1px 2px ${(props => props.theme.btnOutline)}, 1px 1px 2px ${(props => props.theme.btnOutline)}; + border-radius: 12px; + + font-size: 16px; + font-family: 'Strawford'; + width: ${(props => props.width ? props.width : '100%')}; +`; + +export default DateTimePicker; diff --git a/packages/uiweb/src/lib/components/space/reusables/HostPfpContainer.tsx b/packages/uiweb/src/lib/components/space/reusables/HostPfpContainer.tsx new file mode 100644 index 000000000..3c410a760 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/HostPfpContainer.tsx @@ -0,0 +1,111 @@ +import React from 'react'; +import styled from 'styled-components'; + +export interface IHostPfpContainerProps { + name?: string; + handle?: string; + imageUrl?: string; + statusTheme: "Live" | "Scheduled" | "Ended"; + imageHeight?: string; +} + +export const HostPfpContainer: React.FC = ({ + name = "Host Name", + handle = "Host Handle", + imageUrl = "", + statusTheme, + imageHeight, +}: IHostPfpContainerProps) => { + return ( + + + + + + + {name} + Host + + {handle && + + {/* Fetch the handle from Lenster */}@{handle} + + } + + + ); +}; + +const ProfileContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + width: 100%; + align-items: center; +`; + +const PfpContainer = styled.div` + display: flex; +`; + +const Pfp = styled.img<{ imageHeight?: string }>` + height: ${(props) => (props.imageHeight ?? '32px')}; + width: ${(props) => (props.imageHeight ?? '32px')};; + border-radius: 50%; +`; + +const HostContainer = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + padding-left: 8px; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; +`; + +const HostName = styled.div` + display: flex; + flex-direction: row; + font-weight: 600; + font-size: 15px; + width: 100%; +`; + +const Name = styled.span` + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +`; + +const Host = styled.div<{ statusTheme?: string }>` + display: flex; + flex-direction: row; + align-items: center; + padding: 2px 8px; + margin-left: 8px; + line-height: 18px; + width: max-content; + height: 19px; + background: ${(props) => + props.statusTheme === 'Live' + ? 'rgba(255, 255, 255, 0.2);' + : 'rgba(139, 92, 246, 0.2)'}; + color: ${(props) => (props.statusTheme === 'Live' ? 'inherit' : '#8B5CF6')}; + border-radius: 6px; + font-weight: 500; + font-size: 10px; +`; + +const HostHandle = styled.div<{ statusTheme?: string }>` + color: ${(props) => (props.statusTheme === 'Live' ? '#F5F5F5E5' : '#71717A')}; + padding: 0; + font-weight: 450; + font-size: 14px; + line-height: 130%; + width: 100%; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +`; diff --git a/packages/uiweb/src/lib/components/space/reusables/Modal.tsx b/packages/uiweb/src/lib/components/space/reusables/Modal.tsx new file mode 100644 index 000000000..b45a54949 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/Modal.tsx @@ -0,0 +1,83 @@ +/** + * @file Modal + * generic modal component for spaces UI + * does not handle any business logic, acts only as a container + */ +import { useRef, useContext } from 'react'; +import styled from 'styled-components' + +import { ThemeContext } from '../theme/ThemeProvider'; + +import { useClickAway } from '../../../hooks'; + +interface IModalProps { + width?: string; + clickawayClose?: () => void; + children: any; +} + +const ClickawayCloseModal = ({ children, clickawayClose, width }: IModalProps) => { + const modalRef = useRef(null); + const theme = useContext(ThemeContext) + + useClickAway(modalRef, () => { + if (clickawayClose) { + clickawayClose(); + } + }); + + return ( + + {children} + + ); +}; + +export const Modal = ({ clickawayClose, children, width }: IModalProps) => { + const theme = useContext(ThemeContext) + return ( + + {clickawayClose ? ( + {children} + ) : ( + + { children } + + )} + + ); +}; + +/* styling */ + +const ModalOverlay = styled.div` + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.4); /* Black with 40% opacity */ + display: flex; + justify-content: center; + align-items: center; +`; + +const ModalParent = styled.div` + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + + display: flex; + flex-direction: column; + align-items: center; + padding: 24px 20px; + + background: ${(props => props.theme.bgColorPrimary)}; + border-radius: 12px; + + width: ${(props => props.width ? props.width : 'auto')}; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/reusables/ModalHeader.tsx b/packages/uiweb/src/lib/components/space/reusables/ModalHeader.tsx new file mode 100644 index 000000000..e6df966a6 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/ModalHeader.tsx @@ -0,0 +1,101 @@ +import { MouseEventHandler } from 'react'; +import styled from 'styled-components'; + +import { CloseSvg } from '../../../icons/CloseSvg'; +import { ArrowLeft } from '../../../icons/ArrowLeft'; + +export interface IModalHeaderProps { + heading: string; + headingBadgeNumber?: number; + backCallback?: MouseEventHandler; + closeCallback?: MouseEventHandler; +} + +export const ModalHeader = (props: IModalHeaderProps) => { + return ( +
+
+ {props.backCallback ? ( + + + + ) : null} + + + {props.heading} + {props.headingBadgeNumber && {props.headingBadgeNumber}} + + + {props.closeCallback ? ( + + + + ) : null} +
+
+ ); +}; + +/* styling */ +const Header = styled.div` + display: flex; + align-items: center; + width: 100%; + + margin-bottom: 24px; +`; + +const BackBtn = styled.button` + position: absolute; + top: 0; + left: 0; + margin: 1.5rem; + + border: none; + background: transparent; + + &:hover { + cursor: pointer; + } +`; + +const CloseBtn = styled.button` + position: absolute; + top: 0; + right: 0; + margin: 1.5rem; + + border: none; + background: transparent; + + &:hover { + cursor: pointer; + } +`; + +const CenterText = styled.div` + position: absolute; + top: 0; + left: 50%; + transform: translateX(-50%); + margin: 1.5rem 0; + + display: flex; + flex-direction: row; + align-items: center; + + font-weight: 500; +`; + +const NumberBadge = styled.div` + display: flex; + justify-content: center; + align-items: center; + background:#8B5CF6; + color: #fff; + border-radius: 8px; + margin-left: 8px; + padding: 4px 8px; + font-size: 13px; + font-weight: 500; +}`; diff --git a/packages/uiweb/src/lib/components/space/reusables/ParticipantContainer.tsx b/packages/uiweb/src/lib/components/space/reusables/ParticipantContainer.tsx new file mode 100644 index 000000000..789f016ce --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/ParticipantContainer.tsx @@ -0,0 +1,98 @@ +import React from 'react'; +import styled from 'styled-components'; + +export interface IParticipantContainerProps { + participants: any[]; + orientation?: 'maximized' | 'minimized' | 'pill'; + imageHeight?: any; +} + +export const ParticipantContainer: React.FC = ({ + participants, + orientation, + imageHeight, +}) => { + return ( + + + {orientation === 'pill' + ? participants && + participants.map( + (person, index) => + index < 2 && ( + + ) + ) + : participants && + participants.map( + (person, index) => + index < 3 && ( + + ) + )} + + + {orientation === 'pill' + ? participants && (participants.length as number) - 3 > 0 + ? `+${(participants.length as number) - 3}` + : null + : participants && (participants.length as number) - 3 > 0 + ? `+${(participants.length as number) - 3}` + : null} + + + ); +}; + +const Participants = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; +}`; + +const ParticipantsIconContainer = styled.div<{ orientation?: string }>` + display: grid; + grid-template-columns: repeat(5, 1fr); + width: ${(props) => (props.orientation === 'pill' ? '46.5px' : '62px')}; + padding: 0 4px; +}`; + +const ParticipantsIcon = styled.img<{ imageHeight?: any }>` + height: ${(props) => (props.imageHeight ? props.imageHeight : '31px')}; + border-radius: 50%; + + &.index0 { + position: relative; + top: 0; + left: 0; + z-index: 3; + } + &.index1 { + position: relative; + top: 0; + left: -50%; + z-index: 2; + } + &.index2 { + position: relative; + top: 0; + left: -100%; + z-index: 1; + } +}`; + +const ParticipantsText = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: auto; +}`; diff --git a/packages/uiweb/src/lib/components/space/reusables/ProfileContainer.tsx b/packages/uiweb/src/lib/components/space/reusables/ProfileContainer.tsx new file mode 100644 index 000000000..4eed4f884 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/ProfileContainer.tsx @@ -0,0 +1,229 @@ +import React, { useContext, useState, useRef, useEffect } from 'react'; +import styled, { keyframes } from 'styled-components'; +import { ThemeContext } from '../theme/ThemeProvider'; + +export interface IProfileContainerProps { + name?: string; + handle?: string; + imageUrl?: string; + tag?: string; + imageHeight?: string; + border?: boolean; + contBtn?: any; + btnCallback?: any; + removeCallback?: any; + promoteCallback?: any; +} + +export const ProfileContainer: React.FC = ({ + name = "Host Name", + handle = "Host Handle", + imageUrl = "", + tag, + imageHeight, + border = false, + contBtn, + btnCallback, + removeCallback, + promoteCallback, +}: IProfileContainerProps) => { + const theme = useContext(ThemeContext); + + const dropdownRef = useRef(null); + + const [isDDOpen, setIsDDOpen] = useState(false) + + const handleDDState = () => { + setIsDDOpen(!isDDOpen) + } + + useEffect(() => { + const handleOutsideClick = (event: any) => { + if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { + setIsDDOpen(false); + } + }; + + document.addEventListener('mousedown', handleOutsideClick); + + return () => { + document.removeEventListener('mousedown', handleOutsideClick); + }; + }, []); + + return ( + + + + + + + + {name} + + {handle && + + {/* Fetch the handle from Lenster */}@{handle} + + } + + { tag ? {tag} : null } + { contBtn ?
{contBtn}
: null } +
+ + { + isDDOpen ? + + + Remove + + { + promoteCallback ? + + Make Admin + + : null + } + + : null + } +
+ ); +}; + +const ParentContainer = styled.div<{ border?: boolean }>` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + + position: relative; + + padding: 8px 16px; + + border: ${(props => props.border ? '1px solid #E4E4E7' : 'none')}; + border-radius: 16px; +`; + +const PfpContainer = styled.div` + display: flex; +`; + +const Pfp = styled.img<{ imageHeight?: string }>` + height: ${(props) => (props.imageHeight ?? '32px')}; + width: ${(props) => (props.imageHeight ?? '32px')};; + border-radius: 50%; +`; + +const HostContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding-left: 8px; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; +`; + +const ProfileDetails = styled.div` + display: flex; + flex-direction: column; + + flex-grow: 1; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + + width: 200px; +`; + +const HostName = styled.div` + display: flex; + flex-direction: row; + font-weight: 600; + font-size: 15px; + width: 100%; +`; + +const Name = styled.span` + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +`; + +const Host = styled.div` + display: flex; + flex-direction: row; + align-items: center; + margin-left: 8px; + line-height: 18px; + width: max-content; + background: rgba(139, 92, 246, 0.2); + color: #8B5CF6; + border-radius: 6px; + font-weight: 500; + font-size: 12px; + padding: 6px 10px; + border-radius: 8px; +`; + +const HostHandle = styled.div<{ theme?: any }>` + background: ${(props => props.theme.textGradient)}; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + padding: 0; + font-weight: 450; + font-size: 14px; + line-height: 130%; + width: 100%; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +`; + +const DropDown = styled.div<{ theme?: any, isDDOpen: any }>` + position: absolute; + top: 0px; + right: 0px; + + display: flex; + flex-direction: column; + gap: 12px; + + justify-content: center; + align-items: start; + + animation: ${({ isDDOpen }) => (isDDOpen ? fadeIn : fadeOut)} 0.2s ease-in-out; + padding: 16px; + background: ${(props => props.theme.bgColorPrimary)}; + color: ${(props => props.theme.textColorPrimary)}; + border-radius: 16px; + + border: 1px solid ${(props => props.theme.borderColor)}; +`; + +const DDItem = styled.div` + cursor: pointer; +`; + +const fadeIn = keyframes` + from { + opacity: 0; + } + to { + opacity: 1; + } +`; + +const fadeOut = keyframes` + from { + opacity: 1; + } + to { + opacity: 0; + visibility: hidden; + } +`; diff --git a/packages/uiweb/src/lib/components/space/reusables/SearchInput.tsx b/packages/uiweb/src/lib/components/space/reusables/SearchInput.tsx new file mode 100644 index 000000000..5f44c25e2 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/SearchInput.tsx @@ -0,0 +1,76 @@ +import { ChangeEvent, useContext } from 'react'; +import styled from 'styled-components'; + +import { ISpacesTheme } from '../theme'; +import { ThemeContext } from '../theme/ThemeProvider'; + +import { CloseSvg } from '../../../icons/CloseSvg'; + +export interface ISearchInputProps { + labelName?: string; + inputValue?: string; + onInputChange?: any; + clearInput?: any; +} + +export const SearchInput = (props: ISearchInputProps) => { + const theme = useContext(ThemeContext); + + const handleChange = (event: ChangeEvent) => { + props.onInputChange(event); + }; + + return ( + + + + + + + + + + + + ); +}; + +/* styling */ +const InputContainer = styled.div` + display: flex; + flex-direction: column; + + margin: 16px 0; + + font-family: 'Strawford'; // update to fontFamily theme +`; + +const LabelContainer = styled.div` + display: flex; + justify-content: space-between; + + font-weight: 500; +`; + +const Input = styled.input` + padding: 16px; + margin-top: 12px; + + width: 330px; + + background: #FFFFFF; + border: 1px solid ${(props => props.theme.btnOutline)}; + box-shadow: -1px -1px 2px ${(props => props.theme.btnOutline)}, 1px 1px 2px ${(props => props.theme.btnOutline)}; + border-radius: 12px; +`; + +const InputWrapper = styled.div` + position: relative; +`; + +const CloseBtn = styled.div` + position: absolute; + right: 0; + top: 0; + padding: 1.75rem 0.75rem; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/reusables/Spinner.tsx b/packages/uiweb/src/lib/components/space/reusables/Spinner.tsx new file mode 100644 index 000000000..d635de040 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/Spinner.tsx @@ -0,0 +1,35 @@ +import React, { useContext } from 'react'; +import styled, { keyframes } from 'styled-components'; +import { SpinnerSvg } from '../../../icons/SpinnerSvg'; + +type SpinnerPropType = { + size?: string; +}; + +type SpinLoaderPropType = { + width?: string; +}; + +export const Spinner: React.FC = ({ size = 42 }) => { + return ( + + + + ); +}; + +//styles +const spinAnimation = keyframes` + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } +`; +const SpinLoader = styled.div` + display: flex; + flex: initial; + align-self: center; + width: ${(props) => props.width}; + animation-name: ${spinAnimation}; + animation-duration: 2500ms; + animation-iteration-count: infinite; + animation-timing-function: linear; +`; diff --git a/packages/uiweb/src/lib/components/space/reusables/TextInput.tsx b/packages/uiweb/src/lib/components/space/reusables/TextInput.tsx new file mode 100644 index 000000000..d87d90a2d --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/TextInput.tsx @@ -0,0 +1,71 @@ +import React, { ChangeEvent, useContext } from 'react'; +import styled from 'styled-components'; + +import { ISpacesTheme } from '../theme'; +import { ThemeContext } from '../theme/ThemeProvider'; + +export interface ITextInputProps { + charCount: number; + labelName?: string; + inputValue: string; + onInputChange: any; +} + +export const TextInputWithCounter = (props: ITextInputProps) => { + const theme = useContext(ThemeContext); + + const handleChange = (event: ChangeEvent) => { + const newText = event.target.value; + const count = newText.length; + + if (count <= props.charCount) { + props.onInputChange(event); + } + }; + + return ( + + + + {props.inputValue.length} / {props.charCount} + + + + ); +}; + +/* styling */ +const InputContainer = styled.div` + display: flex; + flex-direction: column; + + margin: 16px 0; + + font-family: 'Strawford'; // update to fontFamily theme +`; + +const LabelContainer = styled.div` + display: flex; + justify-content: space-between; + + font-weight: 500; +`; + +const Input = styled.input` + padding: 16px; + margin-top: 12px; + + width: 330px; + + background: #FFFFFF; + border: 1px solid ${(props => props.theme.btnOutline)}; + box-shadow: -1px -1px 2px ${(props => props.theme.btnOutline)}, 1px 1px 2px ${(props => props.theme.btnOutline)}; + border-radius: 12px; + + font-family: 'Strawford'; // update to fontFamily theme + font-size: 14px; +`; + +const CharCounter = styled.div` + color: ${(props => props.theme.textColorSecondary)}; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/reusables/index.ts b/packages/uiweb/src/lib/components/space/reusables/index.ts new file mode 100644 index 000000000..b9a75a085 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/index.ts @@ -0,0 +1,2 @@ +export * from './HostPfpContainer'; +export * from './ParticipantContainer'; diff --git a/packages/uiweb/src/lib/components/space/theme/ThemeProvider.tsx b/packages/uiweb/src/lib/components/space/theme/ThemeProvider.tsx new file mode 100644 index 000000000..999c6e8d1 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/theme/ThemeProvider.tsx @@ -0,0 +1,19 @@ +/** + * @file ThemeProvider.tsx: This acts as the custom theme provider for the entire app. + */ +import { createContext } from 'react'; + +import { ISpacesTheme, lightTheme } from './index'; + +/** + * @param theme optional: light or dark theme. defaults to light + * @param customTheme optional: custom colors/theme + * @param children children to be wrapped with ThemeProvider + */ +export interface IThemeProviderProps { + theme?: 'light' | 'dark'; + customTheme?: Partial; + children: any; +} + +export const ThemeContext = createContext(lightTheme); diff --git a/packages/uiweb/src/lib/components/space/theme/index.ts b/packages/uiweb/src/lib/components/space/theme/index.ts new file mode 100644 index 000000000..99c70253e --- /dev/null +++ b/packages/uiweb/src/lib/components/space/theme/index.ts @@ -0,0 +1,58 @@ +/** + * @file theme file: all the predefined themes are defined here + */ + +export interface ISpacesTheme { + titleBg?: string; + titleTextColor?: string; + bgColorPrimary?: string; + bgColorSecondary?: string; + textColorPrimary?: string; + textColorSecondary?: string; + textGradient?: string; + btnColorPrimary?: string; + btnOutline?: string; + borderColor?: string; + borderRadius?: string; + containerBorderRadius?: string; + statusColorError?: string; + statusColorSuccess?: string; + iconColorPrimary?: string; + fontFamily?: string; +} + +export const lightTheme: ISpacesTheme = { + titleBg: 'linear-gradient(87.17deg, #EA4EE4 0%, #D23CDF 0.01%, #8B5CF6 100%)', + titleTextColor: '#fff', + bgColorPrimary: '#fff', + bgColorSecondary: '#EDE9FE', + textColorPrimary: '#000', + textColorSecondary: '#71717A', + textGradient: 'linear-gradient(45deg, #B6A0F5, #F46EF6, #FFDED3, #FFCFC5)', + btnColorPrimary: '#8B5CF6', + btnOutline: '#8B5CF6', + borderColor: '#DCDCDF', + borderRadius: '17px', + containerBorderRadius: '12px', + statusColorError: '#E93636', + statusColorSuccess: '#30CC8B', + iconColorPrimary: '#82828A' +}; + +export const darkTheme: ISpacesTheme = { + titleBg: 'linear-gradient(87.17deg, #EA4EE4 0%, #D23CDF 0.01%, #8B5CF6 100%)', + titleTextColor: '#fff', + bgColorPrimary: '#000', + bgColorSecondary: '#292344', + textColorPrimary: '#fff', + textColorSecondary: '#71717A', + textGradient: 'linear-gradient(45deg, #B6A0F5, #F46EF6, #FFDED3, #FFCFC5)', + btnColorPrimary: '#8B5CF6', + btnOutline: '#8B5CF6', + borderColor: '#3F3F46', + borderRadius: '17px', + containerBorderRadius: '12px', + statusColorError: '#E93636', + statusColorSuccess: '#30CC8B', + iconColorPrimary: '#71717A' +}; diff --git a/packages/uiweb/src/lib/components/supportChat/AddressInfo.tsx b/packages/uiweb/src/lib/components/supportChat/AddressInfo.tsx index 95c02ab95..c9e6c79a4 100644 --- a/packages/uiweb/src/lib/components/supportChat/AddressInfo.tsx +++ b/packages/uiweb/src/lib/components/supportChat/AddressInfo.tsx @@ -27,7 +27,7 @@ export const AddressInfo: React.FC = () => { ` + display: ${(props) => props.display}; + position: ${(props) => props.position}; + background: ${(props) => props.background}; + color: ${(props) => props.color}; + cursor: ${(props) => props.cursor}; + flex: ${(props) => props.flex}; + flex-direction: ${(props) => props.flexDirection}; + flex-wrap: ${(props) => props.flexWrap}; + gap: ${(props) => props.gap}; + align-self: ${(props) => props.alignSelf}; + align-items: ${(props) => props.alignItems}; + align-content: ${(props) => props.alignContent}; + justify-content: ${(props) => props.justifyContent}; + padding: ${(props) => props.padding}; + margin: ${(props) => props.margin}; + margin-top: ${(props) => props.marginTop}; + margin-left: ${(props) => props.marginLeft}; + margin-right: ${(props) => props.marginRight}; + margin-bottom: ${(props) => props.marginBottom}; + min-width: ${(props) => props.minWidth}; + max-width: ${(props) => props.maxWidth}; + overflow-y: ${(props) => props.overflowY}; + font-size: ${(props) => props.fontSize}; + font-weight: ${(props) => props.fontWeight}; + text-align: ${(props) => props.textAlign}; + filter: ${(props) => props.filter}; + box-shadow: ${(props) => props.boxShadow}; + top: ${(props) => props.top}; + bottom: ${(props) => props.bottom}; + left: ${(props) => props.left}; + right: ${(props) => props.right}; + width: ${(props) => props.width}; + height: ${(props) => props.height}; + border: ${(props) => props.border}; + border-radius: ${(props) => props.borderRadius}; + overflow: ${(props) => props.overflow}; + z-index: ${(props) => props.zIndex}; +`; + +export const Item = styled.div` + ${commonStyle} +`; + +export const Anchor = styled.a` + ${commonStyle} +`; + +export const Container = styled.div` + ${commonStyle} +`; + +export const Image = styled.img` + ${commonStyle} +`; + +export const Heading = styled.h1` + ${commonStyle} +`; + +export const Button = styled.button` + ${commonStyle} +`; + +export const Text = styled.span` + ${commonStyle} +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/context/index.ts b/packages/uiweb/src/lib/context/index.ts index 4863751ad..35b23b387 100644 --- a/packages/uiweb/src/lib/context/index.ts +++ b/packages/uiweb/src/lib/context/index.ts @@ -1,3 +1,5 @@ + +import { SpaceDataContext } from "./spacesContext"; import SupportChatPropsContext from "./supportChat/supportChatPropsContext"; import SupportChatMainStateContext from "./supportChat/supportChatMainStateContext"; import ChatMainStateContextProvider, { ChatMainStateContext } from "./chatAndNotification/chat/chatMainStateContext"; @@ -7,6 +9,7 @@ import ChatAndNotificationMainContextProvider, { ChatAndNotificationMainContext export { SupportChatPropsContext, + SpaceDataContext, SupportChatMainStateContext, ChatMainStateContextProvider, ChatAndNotificationPropsContext, diff --git a/packages/uiweb/src/lib/context/spacesContext.ts b/packages/uiweb/src/lib/context/spacesContext.ts new file mode 100644 index 000000000..cac6e2f4d --- /dev/null +++ b/packages/uiweb/src/lib/context/spacesContext.ts @@ -0,0 +1,131 @@ +import React, { createContext } from 'react'; +import * as PushAPI from '@pushprotocol/restapi'; +import { SpaceDTO, SpaceIFeeds } from '@pushprotocol/restapi'; +import { SignerType } from '../types'; +import { ENV } from '../config'; + +export interface ISpaceInfo { + [key: string]: SpaceDTO; +} + +export interface ISpaceSpeakerData { + [key: string]: PushAPI.video.VideoDataType; +} + +export interface ISpacePaginationData { + apiData?: SpaceIFeeds[]; + currentPage?: number; + lastPage?: number; +} + +export interface ISpaceDataContextValues { + account: string; + setAccount: React.Dispatch>; + signer: SignerType | undefined; + setSigner: React.Dispatch>; + pgpPrivateKey: string; + setPgpPrivateKey: React.Dispatch>; + env: ENV; + setEnv: React.Dispatch>; + trendingListData: any; + setTrendingListData: React.Dispatch>; + spaceInfo: ISpaceInfo; + setSpaceInfo: (key: string, value: SpaceDTO) => void; + getSpaceInfo: (key: string) => SpaceDTO | undefined; + spaceWidgetId: string; + setSpaceWidgetId: React.Dispatch>; + mySpaces: ISpacePaginationData; + setMySpaces: (paginationData: ISpacePaginationData) => void; + popularSpaces: ISpacePaginationData; + setPopularSpaces: (paginationData: ISpacePaginationData) => void; + spaceRequests: ISpacePaginationData; + setSpaceRequests: (paginationData: ISpacePaginationData) => void; + spaceObjectData: PushAPI.SpaceData; + setSpaceObjectData: (data: any) => void; + initSpaceObject: (data: any) => Promise; + spacesObjectRef: React.MutableRefObject; + isJoined: boolean; + // isLive: boolean; + isSpeaker: boolean; + isListener: boolean; + speakerData: ISpaceSpeakerData; + setSpeakerData: (key: string, value: PushAPI.video.VideoDataType) => void; +} + +export const initialSpaceDataContextValues: ISpaceDataContextValues = { + account: '', + setAccount: () => { + /**/ + }, + signer: undefined, + setSigner: () => { + /**/ + }, + pgpPrivateKey: '', + setPgpPrivateKey: () => { + /**/ + }, + env: ENV.DEV, + setEnv: () => { + /**/ + }, + trendingListData: null, + setTrendingListData: () => { + /**/ + }, + spaceInfo: {} as ISpaceInfo, + setSpaceInfo: () => { + /**/ + }, + getSpaceInfo: () => undefined, + spaceWidgetId: '', + setSpaceWidgetId: () => { + /**/ + }, + mySpaces: { + apiData: [] as SpaceIFeeds[], + currentPage: 1, + lastPage: 2, + } as ISpacePaginationData, + setMySpaces: () => { + /**/ + }, + popularSpaces: { + apiData: [] as SpaceIFeeds[], + currentPage: 1, + lastPage: 2, + } as ISpacePaginationData, + setPopularSpaces: () => { + /**/ + }, + spaceRequests: { + apiData: [] as SpaceIFeeds[], + currentPage: 1, + lastPage: 2, + } as ISpacePaginationData, + setSpaceRequests: () => { + /**/ + }, + spaceObjectData: {} as PushAPI.SpaceData, + setSpaceObjectData: () => { + /**/ + }, + initSpaceObject: async () => { + /**/ + }, + spacesObjectRef: { + current: null, + } as React.MutableRefObject, + isJoined: false, + // isLive: false, + isSpeaker: false, + isListener: false, + speakerData: {} as ISpaceSpeakerData, + setSpeakerData: () => { + /** */ + }, +}; + +export const SpaceDataContext = createContext( + initialSpaceDataContextValues +); diff --git a/packages/uiweb/src/lib/dataProviders/SpaceDataProvider.tsx b/packages/uiweb/src/lib/dataProviders/SpaceDataProvider.tsx new file mode 100644 index 000000000..e716dbaf0 --- /dev/null +++ b/packages/uiweb/src/lib/dataProviders/SpaceDataProvider.tsx @@ -0,0 +1,300 @@ +import { useEffect, useRef, useState } from 'react'; +import { SignerType, SpaceDTO, SpaceIFeeds } from '@pushprotocol/restapi'; + +import { SpacesUI } from '../components'; +import { ThemeContext } from '../components/space/theme/ThemeProvider'; +import { ISpacesTheme, lightTheme } from '../components/space/theme'; +import { + ISpaceDataContextValues, + ISpaceInfo, + ISpacePaginationData, + ISpaceSpeakerData, + SpaceDataContext, +} from '../context/spacesContext'; +import { ENV } from '../config'; + +import * as PushAPI from '@pushprotocol/restapi'; +import { usePushSpaceSocket, useSpaceNotificationSocket } from '../hooks'; + +import { + LivepeerConfig, + Player, + createReactClient, + studioProvider, +} from '@livepeer/react'; + +export interface ISpacesUIProviderProps { + spaceUI: SpacesUI; + theme: ISpacesTheme; + children: React.ReactNode; +} + +export const SpacesUIProvider = ({ + spaceUI, + theme, + children, +}: ISpacesUIProviderProps) => { + const spacesObjectRef = useRef({} as PushAPI.space.Space); + const [account, setAccount] = useState(spaceUI.account); + const [signer, setSigner] = useState(spaceUI.signer); + const [pgpPrivateKey, setPgpPrivateKey] = useState( + spaceUI.pgpPrivateKey + ); + const [env, setEnv] = useState(spaceUI.env); + const [spaceWidgetId, setSpaceWidgetId] = useState(''); + + const [speakerData, setSpeakerData] = useState({} as ISpaceSpeakerData); + + const [trendingListData, setTrendingListData] = useState(null); + const [spaceInfo, setSpaceInfo] = useState({} as ISpaceInfo); + const [spaceObjectData, setSpaceObjectData] = useState( + PushAPI.space.initSpaceData + ); + + const [mySpaces, setMySpaces] = useState({ + apiData: [] as SpaceIFeeds[], + currentPage: 1, + lastPage: 2, + } as ISpacePaginationData); + + const [popularSpaces, setPopularSpaces] = useState({ + apiData: [] as SpaceIFeeds[], + currentPage: 1, + lastPage: 2, + } as ISpacePaginationData); + + const [spaceRequests, setSpaceRequests] = useState({ + apiData: [] as SpaceIFeeds[], + currentPage: 1, + lastPage: 2, + } as ISpacePaginationData); + + const isJoined = Boolean( + spaceObjectData?.connectionData?.meta?.broadcast?.livepeerInfo || + spaceObjectData?.spaceDescription + ); + + const livepeerClient = createReactClient({ + provider: studioProvider({ + apiKey: '2638ace1-0a3a-4853-b600-016e6125b9bc', + }), + }); + + // const isLive = isLiveSpace(); + + const setSpaceInfoItem = (key: string, value: SpaceDTO): void => { + setSpaceInfo((prevState) => ({ + ...prevState, + [key]: value, + })); + }; + + const setSpeakerDataItem = ( + key: string, + value: PushAPI.video.VideoDataType + ): void => { + setSpeakerData((prevState) => ({ + ...prevState, + [key]: value, + })); + }; + + const initSpaceObject = async (spaceId: string) => { + spacesObjectRef.current = new PushAPI.space.Space({ + signer, + pgpPrivateKey, + address: account, + chainId: 5, // TODO: Make this dynamic + env, + setSpaceData: setSpaceObjectData, + }); + await spacesObjectRef.current.initialize({ spaceId }); + }; + + const getSpaceInfo = (spaceId: string): SpaceDTO | undefined => { + return spaceInfo[spaceId]; + }; + + const setMySpacePaginationInfo = ( + paginationInfo: ISpacePaginationData + ): void => { + const { apiData, currentPage, lastPage } = paginationInfo; + setMySpaces((prevState) => { + if (apiData) { + const existingIds = new Set( + prevState.apiData?.map((space: SpaceIFeeds) => space.spaceId) + ); + console.log('Existing ID', existingIds); + const uniqueSpaces = apiData?.filter( + (space) => !existingIds.has(space.spaceId) + ); + console.log('Unique Spaces', uniqueSpaces); + return { + ...prevState, + ...(uniqueSpaces && + prevState.apiData && { + apiData: [...prevState.apiData, ...uniqueSpaces], + }), + }; + } + return { + ...prevState, + ...(currentPage && { currentPage }), + ...(lastPage && { lastPage }), + }; + }); + }; + + const setPopularSpacePaginationInfo = ( + paginationInfo: ISpacePaginationData + ): void => { + const { apiData, currentPage, lastPage } = paginationInfo; + setPopularSpaces((prevState) => { + if (apiData) { + const existingIds = new Set( + prevState.apiData?.map((space: SpaceIFeeds) => space.spaceId) + ); + console.log('Existing ID', existingIds); + const uniqueSpaces = apiData?.filter( + (space) => !existingIds.has(space.spaceId) + ); + console.log('Unique Spaces', uniqueSpaces); + return { + ...prevState, + ...(uniqueSpaces && + prevState.apiData && { + apiData: [...prevState.apiData, ...uniqueSpaces], + }), + }; + } + return { + ...prevState, + ...(currentPage && { currentPage }), + ...(lastPage && { lastPage }), + }; + }); + }; + + const setSpacesRequestPaginationInfo = ( + paginationInfo: ISpacePaginationData + ): void => { + const { apiData, currentPage, lastPage } = paginationInfo; + setSpaceRequests((prevState) => { + if (apiData) { + const existingIds = new Set( + prevState.apiData?.map((space: SpaceIFeeds) => space.spaceId) + ); + console.log('Existing ID', existingIds); + const uniqueSpaces = apiData?.filter( + (space) => !existingIds.has(space.spaceId) + ); + console.log('Unique Spaces', uniqueSpaces); + return { + ...prevState, + ...(uniqueSpaces && + prevState.apiData && { + apiData: [...prevState.apiData, ...uniqueSpaces], + }), + }; + } + return { + ...prevState, + ...(currentPage && { currentPage }), + ...(lastPage && { lastPage }), + }; + }); + }; + + const isSpeaker = Boolean( + spaceObjectData?.members?.find((member) => { + if ( + account?.toUpperCase() === + spaceObjectData.spaceCreator.replace('eip155:', '').toUpperCase() + ) + return false; + const address = member.wallet.replace('eip155:', ''); + return ( + address?.toUpperCase() === account?.toUpperCase() && member.isSpeaker + ); + }) || + spaceObjectData?.pendingMembers?.find((member) => { + const address = member.wallet.replace('eip155:', ''); + return ( + address?.toUpperCase() === account?.toUpperCase() && member.isSpeaker + ); + }) + ); + + const isListener = Boolean( + spaceObjectData?.members?.find((member) => { + console.log('member', member); + const address = member.wallet.replace('eip155:', ''); + return ( + address.toUpperCase() === account.toUpperCase() && !member.isSpeaker + ); + }) || + spaceObjectData?.pendingMembers?.find((member) => { + console.log('pending member', member); + const address = member.wallet.replace('eip155:', ''); + return ( + address.toUpperCase() === account.toUpperCase() && !member.isSpeaker + ); + }) + ); + + const value: ISpaceDataContextValues = { + account, + setAccount, + signer, + setSigner, + pgpPrivateKey, + setPgpPrivateKey, + env, + setEnv, + trendingListData, + setTrendingListData, + spaceInfo, + setSpaceInfo: setSpaceInfoItem, + getSpaceInfo, + spaceWidgetId, + setSpaceWidgetId, + mySpaces, + setMySpaces: setMySpacePaginationInfo, + popularSpaces, + setPopularSpaces: setPopularSpacePaginationInfo, + spaceRequests, + setSpaceRequests: setSpacesRequestPaginationInfo, + spaceObjectData, + setSpaceObjectData, + initSpaceObject, + spacesObjectRef, + isJoined, + isSpeaker, + isListener, + speakerData, + setSpeakerData: setSpeakerDataItem, + }; + + useEffect(() => { + setAccount(spaceUI.account); + setSigner(spaceUI.signer); + setEnv(spaceUI.env); + setPgpPrivateKey(spaceUI.pgpPrivateKey); + }, [spaceUI]); + + const PROVIDER_THEME = Object.assign({}, lightTheme, theme); + + spaceUI.init(); + useSpaceNotificationSocket({ account, env }); + usePushSpaceSocket({ account, env }); + + return ( + + + + {children} + + + + ); +}; diff --git a/packages/uiweb/src/lib/dataProviders/index.ts b/packages/uiweb/src/lib/dataProviders/index.ts new file mode 100644 index 000000000..bf7f090a8 --- /dev/null +++ b/packages/uiweb/src/lib/dataProviders/index.ts @@ -0,0 +1 @@ +export * from "./SpaceDataProvider"; \ No newline at end of file diff --git a/packages/uiweb/src/lib/helpers/apiHelper.ts b/packages/uiweb/src/lib/helpers/apiHelper.ts new file mode 100644 index 000000000..c33e9d6d5 --- /dev/null +++ b/packages/uiweb/src/lib/helpers/apiHelper.ts @@ -0,0 +1,9 @@ +export const pollAPI = async (fetchData: () => Promise, interval: number): Promise => { + try { + await fetchData(); + setTimeout(() => pollAPI(fetchData, interval), interval); + } catch (error) { + console.error('Error polling API:', error); + // Handle error if needed + } +}; diff --git a/packages/uiweb/src/lib/helpers/date.ts b/packages/uiweb/src/lib/helpers/date.ts new file mode 100644 index 000000000..c1a7357e5 --- /dev/null +++ b/packages/uiweb/src/lib/helpers/date.ts @@ -0,0 +1,6 @@ +import moment from 'moment'; + +export const formatDate = (date: number): string => { + const formattedDate = moment(date).format('Do MMM [at] h:mm A'); + return formattedDate; +} \ No newline at end of file diff --git a/packages/uiweb/src/lib/helpers/index.ts b/packages/uiweb/src/lib/helpers/index.ts index 4c07bfd93..7bfbb1ea4 100644 --- a/packages/uiweb/src/lib/helpers/index.ts +++ b/packages/uiweb/src/lib/helpers/index.ts @@ -1,3 +1,6 @@ -export * from './chat'; +export * from "./chat"; +export * from "./apiHelper"; +export * from "./date"; + export * from "./address"; export * from "./udResolver"; diff --git a/packages/uiweb/src/lib/hooks/index.ts b/packages/uiweb/src/lib/hooks/index.ts index ca85e13b1..8ebc61937 100644 --- a/packages/uiweb/src/lib/hooks/index.ts +++ b/packages/uiweb/src/lib/hooks/index.ts @@ -1,9 +1,10 @@ export * from './useClickAway'; export * from './useChatScroll'; +export * from "./space"; export * from './chat'; export * from './useSDKSocket'; export * from './useResolveWeb3Name'; export * from './notifications'; export * from './chatAndNotification'; export * from './useDivOffsetWidth'; -export * from './useDeviceWidthCheck'; \ No newline at end of file +export * from './useDeviceWidthCheck'; diff --git a/packages/uiweb/src/lib/hooks/space/index.ts b/packages/uiweb/src/lib/hooks/space/index.ts new file mode 100644 index 000000000..b1083d6a5 --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/index.ts @@ -0,0 +1,8 @@ +export * from './useSpaceData'; +export * from './useGetSpaceInfo'; +export * from './usePopularSpaces'; +export * from './useMySpaces'; +export * from './useSpaceRequests'; +export * from './useFeedScroll'; +export * from './useSpaceNotificationSocket'; +export * from './usePushSpaceSocket'; diff --git a/packages/uiweb/src/lib/hooks/space/useFeedScroll.ts b/packages/uiweb/src/lib/hooks/space/useFeedScroll.ts new file mode 100644 index 000000000..b589f37c5 --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/useFeedScroll.ts @@ -0,0 +1,13 @@ +import React from 'react'; + +export const useFeedScroll = ( + dep: T, +): React.MutableRefObject => { + const ref = React.useRef(null); + React.useEffect(() => { + if (ref.current) { + ref.current.scrollTop = 0; + } + }, []); + return ref; +}; \ No newline at end of file diff --git a/packages/uiweb/src/lib/hooks/space/useGetSpaceInfo.ts b/packages/uiweb/src/lib/hooks/space/useGetSpaceInfo.ts new file mode 100644 index 000000000..1e50445c6 --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/useGetSpaceInfo.ts @@ -0,0 +1,37 @@ +import { useContext, useEffect, useState } from 'react'; +import * as PushAPI from '@pushprotocol/restapi'; +import { + ISpaceDataContextValues, + SpaceDataContext, +} from '../../context/spacesContext'; +import { SpaceDTO } from '@pushprotocol/restapi'; +import { ENV } from '../../config'; + +export const useGetSpaceInfo = (spaceId: string): SpaceDTO | undefined => { + const { getSpaceInfo, setSpaceInfo, env }: ISpaceDataContextValues = + useContext(SpaceDataContext); + const [spaceData, setSpaceDataState] = useState( + getSpaceInfo(spaceId) + ); + + useEffect(() => { + if (!spaceId) { + return; + } + const fetchData = async () => { + if (!spaceData) { + try { + const response = await PushAPI.space.get({ spaceId, env }); + setSpaceInfo(spaceId, response); + setSpaceDataState(response); + } catch (error) { + console.error(error); + } + } + }; + + fetchData(); + }, [spaceId, spaceData, getSpaceInfo, setSpaceInfo]); + + return spaceData; +}; diff --git a/packages/uiweb/src/lib/hooks/space/useMySpaces.ts b/packages/uiweb/src/lib/hooks/space/useMySpaces.ts new file mode 100644 index 000000000..d78de24ff --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/useMySpaces.ts @@ -0,0 +1,44 @@ +import { useSpaceData } from './useSpaceData'; +import { useEffect, useState } from 'react'; + +import * as PushAPI from '@pushprotocol/restapi'; + +export const useMySpaces = (account?: string) => { + const LIMIT = 10; + + const { mySpaces, setMySpaces, env } = useSpaceData(); + const [loading, setLoading] = useState(false); + + const fetchMySpaces = async () => { + if (!account) return; + setLoading(true); + try { + const res = await PushAPI.space.spaces({ + account: account, + page: mySpaces.currentPage, + limit: LIMIT, + env, + }); + + const newMySpaces = res; + + if (newMySpaces.length === 0) { + setMySpaces({ lastPage: -1 }); + setLoading(false); + return; + } + if (newMySpaces.length > 0) { + setMySpaces({ apiData: newMySpaces }); + } + } catch (error) { + console.error('Error while fetching Spaces For You:', error); + } + setLoading(false); + }; + + useEffect(() => { + fetchMySpaces(); + }, [mySpaces.currentPage]); + + return { loading }; +}; diff --git a/packages/uiweb/src/lib/hooks/space/usePopularSpaces.ts b/packages/uiweb/src/lib/hooks/space/usePopularSpaces.ts new file mode 100644 index 000000000..2f6fcb7b1 --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/usePopularSpaces.ts @@ -0,0 +1,41 @@ +import { useSpaceData } from './useSpaceData'; +import { useEffect, useState } from 'react'; + +import * as PushAPI from '@pushprotocol/restapi'; + +export const usePopularSpaces = () => { + const LIMIT = 10; + const { popularSpaces, setPopularSpaces, env } = useSpaceData(); + const [loading, setLoading] = useState(false); + + const fetchPopularSpaces = async () => { + setLoading(true); + try { + const res = await PushAPI.space.trending({ + page: popularSpaces.currentPage, + limit: LIMIT, + env + }); + + const newPopularSpaces = res; + + if (newPopularSpaces.length === 0) { + setPopularSpaces({ lastPage: -1 }); + setLoading(false); + return; + } + if (newPopularSpaces.length > 0) { + setPopularSpaces({ apiData: newPopularSpaces }); + } + } catch (error) { + console.error('Error while fetching popular spaces:', error); + } + setLoading(false); + }; + + useEffect(() => { + fetchPopularSpaces(); + }, [popularSpaces.currentPage]); + + return { loading }; +}; diff --git a/packages/uiweb/src/lib/hooks/space/usePushSpaceSocket.tsx b/packages/uiweb/src/lib/hooks/space/usePushSpaceSocket.tsx new file mode 100644 index 000000000..8346b7b3e --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/usePushSpaceSocket.tsx @@ -0,0 +1,112 @@ +import { createSocketConnection, EVENTS } from '@pushprotocol/socket'; +import { useCallback, useEffect, useState } from 'react'; +import { ENV } from '../../config'; +import { useSpaceData } from './useSpaceData'; +import * as PushAPI from "@pushprotocol/restapi"; +import { SpaceDTO, SpaceIFeeds } from '@pushprotocol/restapi'; + +const SPACE_SOCKET_TYPE = 'chat'; + +export type PushSDKSocketHookOptions = { + account?: string | null; + env?: ENV; +}; + +export const usePushSpaceSocket = ({ + account, + env = ENV.PROD, +}: PushSDKSocketHookOptions) => { + const { spaceRequests, setSpaceRequests } = useSpaceData(); + const [pushSpaceSocket, setPushSpaceSocket] = useState(null); + const [isPushSDKSocketConnected, setIsPushSDKSocketConnected] = + useState(false); + + const addSocketEvents = useCallback(() => { + pushSpaceSocket?.on(EVENTS.CONNECT, () => { + setIsPushSDKSocketConnected(true); + }); + + pushSpaceSocket?.on(EVENTS.DISCONNECT, () => { + setIsPushSDKSocketConnected(false); + }); + + pushSpaceSocket?.on( + EVENTS.CHAT_RECEIVED_MESSAGE, + async () => { + /** */ + } + ); + + pushSpaceSocket?.on('SPACES', (spaceInfo: SpaceDTO) => { + console.log(spaceInfo); + + const updatedData = spaceRequests?.apiData?.map(item => { + if (item.spaceId === spaceInfo.spaceId) { + return { + ...item, + spaceInformation: spaceInfo + }; + } + return item; + }); + + setSpaceRequests({ + apiData: updatedData as PushAPI.SpaceIFeeds[] + }) + }); + }, [ + pushSpaceSocket + ]); + + const removeSocketEvents = useCallback(() => { + pushSpaceSocket?.off(EVENTS.CONNECT); + pushSpaceSocket?.off(EVENTS.DISCONNECT); + pushSpaceSocket?.off(EVENTS.CHAT_GROUPS); + pushSpaceSocket?.off(EVENTS.CHAT_RECEIVED_MESSAGE); + }, [pushSpaceSocket]); + + useEffect(() => { + if (pushSpaceSocket) { + addSocketEvents(); + } + + return () => { + if (pushSpaceSocket) { + removeSocketEvents(); + } + }; + }, [addSocketEvents, pushSpaceSocket, removeSocketEvents]); + + /** + * Whenever the required params to create a connection object change + * - disconnect the old connection + * - create a new connection object + */ + useEffect(() => { + if (account) { + if (pushSpaceSocket) { + // console.log('=================>>> disconnection in the hook'); + pushSpaceSocket?.disconnect(); + } + const main = async () => { + const connectionObject = createSocketConnection({ + user: account, + env, + socketType: SPACE_SOCKET_TYPE, + socketOptions: { autoConnect: true, reconnectionAttempts: 3 }, + }); + console.warn('new connection object: ', connectionObject); + + setPushSpaceSocket(connectionObject); + }; + main().catch((err) => console.error(err)); + } + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [account, env]); + + return { + pushSpaceSocket, + isPushSDKSocketConnected, + }; +}; diff --git a/packages/uiweb/src/lib/hooks/space/useSpaceData.ts b/packages/uiweb/src/lib/hooks/space/useSpaceData.ts new file mode 100644 index 000000000..e1e00a93e --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/useSpaceData.ts @@ -0,0 +1,11 @@ +import { useContext } from "react"; +import { ISpaceDataContextValues } from "../../context/spacesContext"; +import { SpaceDataContext } from "../../context"; + +export const useSpaceData = (): ISpaceDataContextValues => { + const context = useContext(SpaceDataContext); + if (!context) { + throw new Error('useSpaceData must be used within a SpaceDataProvider'); + } + return context; +} \ No newline at end of file diff --git a/packages/uiweb/src/lib/hooks/space/useSpaceNotificationSocket.ts b/packages/uiweb/src/lib/hooks/space/useSpaceNotificationSocket.ts new file mode 100644 index 000000000..a8daa4ac6 --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/useSpaceNotificationSocket.ts @@ -0,0 +1,150 @@ +import { useCallback, useEffect, useState } from 'react'; +import { createSocketConnection, EVENTS } from '@pushprotocol/socket'; +import * as PushAPI from '@pushprotocol/restapi'; +import { useSpaceData } from './useSpaceData'; +import { ENV } from '../../config'; + +const NOTIFICATION_SOCKET_TYPE = 'notification'; + +export type SDKSpaceNotificationSocketHookOptions = { + account?: string | null; + env?: ENV; +}; + +export const useSpaceNotificationSocket = ({ + account, + env = ENV.PROD, +}: SDKSpaceNotificationSocketHookOptions) => { + const { spacesObjectRef } = useSpaceData(); + + const [notificationSocket, setNotificationSocket] = useState(null); + const [isNotificationSocketConnected, setIsNotificationSocketConnected] = + useState(false); + + const addSocketEvents = useCallback(() => { + notificationSocket?.on(EVENTS.CONNECT, () => { + setIsNotificationSocketConnected(true); + }); + + notificationSocket?.on(EVENTS.DISCONNECT, () => { + setIsNotificationSocketConnected(false); + }); + + notificationSocket?.on(EVENTS.USER_FEEDS, (feedItem: any) => { + const { payload } = feedItem; + + console.log('RECEIVED USER FEEDS NOTIF', payload); + + if ( + payload?.data?.additionalMeta?.type === + `${PushAPI.payloads.ADDITIONAL_META_TYPE.PUSH_VIDEO}+1` + ) { + const { + status, + callDetails, + senderAddress, + recipientAddress, + signalData, + chatId, + }: PushAPI.video.VideoDataType = JSON.parse( + payload.data.additionalMeta.data + ); + + if (status === PushAPI.VideoCallStatus.INITIALIZED) { + if ( + callDetails?.type === + PushAPI.payloads.SPACE_REQUEST_TYPE.JOIN_SPEAKER + ) { + // TODO: see if check for speaker is req + spacesObjectRef.current?.acceptRequest({ + senderAddress: recipientAddress, + recipientAddress: senderAddress, + signalData, + chatId, + }); + } + if ( + callDetails?.type === + PushAPI.payloads.SPACE_REQUEST_TYPE.ESTABLISH_MESH + ) { + spacesObjectRef.current?.acceptRequest({ + signalData, + senderAddress: recipientAddress, + recipientAddress: senderAddress, + chatId: chatId, + }); + } + } + if (status === PushAPI.VideoCallStatus.RECEIVED) { + spacesObjectRef.current?.connect({ + signalData, + peerAddress: senderAddress, + }); + } + if (status === PushAPI.VideoCallStatus.DISCONNECTED) { + if ( + callDetails?.type === PushAPI.payloads.SPACE_DISCONNECT_TYPE.LEAVE + ) { + // later -> the 'senderAddress' has left the space + } + if ( + callDetails?.type === PushAPI.payloads.SPACE_DISCONNECT_TYPE.STOP + ) { + // later -> space has been ended by the host + } + } + } + }); + }, [notificationSocket]); + + const removeSocketEvents = useCallback(() => { + notificationSocket?.off(EVENTS.CONNECT); + notificationSocket?.off(EVENTS.DISCONNECT); + notificationSocket?.off(EVENTS.USER_FEEDS); + }, [notificationSocket]); + + useEffect(() => { + if (notificationSocket) { + addSocketEvents(); + } + + return () => { + if (notificationSocket) { + removeSocketEvents(); + } + }; + }, [addSocketEvents, notificationSocket, removeSocketEvents]); + + /** + * Whenever the requisite params to create a connection object change + * - disconnect the old connection + * - create a new connection object + */ + useEffect(() => { + if (account) { + if (notificationSocket) { + // console.log('=================>>> disconnection in the hook'); + notificationSocket?.disconnect(); + } + const main = async () => { + const connectionObject = createSocketConnection({ + user: account, + env, + socketType: NOTIFICATION_SOCKET_TYPE, + socketOptions: { autoConnect: true, reconnectionAttempts: 3 }, + }); + console.warn('new connection object: ', connectionObject); + + setNotificationSocket(connectionObject); + }; + main().catch((err) => console.error(err)); + } + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [account, env]); + + return { + notificationSocket, + isNotificationSocketConnected, + }; +}; diff --git a/packages/uiweb/src/lib/hooks/space/useSpaceRequests.ts b/packages/uiweb/src/lib/hooks/space/useSpaceRequests.ts new file mode 100644 index 000000000..b9c67c0a7 --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/useSpaceRequests.ts @@ -0,0 +1,45 @@ +import { useSpaceData } from './useSpaceData'; +import { useEffect, useState } from 'react'; + +import * as PushAPI from '@pushprotocol/restapi'; + +export const useSpaceRequests = (account?: string) => { + const LIMIT = 2; + + const { spaceRequests, setSpaceRequests, env } = useSpaceData(); + const [loading, setLoading] = useState(false); + + const fetchSpaceRequests = async () => { + if (!account) return; + setLoading(true); + try { + const res = await PushAPI.space.requests({ + account: account, + page: spaceRequests.currentPage, + limit: LIMIT, + env, + + }); + + const newSpaceRequests = res; + + if (newSpaceRequests.length === 0) { + setSpaceRequests({ lastPage: -1 }); + setLoading(false); + return; + } + if (newSpaceRequests.length > 0) { + setSpaceRequests({ apiData: newSpaceRequests }); + } + } catch (error) { + console.error('Error while fetching spaces requests:', error); + } + setLoading(false); + }; + + useEffect(() => { + fetchSpaceRequests(); + }, [spaceRequests.currentPage]); + + return { loading }; +}; diff --git a/packages/uiweb/src/lib/hooks/useChatScroll.ts b/packages/uiweb/src/lib/hooks/useChatScroll.ts index d7f7a90ad..f02209c2c 100644 --- a/packages/uiweb/src/lib/hooks/useChatScroll.ts +++ b/packages/uiweb/src/lib/hooks/useChatScroll.ts @@ -6,7 +6,7 @@ export const useChatScroll = ( const ref = React.useRef(null); React.useEffect(() => { if (ref.current) { - ref.current.scrollTop = ref.current.scrollHeight; + ref.current.scrollTop = 0; } }, [dep]); return ref; diff --git a/packages/uiweb/src/lib/icons/ArrowLeft.svg b/packages/uiweb/src/lib/icons/ArrowLeft.svg new file mode 100644 index 000000000..de2987515 --- /dev/null +++ b/packages/uiweb/src/lib/icons/ArrowLeft.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/uiweb/src/lib/icons/ArrowLeft.tsx b/packages/uiweb/src/lib/icons/ArrowLeft.tsx new file mode 100644 index 000000000..54b4153aa --- /dev/null +++ b/packages/uiweb/src/lib/icons/ArrowLeft.tsx @@ -0,0 +1,9 @@ +export const ArrowLeft = () => { + return ( + + + + + ); + }; + \ No newline at end of file diff --git a/packages/uiweb/src/lib/icons/CalendarPurple.tsx b/packages/uiweb/src/lib/icons/CalendarPurple.tsx new file mode 100644 index 000000000..a3e4f8524 --- /dev/null +++ b/packages/uiweb/src/lib/icons/CalendarPurple.tsx @@ -0,0 +1,28 @@ +import React from 'react'; + +export const CalendarPurple = ({ height, width }: { height?: string, width?: string }) => { + return ( + < svg + width={width || "15"} + height={height || "14"} + viewBox = "0 0 15 14" + fill = "none" + xmlns = "http://www.w3.org/2000/svg" + > + + + + ); +}; diff --git a/packages/uiweb/src/lib/icons/CaretDown.svg b/packages/uiweb/src/lib/icons/CaretDown.svg new file mode 100644 index 000000000..6b3c3561b --- /dev/null +++ b/packages/uiweb/src/lib/icons/CaretDown.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/CaretDownGrey.svg b/packages/uiweb/src/lib/icons/CaretDownGrey.svg new file mode 100644 index 000000000..a450775da --- /dev/null +++ b/packages/uiweb/src/lib/icons/CaretDownGrey.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/CaretUp.svg b/packages/uiweb/src/lib/icons/CaretUp.svg new file mode 100644 index 000000000..852d9acae --- /dev/null +++ b/packages/uiweb/src/lib/icons/CaretUp.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/CaretUpGrey.svg b/packages/uiweb/src/lib/icons/CaretUpGrey.svg new file mode 100644 index 000000000..43b353b05 --- /dev/null +++ b/packages/uiweb/src/lib/icons/CaretUpGrey.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/CloseSvg.tsx b/packages/uiweb/src/lib/icons/CloseSvg.tsx index 2bf81b330..cf42abfe7 100644 --- a/packages/uiweb/src/lib/icons/CloseSvg.tsx +++ b/packages/uiweb/src/lib/icons/CloseSvg.tsx @@ -1,25 +1,25 @@ import React from 'react'; -export const CloseSvg = () => { +export const CloseSvg = ({ stroke, height, width }: { stroke?: string, height?: string, width?: string }) => { return ( + + + + + diff --git a/packages/uiweb/src/lib/icons/MicEngage.svg b/packages/uiweb/src/lib/icons/MicEngage.svg new file mode 100644 index 000000000..2118ce9d3 --- /dev/null +++ b/packages/uiweb/src/lib/icons/MicEngage.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/Minimize.tsx b/packages/uiweb/src/lib/icons/Minimize.tsx index e7a001f1d..c8a15dd52 100644 --- a/packages/uiweb/src/lib/icons/Minimize.tsx +++ b/packages/uiweb/src/lib/icons/Minimize.tsx @@ -8,4 +8,4 @@ export const MinimizeIcon = () => { ); -}; \ No newline at end of file +}; diff --git a/packages/uiweb/src/lib/icons/Muted.svg b/packages/uiweb/src/lib/icons/Muted.svg new file mode 100644 index 000000000..a68158636 --- /dev/null +++ b/packages/uiweb/src/lib/icons/Muted.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/Share.svg b/packages/uiweb/src/lib/icons/Share.svg new file mode 100644 index 000000000..dd69beae1 --- /dev/null +++ b/packages/uiweb/src/lib/icons/Share.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/packages/uiweb/src/lib/icons/Spaces.svg b/packages/uiweb/src/lib/icons/Spaces.svg new file mode 100644 index 000000000..529ef17e0 --- /dev/null +++ b/packages/uiweb/src/lib/icons/Spaces.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/packages/uiweb/src/lib/icons/atVector.svg b/packages/uiweb/src/lib/icons/atVector.svg new file mode 100644 index 000000000..b4aa5c9bf --- /dev/null +++ b/packages/uiweb/src/lib/icons/atVector.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/uiweb/src/lib/icons/calendar.svg b/packages/uiweb/src/lib/icons/calendar.svg new file mode 100644 index 000000000..769c7e11c --- /dev/null +++ b/packages/uiweb/src/lib/icons/calendar.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/uiweb/src/lib/icons/calendarPurple.svg b/packages/uiweb/src/lib/icons/calendarPurple.svg new file mode 100644 index 000000000..fde94df20 --- /dev/null +++ b/packages/uiweb/src/lib/icons/calendarPurple.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/uiweb/src/lib/icons/checkIcon.svg b/packages/uiweb/src/lib/icons/checkIcon.svg new file mode 100644 index 000000000..f8d7fc7cb --- /dev/null +++ b/packages/uiweb/src/lib/icons/checkIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/copyVector.svg b/packages/uiweb/src/lib/icons/copyVector.svg new file mode 100644 index 000000000..6f780bb22 --- /dev/null +++ b/packages/uiweb/src/lib/icons/copyVector.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/uiweb/src/lib/icons/filter.svg b/packages/uiweb/src/lib/icons/filter.svg new file mode 100644 index 000000000..2ac3e870f --- /dev/null +++ b/packages/uiweb/src/lib/icons/filter.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/hand.svg b/packages/uiweb/src/lib/icons/hand.svg new file mode 100644 index 000000000..422d49f54 --- /dev/null +++ b/packages/uiweb/src/lib/icons/hand.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packages/uiweb/src/lib/icons/live.svg b/packages/uiweb/src/lib/icons/live.svg new file mode 100644 index 000000000..5cf6ae8c8 --- /dev/null +++ b/packages/uiweb/src/lib/icons/live.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/packages/uiweb/src/lib/icons/micoff.svg b/packages/uiweb/src/lib/icons/micoff.svg new file mode 100644 index 000000000..ad6e4f143 --- /dev/null +++ b/packages/uiweb/src/lib/icons/micoff.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/micon.svg b/packages/uiweb/src/lib/icons/micon.svg new file mode 100644 index 000000000..80cd7a2a1 --- /dev/null +++ b/packages/uiweb/src/lib/icons/micon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/uiweb/src/lib/icons/scheduled.svg b/packages/uiweb/src/lib/icons/scheduled.svg new file mode 100644 index 000000000..63b3495d0 --- /dev/null +++ b/packages/uiweb/src/lib/icons/scheduled.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/uiweb/src/lib/icons/settings.svg b/packages/uiweb/src/lib/icons/settings.svg new file mode 100644 index 000000000..9510b8a01 --- /dev/null +++ b/packages/uiweb/src/lib/icons/settings.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/uiweb/src/lib/icons/settingsBlack.svg b/packages/uiweb/src/lib/icons/settingsBlack.svg new file mode 100644 index 000000000..0ffa8bc28 --- /dev/null +++ b/packages/uiweb/src/lib/icons/settingsBlack.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/uiweb/src/lib/icons/twitterVector.svg b/packages/uiweb/src/lib/icons/twitterVector.svg new file mode 100644 index 000000000..4be66ead6 --- /dev/null +++ b/packages/uiweb/src/lib/icons/twitterVector.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/index.ts b/packages/uiweb/src/lib/index.ts index 6671d57e2..b81e6f07f 100644 --- a/packages/uiweb/src/lib/index.ts +++ b/packages/uiweb/src/lib/index.ts @@ -1,3 +1,4 @@ export * from './components' export * from './config'; +export * from './dataProviders'; export * from './types'; diff --git a/packages/uiweb/yarn.lock b/packages/uiweb/yarn.lock index 507d89db1..0e9621d0f 100644 --- a/packages/uiweb/yarn.lock +++ b/packages/uiweb/yarn.lock @@ -33,6 +33,13 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.4.tgz#a770e98fd785c231af9d93f6459d36770993fb32" integrity sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA== +"@babel/runtime@^7.13.10": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" + integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== + dependencies: + regenerator-runtime "^0.13.11" + "@babel/types@^7.0.0", "@babel/types@^7.20.7": version "7.22.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.4.tgz#56a2653ae7e7591365dabf20b76295410684c071" @@ -224,11 +231,68 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" +"@floating-ui/core@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.3.1.tgz#4d795b649cc3b1cbb760d191c80dcb4353c9a366" + integrity sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g== + +"@floating-ui/dom@^1.3.0": + version "1.4.4" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.4.4.tgz#cf859dde33995a4e7b6ded16c98cb73b2ebfffd0" + integrity sha512-21hhDEPOiWkGp0Ys4Wi6Neriah7HweToKra626CIK712B5m9qkdz54OP9gVldUg+URnBTpv/j/bi/skmGdstXQ== + dependencies: + "@floating-ui/core" "^1.3.1" + +"@floating-ui/react-dom@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.1.tgz#7972a4fc488a8c746cded3cfe603b6057c308a91" + integrity sha512-rZtAmSht4Lry6gdhAJDrCp/6rKN7++JnL1/Anbr/DdeyYXQPxvg/ivrbYvJulbRf4vL8b212suwMM2lxbv+RQA== + dependencies: + "@floating-ui/dom" "^1.3.0" + "@juggle/resize-observer@^3.3.1": version "3.4.0" resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA== +"@livepeer/core-react@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@livepeer/core-react/-/core-react-1.6.0.tgz#2a29789bd8acb551d81496cdc85376f165652971" + integrity sha512-6lsrWJ/iJSF9bL3y8O+gkvRJ17tT6g9z3l1/E7pf30tIlELjwFb4KklK/k3SFtuYYskkx8v5DvU2LaOd2yhQYA== + dependencies: + "@livepeer/core" "^1.6.0" + "@tanstack/query-async-storage-persister" "4.22.4" + "@tanstack/query-core" "4.22.4" + "@tanstack/react-query" "4.22.4" + "@tanstack/react-query-persist-client" "4.22.4" + use-sync-external-store "^1.2.0" + zustand "^4.3.2" + +"@livepeer/core@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@livepeer/core/-/core-1.6.0.tgz#1be05fc92b21f0cdebf28dd7243de6d8d0b8753c" + integrity sha512-MhyrtsXFrndnWn16GViavVG9UNjGroavw1FttgfstQ1IPWxrP2HEEvX52zATXF0JX/xfH5MCsfLNcVC9MF399g== + dependencies: + cross-fetch "^3.1.5" + ms "^3.0.0-canary.1" + multiformats "9.9.0" + tus-js-client "^3.0.1" + zustand "^4.3.2" + +"@livepeer/react@^2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@livepeer/react/-/react-2.6.0.tgz#6ddff6d1c9e8f4dccff76c95ece238bc77642e5b" + integrity sha512-CH5hpONn4eiL6Qqf3neVzduvMbEkYa9DP1wliEGTpq/rAb8kfdrKGVOeEKkx7GoIIdHNPf0GIwFIggiqu/l8yw== + dependencies: + "@livepeer/core-react" "^1.6.0" + "@radix-ui/react-dialog" "^1.0.4" + "@radix-ui/react-popover" "^1.0.6" + "@radix-ui/react-select" "^1.2.2" + "@stitches/react" "^1.2.8" + core-js "^3.27.2" + livepeer "2.6.0" + zustand "^4.3.2" + "@pushprotocol/socket@^0.5.0": version "0.5.0" resolved "https://registry.yarnpkg.com/@pushprotocol/socket/-/socket-0.5.0.tgz#ef5dfef1891dec9436e23b02d80e496e53ea4fe6" @@ -237,11 +301,301 @@ socket.io-client "^4.5.2" tslib "^2.3.0" +"@radix-ui/number@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.0.1.tgz#644161a3557f46ed38a042acf4a770e826021674" + integrity sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/primitive@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.1.tgz#e46f9958b35d10e9f6dc71c497305c22e3e55dbd" + integrity sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-arrow@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz#c24f7968996ed934d57fe6cde5d6ec7266e1d25d" + integrity sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.3" + +"@radix-ui/react-collection@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.3.tgz#9595a66e09026187524a36c6e7e9c7d286469159" + integrity sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + +"@radix-ui/react-compose-refs@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989" + integrity sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-context@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.1.tgz#fe46e67c96b240de59187dcb7a1a50ce3e2ec00c" + integrity sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-dialog@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.4.tgz#06bce6c16bb93eb36d7a8589e665a20f4c1c52c1" + integrity sha512-hJtRy/jPULGQZceSAP2Re6/4NpKo8im6V8P2hUqZsdFiSL8l35kYsw3qbRI6Ay5mQd2+wlLqje770eq+RJ3yZg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-dismissable-layer" "1.0.4" + "@radix-ui/react-focus-guards" "1.0.1" + "@radix-ui/react-focus-scope" "1.0.3" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-portal" "1.0.3" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + "@radix-ui/react-use-controllable-state" "1.0.1" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.5" + +"@radix-ui/react-direction@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.1.tgz#9cb61bf2ccf568f3421422d182637b7f47596c9b" + integrity sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-dismissable-layer@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz#883a48f5f938fa679427aa17fcba70c5494c6978" + integrity sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-escape-keydown" "1.0.3" + +"@radix-ui/react-focus-guards@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz#1ea7e32092216b946397866199d892f71f7f98ad" + integrity sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-focus-scope@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.3.tgz#9c2e8d4ed1189a1d419ee61edd5c1828726472f9" + integrity sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + +"@radix-ui/react-id@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.1.tgz#73cdc181f650e4df24f0b6a5b7aa426b912c88c0" + integrity sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-layout-effect" "1.0.1" + +"@radix-ui/react-popover@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.6.tgz#19bb81e7450482c625b8cd05bf4dcd1d2cd91a8b" + integrity sha512-cZ4defGpkZ0qTRtlIBzJLSzL6ht7ofhhW4i1+pkemjV1IKXm0wgCRnee154qlV6r9Ttunmh2TNZhMfV2bavUyA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-dismissable-layer" "1.0.4" + "@radix-ui/react-focus-guards" "1.0.1" + "@radix-ui/react-focus-scope" "1.0.3" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-popper" "1.1.2" + "@radix-ui/react-portal" "1.0.3" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + "@radix-ui/react-use-controllable-state" "1.0.1" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.5" + +"@radix-ui/react-popper@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.2.tgz#4c0b96fcd188dc1f334e02dba2d538973ad842e9" + integrity sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg== + dependencies: + "@babel/runtime" "^7.13.10" + "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.0.3" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" + "@radix-ui/react-use-rect" "1.0.1" + "@radix-ui/react-use-size" "1.0.1" + "@radix-ui/rect" "1.0.1" + +"@radix-ui/react-portal@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.3.tgz#ffb961244c8ed1b46f039e6c215a6c4d9989bda1" + integrity sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.3" + +"@radix-ui/react-presence@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.1.tgz#491990ba913b8e2a5db1b06b203cb24b5cdef9ba" + integrity sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" + +"@radix-ui/react-primitive@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0" + integrity sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-slot" "1.0.2" + +"@radix-ui/react-select@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-select/-/react-select-1.2.2.tgz#caa981fa0d672cf3c1b2a5240135524e69b32181" + integrity sha512-zI7McXr8fNaSrUY9mZe4x/HC0jTLY9fWNhO1oLWYMQGDXuV4UCivIGTxwioSzO0ZCYX9iSLyWmAh/1TOmX3Cnw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/number" "1.0.1" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-collection" "1.0.3" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-direction" "1.0.1" + "@radix-ui/react-dismissable-layer" "1.0.4" + "@radix-ui/react-focus-guards" "1.0.1" + "@radix-ui/react-focus-scope" "1.0.3" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-popper" "1.1.2" + "@radix-ui/react-portal" "1.0.3" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-controllable-state" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" + "@radix-ui/react-use-previous" "1.0.1" + "@radix-ui/react-visually-hidden" "1.0.3" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.5" + +"@radix-ui/react-slot@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" + integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + +"@radix-ui/react-use-callback-ref@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz#f4bb1f27f2023c984e6534317ebc411fc181107a" + integrity sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-controllable-state@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz#ecd2ced34e6330caf89a82854aa2f77e07440286" + integrity sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "1.0.1" + +"@radix-ui/react-use-escape-keydown@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz#217b840c250541609c66f67ed7bab2b733620755" + integrity sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "1.0.1" + +"@radix-ui/react-use-layout-effect@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz#be8c7bc809b0c8934acf6657b577daf948a75399" + integrity sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-previous@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-1.0.1.tgz#b595c087b07317a4f143696c6a01de43b0d0ec66" + integrity sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-rect@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz#fde50b3bb9fd08f4a1cd204572e5943c244fcec2" + integrity sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/rect" "1.0.1" + +"@radix-ui/react-use-size@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz#1c5f5fea940a7d7ade77694bb98116fb49f870b2" + integrity sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-layout-effect" "1.0.1" + +"@radix-ui/react-visually-hidden@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz#51aed9dd0fe5abcad7dee2a234ad36106a6984ac" + integrity sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.3" + +"@radix-ui/rect@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.1.tgz#bf8e7d947671996da2e30f4904ece343bc4a883f" + integrity sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@socket.io/component-emitter@~3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== +"@stitches/core@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@stitches/core/-/core-1.2.8.tgz#dce3b8fdc764fbc6dbea30c83b73bfb52cf96173" + integrity sha512-Gfkvwk9o9kE9r9XNBmJRfV8zONvXThnm1tcuojL04Uy5uRyqg93DC83lDebl0rocZCfKSjUv+fWYtMQmEDJldg== + +"@stitches/react@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@stitches/react/-/react-1.2.8.tgz#954f8008be8d9c65c4e58efa0937f32388ce3a38" + integrity sha512-9g9dWI4gsSVe8bNLlb+lMkBYsnIKCZTmvqvDG+Avnn69XfmHZKiaMrx7cgTaddq7aTPPmXiTsbFcUy0xgI4+wA== + "@storybook/addon-styling@^1.0.8": version "1.0.8" resolved "https://registry.yarnpkg.com/@storybook/addon-styling/-/addon-styling-1.0.8.tgz#3533c4c5322b286575c235adcec246e39dcdf913" @@ -406,6 +760,38 @@ "@types/express" "^4.7.0" file-system-cache "^2.0.0" +"@tanstack/query-async-storage-persister@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@tanstack/query-async-storage-persister/-/query-async-storage-persister-4.22.4.tgz#60f846dbb2b0bad6911b29ff77ba6272e610283c" + integrity sha512-8DWEt+bmxyjp12aqGnYhpgroOZgvgzvs+mMqBIyZVET4eWQNKAuQSFXTlkztmq9/sxbvTnp+xu7KRZExyurZPA== + dependencies: + "@tanstack/query-persist-client-core" "4.22.4" + +"@tanstack/query-core@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.22.4.tgz#aca622d2f8800a147ece5520d956a076ab92f0ea" + integrity sha512-t79CMwlbBnj+yL82tEcmRN93bL4U3pae2ota4t5NN2z3cIeWw74pzdWrKRwOfTvLcd+b30tC+ciDlfYOKFPGUw== + +"@tanstack/query-persist-client-core@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@tanstack/query-persist-client-core/-/query-persist-client-core-4.22.4.tgz#a8ed136a8234b9cbd12ae3df857425330c6200db" + integrity sha512-F5rCLczSw8RjFlwWASD3oRR7D4oyG90QbBFaOqBCjGbvE3bcD+m/E4GGCp1qfACoLuH4KtxhdwdOFfE+e0TRZQ== + +"@tanstack/react-query-persist-client@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@tanstack/react-query-persist-client/-/react-query-persist-client-4.22.4.tgz#8e4fad6f70ca922ef9e7be58c5bd14b010cff780" + integrity sha512-vnRD28T0BLsbDRlantC6W34eLCbjSoZEkYL4t2QYRyuEcmUya2Ddbn+DN+RfZHqxoMiSJNfMdmRXsMPpNHZ1QA== + dependencies: + "@tanstack/query-persist-client-core" "4.22.4" + +"@tanstack/react-query@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.22.4.tgz#851581c645f1c9cfcd394448fedd980a39bbc3fe" + integrity sha512-e5j5Z88XUQGeEPMyz5XF1V0mMf6Da+6URXiTpZfUb9nuHs2nlNoA+EoIvnhccE5b9YT6Yg7kARhn2L7u94M/4A== + dependencies: + "@tanstack/query-core" "4.22.4" + use-sync-external-store "^1.2.0" + "@types/babel__core@^7.0.0": version "7.20.1" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.1.tgz#916ecea274b0c776fec721e333e55762d3a9614b" @@ -576,6 +962,13 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-hidden@^1.1.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.3.tgz#14aeb7fb692bbb72d69bebfa47279c1fd725e954" + integrity sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ== + dependencies: + tslib "^2.0.0" + async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" @@ -608,6 +1001,11 @@ brorand@^1.1.0: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== +buffer-from@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + call-bind@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -672,6 +1070,14 @@ color-support@^1.1.2: resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== +combine-errors@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/combine-errors/-/combine-errors-3.0.3.tgz#f4df6740083e5703a3181110c2b10551f003da86" + integrity sha512-C8ikRNRMygCwaTx+Ek3Yr+OuZzgZjduCOfSQBjbM8V3MfgcjSTeto/GXP6PAwKvJz/v15b7GHZvx5rOlczFw/Q== + dependencies: + custom-error-instance "2.1.1" + lodash.uniqby "4.5.0" + console-control-strings@^1.0.0, console-control-strings@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" @@ -682,6 +1088,11 @@ convert-source-map@^1.7.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== +core-js@^3.27.2: + version "3.31.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.31.1.tgz#f2b0eea9be9da0def2c5fece71064a7e5d687653" + integrity sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ== + core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -704,6 +1115,13 @@ cross-fetch@^3.1.4: dependencies: node-fetch "2.6.7" +cross-fetch@^3.1.5: + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + dependencies: + node-fetch "^2.6.12" + crypto-js@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" @@ -728,6 +1146,11 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +custom-error-instance@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/custom-error-instance/-/custom-error-instance-2.1.1.tgz#3cf6391487a6629a6247eb0ca0ce00081b7e361a" + integrity sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg== + date-fns@^2.28.0: version "2.29.3" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" @@ -772,6 +1195,11 @@ dequal@^2.0.2: resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== +detect-node-es@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== + dom-serializer@^1.0.1: version "1.4.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" @@ -927,6 +1355,11 @@ get-intrinsic@^1.0.2: has-proto "^1.0.1" has-symbols "^1.0.3" +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + gif-picker-react@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/gif-picker-react/-/gif-picker-react-1.2.0.tgz#bbedd040b5433b5de00d447d1a68f08de1e17715" @@ -934,7 +1367,7 @@ gif-picker-react@^1.1.0: dependencies: "@storybook/addon-styling" "^1.0.8" -graceful-fs@^4.1.6, graceful-fs@^4.2.0: +graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -979,6 +1412,11 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hls.js@^1.4.0: + version "1.4.8" + resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-1.4.8.tgz#6fedcb5224d7361e4f38046ffd45286d8a645df8" + integrity sha512-wYL7W49M6oKv0+P4RW50YkJaxDzgnHMMrN+YoLpow07hVgaedAdX9HfKkehTb04UEfeJhNSef5ucICYPsHOfqg== + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -1039,6 +1477,13 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -1049,6 +1494,11 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -1059,12 +1509,17 @@ jiti@^1.18.2: resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.18.2.tgz#80c3ef3d486ebf2450d9335122b32d121f2a83cd" integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg== +js-base64@^3.7.2: + version "3.7.5" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.5.tgz#21e24cf6b886f76d6f5f165bfcd69cc55b9e3fca" + integrity sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA== + js-sha3@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -js-tokens@^4.0.0: +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -1113,6 +1568,21 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +livepeer@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/livepeer/-/livepeer-2.6.0.tgz#b2c1011436ec801390e8b77d1322087c83171c6b" + integrity sha512-tURkBvJQi0nyS5WlFHhKyRGx0qKqGt/DbKSzhUwJ9fAzT3GAlipujgKVOc3wnNWIj76LQrCp7onUmsrrkFRGkQ== + dependencies: + "@livepeer/core" "^1.6.0" + "@stitches/core" "^1.2.8" + core-js "^3.27.2" + cross-fetch "^3.1.5" + hls.js "^1.4.0" + ms "^3.0.0-canary.1" + multiformats "9.9.0" + tus-js-client "^3.0.1" + zustand "^4.3.2" + loader-utils@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" @@ -1122,11 +1592,68 @@ loader-utils@^2.0.0: emojis-list "^3.0.0" json5 "^2.1.2" +lodash._baseiteratee@~4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash._baseiteratee/-/lodash._baseiteratee-4.7.0.tgz#34a9b5543572727c3db2e78edae3c0e9e66bd102" + integrity sha512-nqB9M+wITz0BX/Q2xg6fQ8mLkyfF7MU7eE+MNBNjTHFKeKaZAPEzEg+E8LWxKWf1DQVflNEn9N49yAuqKh2mWQ== + dependencies: + lodash._stringtopath "~4.8.0" + +lodash._basetostring@~4.12.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz#9327c9dc5158866b7fa4b9d42f4638e5766dd9df" + integrity sha512-SwcRIbyxnN6CFEEK4K1y+zuApvWdpQdBHM/swxP962s8HIxPO3alBH5t3m/dl+f4CMUug6sJb7Pww8d13/9WSw== + +lodash._baseuniq@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" + integrity sha512-Ja1YevpHZctlI5beLA7oc5KNDhGcPixFhcqSiORHNsp/1QTv7amAXzw+gu4YOvErqVlMVyIJGgtzeepCnnur0A== + dependencies: + lodash._createset "~4.0.0" + lodash._root "~3.0.0" + +lodash._createset@~4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" + integrity sha512-GTkC6YMprrJZCYU3zcqZj+jkXkrXzq3IPBcF/fIPpNEAB4hZEtXU8zp/RwKOvZl43NUmwDbyRk3+ZTbeRdEBXA== + +lodash._root@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + integrity sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ== + +lodash._stringtopath@~4.8.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/lodash._stringtopath/-/lodash._stringtopath-4.8.0.tgz#941bcf0e64266e5fc1d66fed0a6959544c576824" + integrity sha512-SXL66C731p0xPDC5LZg4wI5H+dJo/EO4KTqOMwLYCH3+FmmfAKJEZCm6ohGpI+T1xwsDsJCfL4OnhorllvlTPQ== + dependencies: + lodash._basetostring "~4.12.0" + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +lodash.uniqby@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.5.0.tgz#a3a17bbf62eeb6240f491846e97c1c4e2a5e1e21" + integrity sha512-IRt7cfTtHy6f1aRVA5n7kT8rgN3N1nH6MOWLcHfpWG2SH19E3JksLK38MktLxZDhlAjCP9jpIXkOnRXlu6oByQ== + dependencies: + lodash._baseiteratee "~4.7.0" + lodash._baseuniq "~4.6.0" + lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -1171,6 +1698,16 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +ms@^3.0.0-canary.1: + version "3.0.0-canary.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-3.0.0-canary.1.tgz#c7b34fbce381492fd0b345d1cf56e14d67b77b80" + integrity sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g== + +multiformats@9.9.0: + version "9.9.0" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" + integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== + nanoid@^3.3.6: version "3.3.6" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" @@ -1193,6 +1730,13 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" +node-fetch@^2.6.12: + version "2.6.12" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" + integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + dependencies: + whatwg-url "^5.0.0" + npmlog@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" @@ -1310,6 +1854,15 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +proper-lockfile@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== + dependencies: + graceful-fs "^4.2.4" + retry "^0.12.0" + signal-exit "^3.0.2" + qs@^6.10.0: version "6.11.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" @@ -1317,6 +1870,11 @@ qs@^6.10.0: dependencies: side-channel "^1.0.4" +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + ramda@0.29.0: version "0.29.0" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.29.0.tgz#fbbb67a740a754c8a4cbb41e2a6e0eb8507f55fb" @@ -1334,6 +1892,34 @@ react-property@2.0.0: resolved "https://registry.yarnpkg.com/react-property/-/react-property-2.0.0.tgz#2156ba9d85fa4741faf1918b38efc1eae3c6a136" integrity sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw== +react-remove-scroll-bar@^2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz#53e272d7a5cb8242990c7f144c44d8bd8ab5afd9" + integrity sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A== + dependencies: + react-style-singleton "^2.2.1" + tslib "^2.0.0" + +react-remove-scroll@2.5.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77" + integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw== + dependencies: + react-remove-scroll-bar "^2.3.3" + react-style-singleton "^2.2.1" + tslib "^2.1.0" + use-callback-ref "^1.3.0" + use-sidecar "^1.1.2" + +react-style-singleton@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4" + integrity sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g== + dependencies: + get-nonce "^1.0.0" + invariant "^2.2.4" + tslib "^2.0.0" + readable-stream@^2.0.5: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" @@ -1356,11 +1942,21 @@ readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + regex-parser@^2.2.11: version "2.2.11" resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58" integrity sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q== +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -1377,6 +1973,11 @@ resolve-url-loader@^5.0.0: postcss "^8.2.14" source-map "0.6.1" +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -1416,7 +2017,7 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.0: +signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -1556,11 +2157,29 @@ ts-dedent@^2.0.0: resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== +tslib@^2.0.0, tslib@^2.1.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3" + integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== + tslib@^2.3.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== +tus-js-client@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/tus-js-client/-/tus-js-client-3.1.0.tgz#20af57d06c23823fbe108ccb3a3dcb7503968cb4" + integrity sha512-Hfpc8ho4C9Lhs/OflPUA/nHUHZJUrKD5upoPBq7dYJJ9DQhWocsjJU2RZYfN16Y5n19j9dFDszwCvVZ5sfcogw== + dependencies: + buffer-from "^1.1.2" + combine-errors "^3.0.3" + is-stream "^2.0.0" + js-base64 "^3.7.2" + lodash.throttle "^4.1.1" + proper-lockfile "^4.1.2" + url-parse "^1.5.7" + type-fest@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" @@ -1576,6 +2195,21 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== +url-parse@^1.5.7: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +use-callback-ref@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.0.tgz#772199899b9c9a50526fedc4993fc7fa1f7e32d5" + integrity sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w== + dependencies: + tslib "^2.0.0" + use-resize-observer@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/use-resize-observer/-/use-resize-observer-9.1.0.tgz#14735235cf3268569c1ea468f8a90c5789fc5c6c" @@ -1583,6 +2217,19 @@ use-resize-observer@^9.1.0: dependencies: "@juggle/resize-observer" "^3.3.1" +use-sidecar@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2" + integrity sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw== + dependencies: + detect-node-es "^1.1.0" + tslib "^2.0.0" + +use-sync-external-store@1.2.0, use-sync-external-store@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -1641,3 +2288,10 @@ yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +zustand@^4.3.2: + version "4.3.9" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.9.tgz#a7d4332bbd75dfd25c6848180b3df1407217f2ad" + integrity sha512-Tat5r8jOMG1Vcsj8uldMyqYKC5IZvQif8zetmLHs9WoZlntTHmIoNM8TpLRY31ExncuUvUOXehd0kvahkuHjDw== + dependencies: + use-sync-external-store "1.2.0"