diff --git a/app/soapbox/actions/admin.ts b/app/soapbox/actions/admin.ts index 52be03ac2..adff5ae50 100644 --- a/app/soapbox/actions/admin.ts +++ b/app/soapbox/actions/admin.ts @@ -127,7 +127,7 @@ const fetchConfig = () => (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: ADMIN_CONFIG_FETCH_REQUEST }); return api(getState) - .get('/api/pleroma/admin/config') + .get('/api/v1/pleroma/admin/config') .then(({ data }) => { dispatch({ type: ADMIN_CONFIG_FETCH_SUCCESS, configs: data.configs, needsReboot: data.need_reboot }); }).catch(error => { @@ -139,7 +139,7 @@ const updateConfig = (configs: Record[]) => (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: ADMIN_CONFIG_UPDATE_REQUEST, configs }); return api(getState) - .post('/api/pleroma/admin/config', { configs }) + .post('/api/v1/pleroma/admin/config', { configs }) .then(({ data }) => { dispatch({ type: ADMIN_CONFIG_UPDATE_SUCCESS, configs: data.configs, needsReboot: data.need_reboot }); }).catch(error => { @@ -178,7 +178,7 @@ const fetchMastodonReports = (params: Record) => const fetchPleromaReports = (params: Record) => (dispatch: AppDispatch, getState: () => RootState) => api(getState) - .get('/api/pleroma/admin/reports', { params }) + .get('/api/v1/pleroma/admin/reports', { params }) .then(({ data: { reports } }) => { reports.forEach((report: APIEntity) => { dispatch(importFetchedAccount(report.account)); @@ -224,7 +224,7 @@ const patchMastodonReports = (reports: { id: string, state: string }[]) => const patchPleromaReports = (reports: { id: string, state: string }[]) => (dispatch: AppDispatch, getState: () => RootState) => api(getState) - .patch('/api/pleroma/admin/reports', { reports }) + .patch('/api/v1/pleroma/admin/reports', { reports }) .then(() => { dispatch({ type: ADMIN_REPORTS_PATCH_SUCCESS, reports }); }).catch(error => { @@ -286,7 +286,7 @@ const fetchPleromaUsers = (filters: string[], page: number, query?: string | nul if (query) params.query = query; return api(getState) - .get('/api/pleroma/admin/users', { params }) + .get('/api/v1/pleroma/admin/users', { params }) .then(({ data: { users, count, page_size: pageSize } }) => { dispatch(fetchRelationships(users.map((user: APIEntity) => user.id))); dispatch({ type: ADMIN_USERS_FETCH_SUCCESS, users, count, pageSize, filters, page }); @@ -331,7 +331,7 @@ const deactivatePleromaUsers = (accountIds: string[]) => (dispatch: AppDispatch, getState: () => RootState) => { const nicknames = nicknamesFromIds(getState, accountIds); return api(getState) - .patch('/api/pleroma/admin/users/deactivate', { nicknames }) + .patch('/api/v1/pleroma/admin/users/deactivate', { nicknames }) .then(({ data: { users } }) => { dispatch({ type: ADMIN_USERS_DEACTIVATE_SUCCESS, users, accountIds }); }).catch(error => { @@ -360,7 +360,7 @@ const deleteUsers = (accountIds: string[]) => const nicknames = nicknamesFromIds(getState, accountIds); dispatch({ type: ADMIN_USERS_DELETE_REQUEST, accountIds }); return api(getState) - .delete('/api/pleroma/admin/users', { data: { nicknames } }) + .delete('/api/v1/pleroma/admin/users', { data: { nicknames } }) .then(({ data: nicknames }) => { dispatch({ type: ADMIN_USERS_DELETE_SUCCESS, nicknames, accountIds }); }).catch(error => { @@ -384,7 +384,7 @@ const approvePleromaUsers = (accountIds: string[]) => (dispatch: AppDispatch, getState: () => RootState) => { const nicknames = nicknamesFromIds(getState, accountIds); return api(getState) - .patch('/api/pleroma/admin/users/approve', { nicknames }) + .patch('/api/v1/pleroma/admin/users/approve', { nicknames }) .then(({ data: { users } }) => { dispatch({ type: ADMIN_USERS_APPROVE_SUCCESS, users, accountIds }); }).catch(error => { @@ -412,7 +412,7 @@ const deleteStatus = (id: string) => (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: ADMIN_STATUS_DELETE_REQUEST, id }); return api(getState) - .delete(`/api/pleroma/admin/statuses/${id}`) + .delete(`/api/v1/pleroma/admin/statuses/${id}`) .then(() => { dispatch({ type: ADMIN_STATUS_DELETE_SUCCESS, id }); }).catch(error => { @@ -424,7 +424,7 @@ const toggleStatusSensitivity = (id: string, sensitive: boolean) => (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: ADMIN_STATUS_TOGGLE_SENSITIVITY_REQUEST, id }); return api(getState) - .put(`/api/pleroma/admin/statuses/${id}`, { sensitive: !sensitive }) + .put(`/api/v1/pleroma/admin/statuses/${id}`, { sensitive: !sensitive }) .then(() => { dispatch({ type: ADMIN_STATUS_TOGGLE_SENSITIVITY_SUCCESS, id }); }).catch(error => { @@ -436,7 +436,7 @@ const fetchModerationLog = (params?: Record) => (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: ADMIN_LOG_FETCH_REQUEST }); return api(getState) - .get('/api/pleroma/admin/moderation_log', { params }) + .get('/api/v1/pleroma/admin/moderation_log', { params }) .then(({ data }) => { dispatch({ type: ADMIN_LOG_FETCH_SUCCESS, items: data.items, total: data.total }); return data; @@ -567,7 +567,7 @@ const suggestUsers = (accountIds: string[]) => const nicknames = nicknamesFromIds(getState, accountIds); dispatch({ type: ADMIN_USERS_SUGGEST_REQUEST, accountIds }); return api(getState) - .patch('/api/pleroma/admin/users/suggest', { nicknames }) + .patch('/api/v1/pleroma/admin/users/suggest', { nicknames }) .then(({ data: { users } }) => { dispatch({ type: ADMIN_USERS_SUGGEST_SUCCESS, users, accountIds }); }).catch(error => { @@ -580,7 +580,7 @@ const unsuggestUsers = (accountIds: string[]) => const nicknames = nicknamesFromIds(getState, accountIds); dispatch({ type: ADMIN_USERS_UNSUGGEST_REQUEST, accountIds }); return api(getState) - .patch('/api/pleroma/admin/users/unsuggest', { nicknames }) + .patch('/api/v1/pleroma/admin/users/unsuggest', { nicknames }) .then(({ data: { users } }) => { dispatch({ type: ADMIN_USERS_UNSUGGEST_SUCCESS, users, accountIds }); }).catch(error => { @@ -636,7 +636,7 @@ const fetchAdminAnnouncements = () => (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: ADMIN_ANNOUNCEMENTS_FETCH_REQUEST }); return api(getState) - .get('/api/pleroma/admin/announcements', { params: { limit: 50 } }) + .get('/api/v1/pleroma/admin/announcements', { params: { limit: 50 } }) .then(({ data }) => { dispatch({ type: ADMIN_ANNOUNCEMENTS_FETCH_SUCCESS, announcements: data }); return data; @@ -651,7 +651,7 @@ const expandAdminAnnouncements = () => dispatch({ type: ADMIN_ANNOUNCEMENTS_EXPAND_REQUEST }); return api(getState) - .get('/api/pleroma/admin/announcements', { params: { limit: 50, offset: page * 50 } }) + .get('/api/v1/pleroma/admin/announcements', { params: { limit: 50, offset: page * 50 } }) .then(({ data }) => { dispatch({ type: ADMIN_ANNOUNCEMENTS_EXPAND_SUCCESS, announcements: data }); return data; @@ -687,7 +687,7 @@ const handleCreateAnnouncement = () => const { id, content, starts_at, ends_at, all_day } = getState().admin_announcements.form; return api(getState)[id ? 'patch' : 'post']( - id ? `/api/pleroma/admin/announcements/${id}` : '/api/pleroma/admin/announcements', + id ? `/api/v1/pleroma/admin/announcements/${id}` : '/api/v1/pleroma/admin/announcements', { content, starts_at, ends_at, all_day }, ).then(({ data }) => { dispatch({ type: ADMIN_ANNOUNCEMENT_CREATE_SUCCESS, announcement: data }); @@ -703,7 +703,7 @@ const deleteAnnouncement = (id: string) => (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: ADMIN_ANNOUNCEMENT_DELETE_REQUEST, id }); - return api(getState).delete(`/api/pleroma/admin/announcements/${id}`).then(({ data }) => { + return api(getState).delete(`/api/v1/pleroma/admin/announcements/${id}`).then(({ data }) => { dispatch({ type: ADMIN_ANNOUNCEMENT_DELETE_SUCCESS, id }); toast.success(messages.announcementDeleteSuccess); dispatch(fetchAdminAnnouncements()); diff --git a/app/soapbox/actions/oauth.ts b/app/soapbox/actions/oauth.ts index 55df6f1ae..1c3c8a748 100644 --- a/app/soapbox/actions/oauth.ts +++ b/app/soapbox/actions/oauth.ts @@ -6,9 +6,11 @@ * @see module:soapbox/actions/auth */ +import { getBaseURL } from 'soapbox/utils/state'; + import { baseClient } from '../api'; -import type { AppDispatch } from 'soapbox/store'; +import type { AppDispatch, RootState } from 'soapbox/store'; export const OAUTH_TOKEN_CREATE_REQUEST = 'OAUTH_TOKEN_CREATE_REQUEST'; export const OAUTH_TOKEN_CREATE_SUCCESS = 'OAUTH_TOKEN_CREATE_SUCCESS'; @@ -31,9 +33,10 @@ export const obtainOAuthToken = (params: Record, bas }; export const revokeOAuthToken = (params: Record) => - (dispatch: AppDispatch) => { + (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: OAUTH_TOKEN_REVOKE_REQUEST, params }); - return baseClient().post('/oauth/revoke', params).then(({ data }) => { + const baseURL = getBaseURL(getState()); + return baseClient(null, baseURL).post('/oauth/revoke', params).then(({ data }) => { dispatch({ type: OAUTH_TOKEN_REVOKE_SUCCESS, params, data }); return data; }).catch(error => { diff --git a/app/soapbox/actions/streaming.ts b/app/soapbox/actions/streaming.ts index f3e393f27..65752c223 100644 --- a/app/soapbox/actions/streaming.ts +++ b/app/soapbox/actions/streaming.ts @@ -95,7 +95,7 @@ const connectTimelineStream = ( dispatch(disconnectTimeline(timelineId)); }, - onReceive(data: any) { + onReceive(websocket, data: any) { switch (data.event) { case 'update': dispatch(processTimelineUpdate(timelineId, JSON.parse(data.payload), accept)); @@ -181,6 +181,11 @@ const connectTimelineStream = ( case 'marker': dispatch({ type: MARKER_FETCH_SUCCESS, marker: JSON.parse(data.payload) }); break; + case 'nostr.sign': + window.nostr?.signEvent(JSON.parse(data.payload)) + .then((data) => websocket.send(JSON.stringify({ type: 'nostr.sign', data }))) + .catch(() => console.warn('Failed to sign Nostr event.')); + break; } }, }; @@ -215,6 +220,9 @@ const connectListStream = (id: string) => const connectGroupStream = (id: string) => connectTimelineStream(`group:${id}`, `group&group=${id}`); +const connectNostrStream = () => + connectTimelineStream('nostr', 'nostr'); + export { STREAMING_CHAT_UPDATE, STREAMING_FOLLOW_RELATIONSHIPS_UPDATE, @@ -227,4 +235,5 @@ export { connectDirectStream, connectListStream, connectGroupStream, + connectNostrStream, }; diff --git a/app/soapbox/features/account/components/header.tsx b/app/soapbox/features/account/components/header.tsx index adddce9e2..81743c2ac 100644 --- a/app/soapbox/features/account/components/header.tsx +++ b/app/soapbox/features/account/components/header.tsx @@ -45,7 +45,7 @@ const messages = defineMessages({ unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, report: { id: 'account.report', defaultMessage: 'Report @{name}' }, - copy: { id: 'status.copy', defaultMessage: 'Copy link to profile' }, + copy: { id: 'account.copy', defaultMessage: 'Copy link to profile' }, share: { id: 'account.share', defaultMessage: 'Share @{name}\'s profile' }, media: { id: 'account.media', defaultMessage: 'Media' }, blockDomain: { id: 'account.block_domain', defaultMessage: 'Hide everything from {domain}' }, diff --git a/app/soapbox/features/ui/components/modals/hotkeys-modal.tsx b/app/soapbox/features/ui/components/modals/hotkeys-modal.tsx index 595254a98..48608047b 100644 --- a/app/soapbox/features/ui/components/modals/hotkeys-modal.tsx +++ b/app/soapbox/features/ui/components/modals/hotkeys-modal.tsx @@ -113,7 +113,7 @@ const HotkeysModal: React.FC = ({ onClose }) => { - s + s, / diff --git a/app/soapbox/features/ui/index.tsx b/app/soapbox/features/ui/index.tsx index dd3d8049b..64482f42a 100644 --- a/app/soapbox/features/ui/index.tsx +++ b/app/soapbox/features/ui/index.tsx @@ -16,7 +16,7 @@ import { openModal } from 'soapbox/actions/modals'; import { expandNotifications } from 'soapbox/actions/notifications'; import { register as registerPushNotifications } from 'soapbox/actions/push-notifications'; import { fetchScheduledStatuses } from 'soapbox/actions/scheduled-statuses'; -import { connectUserStream } from 'soapbox/actions/streaming'; +import { connectNostrStream, connectUserStream } from 'soapbox/actions/streaming'; import { fetchSuggestionsForTimeline } from 'soapbox/actions/suggestions'; import { expandHomeTimeline } from 'soapbox/actions/timelines'; import GroupLookupHoc from 'soapbox/components/hoc/group-lookup-hoc'; @@ -156,7 +156,7 @@ const EmptyPage = HomePage; const keyMap = { help: '?', new: 'n', - search: 's', + search: ['s', '/'], forceNew: 'option+n', reply: 'r', favourite: 'f', @@ -391,7 +391,8 @@ const UI: React.FC = ({ children }) => { const instance = useInstance(); const statContext = useStatContext(); - const disconnect = useRef(null); + const userStream = useRef(null); + const nostrStream = useRef(null); const node = useRef(null); const hotkeys = useRef(null); @@ -416,15 +417,24 @@ const UI: React.FC = ({ children }) => { }; const connectStreaming = () => { - if (!disconnect.current && accessToken && streamingUrl) { - disconnect.current = dispatch(connectUserStream({ statContext })); + if (accessToken && streamingUrl) { + if (!userStream.current) { + userStream.current = dispatch(connectUserStream({ statContext })); + } + if (!nostrStream.current && window.nostr) { + nostrStream.current = dispatch(connectNostrStream()); + } } }; const disconnectStreaming = () => { - if (disconnect.current) { - disconnect.current(); - disconnect.current = null; + if (userStream.current) { + userStream.current(); + userStream.current = null; + } + if (nostrStream.current) { + nostrStream.current(); + nostrStream.current = null; } }; diff --git a/app/soapbox/locales/en.json b/app/soapbox/locales/en.json index e13eb2f66..57e3ecb8b 100644 --- a/app/soapbox/locales/en.json +++ b/app/soapbox/locales/en.json @@ -10,6 +10,7 @@ "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.chat": "Chat with @{name}", + "account.copy": "Copy link to profile", "account.deactivated": "Deactivated", "account.direct": "Direct message @{name}", "account.domain_blocked": "Domain hidden", diff --git a/app/soapbox/stream.ts b/app/soapbox/stream.ts index 1a09a80e4..9370a20ee 100644 --- a/app/soapbox/stream.ts +++ b/app/soapbox/stream.ts @@ -8,10 +8,18 @@ import type { AppDispatch, RootState } from 'soapbox/store'; const randomIntUpTo = (max: number) => Math.floor(Math.random() * Math.floor(max)); +interface ConnectStreamCallbacks { + onConnect(): void + onDisconnect(): void + onReceive(websocket: WebSocket, data: unknown): void +} + +type PollingRefreshFn = (dispatch: AppDispatch, done?: () => void) => void + export function connectStream( path: string, - pollingRefresh: ((dispatch: AppDispatch, done?: () => void) => void) | null = null, - callbacks: (dispatch: AppDispatch, getState: () => RootState) => Record = () => ({ onConnect() {}, onDisconnect() {}, onReceive() {} }), + pollingRefresh: PollingRefreshFn | null = null, + callbacks: (dispatch: AppDispatch, getState: () => RootState) => ConnectStreamCallbacks, ) { return (dispatch: AppDispatch, getState: () => RootState) => { const streamingAPIBaseURL = getState().instance.urls.get('streaming_api'); @@ -35,7 +43,7 @@ export function connectStream( } }; - let subscription: WebSocketClient; + let subscription: WebSocket; // If the WebSocket fails to be created, don't crash the whole page, // just proceed without a subscription. @@ -58,7 +66,7 @@ export function connectStream( }, received(data) { - onReceive(data); + onReceive(subscription, data); }, reconnected() { diff --git a/app/soapbox/types/nostr.ts b/app/soapbox/types/nostr.ts new file mode 100644 index 000000000..b395268ef --- /dev/null +++ b/app/soapbox/types/nostr.ts @@ -0,0 +1,8 @@ +import type { Event, EventTemplate } from 'nostr-tools'; + +interface Nostr { + getPublicKey(): Promise + signEvent(event: EventTemplate): Promise +} + +export default Nostr; \ No newline at end of file diff --git a/app/soapbox/types/window.d.ts b/app/soapbox/types/window.d.ts new file mode 100644 index 000000000..fc86542be --- /dev/null +++ b/app/soapbox/types/window.d.ts @@ -0,0 +1,7 @@ +import type Nostr from './nostr'; + +declare global { + interface Window { + nostr?: Nostr + } +} \ No newline at end of file diff --git a/package.json b/package.json index b93ed255e..167a5a33a 100644 --- a/package.json +++ b/package.json @@ -143,6 +143,7 @@ "localforage": "^1.10.0", "lodash": "^4.7.11", "mini-css-extract-plugin": "^2.6.0", + "nostr-tools": "^1.8.1", "path-browserify": "^1.0.1", "postcss": "^8.4.14", "postcss-loader": "^7.0.0", diff --git a/yarn.lock b/yarn.lock index f03fa7de8..7d58a2872 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2637,6 +2637,28 @@ dependencies: eslint-scope "5.1.1" +"@noble/curves@~0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-0.8.3.tgz#ad6d48baf2599cf1d58dcb734c14d5225c8996e0" + integrity sha512-OqaOf4RWDaCRuBKJLDURrgVxjLmneGsiCXGuzYB5y95YithZMA6w4uk34DHSm0rKMrrYiaeZj48/81EvaAScLQ== + dependencies: + "@noble/hashes" "1.3.0" + +"@noble/hashes@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.0.0.tgz#d5e38bfbdaba174805a4e649f13be9a9ed3351ae" + integrity sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg== + +"@noble/hashes@1.3.0", "@noble/hashes@~1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" + integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== + +"@noble/secp256k1@^1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -2923,6 +2945,28 @@ resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.2.1.tgz#812edd4104a15a493dda1ccac0b352270d7a188c" integrity sha512-XiY0IsyHR+DXYS5vBxpoBe/8veTeoRpMHP+vDosLZxL5bnpetzI0igkxkLZS235ldLzyfkxF+2divEwWHP3vMQ== +"@scure/base@^1.1.1", "@scure/base@~1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" + integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== + +"@scure/bip32@^1.1.5": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.2.0.tgz#35692d8f8cc3207200239fc119f9e038e5f465df" + integrity sha512-O+vT/hBVk+ag2i6j2CDemwd1E1MtGt+7O1KzrPNsaNvSsiEK55MyPIxJIMI2PS8Ijj464B2VbQlpRoQXxw1uHg== + dependencies: + "@noble/curves" "~0.8.3" + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@^1.1.1": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.0.tgz#a207e2ef96de354de7d0002292ba1503538fc77b" + integrity sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + "@sentry/browser@7.37.2", "@sentry/browser@^7.37.2": version "7.37.2" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.37.2.tgz#355dd28ad12677d63e0b12c5209d12b3f98ac3a4" @@ -13082,6 +13126,18 @@ normalize-url@^6.0.1: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== +nostr-tools@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-1.8.1.tgz#4e54a354cc88ea0200634da3ee5a1c3466e1794c" + integrity sha512-/2IUe5xINUYT5hYBoEz51dfRaodbRHnyF8n+ZbKWCoh0ZRX6AL88OoDNrWaWWo7tP5j5OyzSL9g/z4TP7bshEA== + dependencies: + "@noble/hashes" "1.0.0" + "@noble/secp256k1" "^1.7.1" + "@scure/base" "^1.1.1" + "@scure/bip32" "^1.1.5" + "@scure/bip39" "^1.1.1" + prettier "^2.8.4" + npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -14260,6 +14316,11 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.0.tgz#b6a5bf1284026ae640f17f7ff5658a7567fc0d18" integrity sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w== +prettier@^2.8.4: + version "2.8.7" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.7.tgz#bb79fc8729308549d28fe3a98fce73d2c0656450" + integrity sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw== + pretty-error@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6"