diff --git a/README.md b/README.md index 0786520a5..58ba8e4f8 100644 --- a/README.md +++ b/README.md @@ -103,14 +103,13 @@ The project includes several Make commands to manage Docker containers and devel ### Optional configuration -PayButton Server is configured with a `paybutton-config.json` file in the root of the repository. An example file can be find at [config/example-config.json](https://github.com/PayButton/paybutton-server/blob/master/config/example-config.json). The values it takes are: +PayButton Server is configured with a `paybutton-config.json` file in the root of the repository. An example file with the default values can be find at [config/example-config.json](https://github.com/PayButton/paybutton-server/blob/master/config/example-config.json). The values it takes are: --- #### **apiDomain** ``` type: string -default: "http://localhost:3000/api", ``` > Base path for the API. @@ -118,15 +117,19 @@ default: "http://localhost:3000/api", #### apiBasePath ``` type: string -default: "/api/auth" ``` > Base API endpoint for authentication. +#### websiteBasePath +``` +type: string +``` +> Base API endpoint for authentication through SuperTokens. + #### websiteDomain ``` type: string -default: "http://localhost:3000" ``` > Base path for the website. @@ -134,7 +137,6 @@ default: "http://localhost:3000" #### wsBaseURL ``` type: string -default: "http://localhost:5000" ``` > Base path for the websocket server. @@ -142,7 +144,6 @@ default: "http://localhost:5000" #### showTestNetworks ``` type: boolean -default: false, ``` > If the connection of test networks for eCash and Bitcoin Cash should appear in the Networks tab. @@ -161,14 +162,12 @@ type: { #### priceAPIURL ``` type: string -default: "https://coin.dance/api/" ``` > API to get prices from. Only coin.dance currently supported. #### redisURL ``` type: string -default: "redis://paybutton-cache:6379" ``` > URL for the Redis server. @@ -179,10 +178,6 @@ type: { "ecash": "chronik", "bitcoincash": "chronik" } -default: { - "ecash": "chronik", - "bitcoincash": "chronik" -} ``` > Which client to use to get the blockchain information for each network. Currently, only "chronik" is supported for eCash and Bitcoin Cash. @@ -193,10 +188,6 @@ type: { "ecash": boolean "bitcoincash": boolean } - -default: { - "bitcoincash": true -} ``` > What networks are currently under maintenance. @@ -204,14 +195,12 @@ default: { #### triggerPOSTTimeout ``` type: number -default: 3000 ``` > How long a POST request triggered from a button payment will wait for an answer to be marked as successful. #### smtpHost ``` type: string -default: N/A ``` > Host name for the server from which payment trigger emails will be sent. Not setting this up will result in email triggers not working. @@ -219,7 +208,6 @@ default: N/A #### smtpPort ``` type: number -default: N/A ``` > Port for the SMTP server from which payment trigger emails will be sent. Not setting this up will result in email triggers not working. @@ -227,10 +215,59 @@ default: N/A #### sideshiftAffiliateId ``` type: string -default: N/A ``` > Necessary only for paybutton client to interact with sideshift through the server. +#### proSettings +``` +type: object +``` +> General configuration for PayButton Pro. Each parameter is described below. + +##### proSettings.enabled +``` +type: boolean +``` +> If the Pro feature should be enabled or hidden. + +##### proSettings.monthsCost +``` +type: { +[key: string]: number +} +``` +> The pricing model for PayButton Pro subscription — [value] USD for [key] months. + +##### proSettings.payoutAddress +``` +type: string +``` +> The payout address for PayButton Pro subscriptions. + +##### proSettings.standardDailyEmailLimit +``` +type: number | "Inf" +``` +> How many emails can a standard user send daily. + +##### proSettings.proDailyEmailLimit +``` +type: number | "Inf" +``` +> How many emails can a PayButton Pro user send daily. + +##### proSettings.standardAddressesPerButtonLimit +``` +type: number | "Inf" +``` +> How many addresses can a standard Pro user add for a single button. + +##### proSettings.proAddressesPerButtonLimit +``` +type: number | "Inf" +``` +> How many addresses can a PayButton Pro user add for a single button. + --- - For production, set `ENVIRONMENT=production` in `.env.local.` This optimizes the build for performance and skips the setup of various dev tools (like LiveReload). diff --git a/components/Account/ProDisplay.tsx b/components/Account/ProDisplay.tsx new file mode 100644 index 000000000..5339d736a --- /dev/null +++ b/components/Account/ProDisplay.tsx @@ -0,0 +1,76 @@ +import { useEffect, useState } from 'react' +import ProPurchase from './ProPurchase' +import style from './account.module.css' +import stylep from '../../pages/account/account.module.css' +import config from 'config/index' + +const ProConfig = (): JSX.Element => { + const [text, setText] = useState('') + const [isPro, setIsPro] = useState() + + const showLimit = (configLimit: number | 'Inf'): string => { + return configLimit === 'Inf' ? 'Unlimited' : configLimit.toString() + } + + useEffect(() => { + void (async () => { + const res = await fetch('/api/user/remainingProTime') + if (res.status === 200) { + const remainingMs: number | null = await res.json() + if (remainingMs === null) { + setIsPro(false) + setText('You are not PRO.') + } else if (remainingMs <= 0) { + setIsPro(false) + setText('Your PRO has expired.') + } else { + const futureDate = new Date(Date.now() + remainingMs) + setIsPro(true) + setText(`You are PRO until ${futureDate.toLocaleDateString()}.`) + } + } else { + setText('Failed to fetch PRO status') + } + })() + }, []) + + return <> +

PayButton Pro

+
+
+ {text} +
+ {isPro === false && } +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
StandardPro
Outgoing Emails on Payment{showLimit(config.proSettings.standardDailyEmailLimit)} / day{showLimit(config.proSettings.proDailyEmailLimit)} / day
Addresses Per Button{showLimit(config.proSettings.standardAddressesPerButtonLimit)}{showLimit(config.proSettings.proAddressesPerButtonLimit)}
Outgoing Server-to-Server Messages On Payment{showLimit(config.proSettings.standardDailyEmailLimit)} / day{showLimit(config.proSettings.proDailyEmailLimit)} / day
+
+
+ +} + +export default ProConfig diff --git a/components/Account/ProPurchase.tsx b/components/Account/ProPurchase.tsx new file mode 100644 index 000000000..16f0ade02 --- /dev/null +++ b/components/Account/ProPurchase.tsx @@ -0,0 +1,13 @@ +import Button from 'components/Button' +import Link from 'next/link' +import style from './account.module.css' + +const ProPurchase = (): JSX.Element => { + return
+ + + +
+} + +export default ProPurchase diff --git a/components/Account/account.module.css b/components/Account/account.module.css index b67731025..e37aabf5c 100644 --- a/components/Account/account.module.css +++ b/components/Account/account.module.css @@ -44,3 +44,33 @@ body[data-theme='dark'] .changepw_ctn input { } } +.pro_ctn { + width: 100%; + background-color: #fff; + max-width: 700px; + padding: 20px; + border-radius: 10px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-around; +} + +body[data-theme="dark"] .pro_ctn { + background-color: var(--secondary-bg-color); +} + +body[data-theme="dark"] .pro_ctn input { + border-color: var(--gray) +} + +.upgrade_btn { + margin-top: 2rem; + width: 100% +} +.upgrade_btn a { + width: 100% +} +.upgrade_btn a button { + width: 100% +} diff --git a/components/Button/index.tsx b/components/Button/index.tsx index 367d981a8..cabd8cf6d 100644 --- a/components/Button/index.tsx +++ b/components/Button/index.tsx @@ -19,7 +19,7 @@ interface ButtonProps { loading?: boolean } -export default function TopBar ({ +export default function Button ({ children, disabled, type = 'button', diff --git a/components/Organization/ViewOrganization.tsx b/components/Organization/ViewOrganization.tsx index 4fe902b28..3897007cc 100644 --- a/components/Organization/ViewOrganization.tsx +++ b/components/Organization/ViewOrganization.tsx @@ -22,7 +22,8 @@ const ViewOrganization = ({ user, orgMembers, setOrgMembers, organization }: IPr const [orgEdit, setOrgEdit] = useState('') const [loading, setLoading] = useState(false) - return ( + return <> +

Organization

{org !== null && org.creatorId === user.userProfile.id ? ( @@ -129,7 +130,7 @@ const ViewOrganization = ({ user, orgMembers, setOrgMembers, organization }: IPr )} {error !== '' &&
{error}
}
- ) + } export default ViewOrganization diff --git a/config/example-config.json b/config/example-config.json index f77182ff3..1ba97b69b 100644 --- a/config/example-config.json +++ b/config/example-config.json @@ -29,5 +29,19 @@ "bitcoincash": true }, "triggerPOSTTimeout": 3000, - "sideshiftAffiliateId": "JPk84U3xN" + "sideshiftAffiliateId": "JPk84U3xN", + "proSettings": { + "enabled": true, + "monthsCost": { + "1": 10, + "3": 20, + "6": 30, + "12": 50 + }, + "payoutAddress": "ecash:qrf4zh4vgrdal8d8gu905d90w5u2y60djcd2d5h6un", + "standardDailyEmailLimit": 5, + "proDailyEmailLimit": 100, + "standardAddressesPerButtonLimit": 20, + "proAddressesPerButtonLimit": "Inf" + } } diff --git a/config/index.ts b/config/index.ts index b67055e95..b6b67d590 100644 --- a/config/index.ts +++ b/config/index.ts @@ -3,6 +3,18 @@ import localConfig from '../paybutton-config.json' export type BlockchainClientOptions = 'grpc' | 'chronik' +interface ProSettings { + enabled: boolean + monthsCost: { + [key: string]: number + } + payoutAddress: string + standardDailyEmailLimit: number | 'Inf' + proDailyEmailLimit: number | 'Inf' + standardAddressesPerButtonLimit: number | 'Inf' + proAddressesPerButtonLimit: number | 'Inf' +} + interface Config { appName: string apiDomain: string @@ -21,6 +33,7 @@ interface Config { sideshiftAffiliateId: string smtpHost: string smtpPort: number + proSettings: ProSettings } const readConfig = (): Config => { diff --git a/pages/account/account.module.css b/pages/account/account.module.css index 4a8ee6678..9a99a6345 100644 --- a/pages/account/account.module.css +++ b/pages/account/account.module.css @@ -53,166 +53,166 @@ body[data-theme='dark'] .account_row select { } /* body[data-theme='dark'] .account_row select { - background-color: #434343 !important; - border-color: #898EA4 !important; +background-color: #434343 !important; +border-color: #898EA4 !important; } body[data-theme='dark'] .pk_card, body[data-theme='dark'] .pk_copy { - background-color: #434343; +background-color: #434343; } */ -.label { - width: 100%; - position: relative; - font-size: 15px; -} + .label { + width: 100%; + position: relative; + font-size: 15px; + } -.value { - font-weight: 600; - width: 100%; -} + .value { + font-weight: 600; + width: 100%; + } -.pk_ctn { - width: 100%; - display: flex; - align-items: center; - gap: 1px; - margin-top: 10px; -} + .pk_ctn { + width: 100%; + display: flex; + align-items: center; + gap: 1px; + margin-top: 10px; + } -.pk_card { - flex-grow: 2; - background-color: var(--primary-bg-color); - padding: 20px; - border-radius: 10px 0 0 10px; - display: inline-block; - font-weight: 600; - word-break: break-all; - position: relative; - font-weight: 400; - font-size: 16px; -} + .pk_card { + flex-grow: 2; + background-color: var(--primary-bg-color); + padding: 20px; + border-radius: 10px 0 0 10px; + display: inline-block; + font-weight: 600; + word-break: break-all; + position: relative; + font-weight: 400; + font-size: 16px; + } -.pk_copy { - width: 50px; - align-self: stretch; - display: flex; - align-items: center; - cursor: pointer; - background-color: var(--primary-bg-color); - border-radius: 0 10px 10px 0; - justify-content: center; - transition: all ease-in-out 200ms; - flex-shrink: 0; -} + .pk_copy { + width: 50px; + align-self: stretch; + display: flex; + align-items: center; + cursor: pointer; + background-color: var(--primary-bg-color); + border-radius: 0 10px 10px 0; + justify-content: center; + transition: all ease-in-out 200ms; + flex-shrink: 0; + } -body[data-theme='dark'] .pk_copy img { - filter: invert(1); -} + body[data-theme='dark'] .pk_copy img { + filter: invert(1); + } -.copied_confirmation { - width: 100%; - background-color: var(--accent-color); - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - border-radius: 10px 0 0 10px; - display: flex; - align-items: center; - justify-content: center; -} + .copied_confirmation { + width: 100%; + background-color: var(--accent-color); + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: 10px 0 0 10px; + display: flex; + align-items: center; + justify-content: center; + } -.pk_copy:hover { - background-color: var(--accent-color) !important; -} + .pk_copy:hover { + background-color: var(--accent-color) !important; + } -.updatebtn { - font-size: 14px; - cursor: pointer; - display: inline-block; - align-self: flex-start; - margin-top: 10px; - position: relative; - cursor: pointer; - padding: 5px 40px; - box-shadow: none; - font-size: 14px; -} + .updatebtn { + font-size: 14px; + cursor: pointer; + display: inline-block; + align-self: flex-start; + margin-top: 10px; + position: relative; + cursor: pointer; + padding: 5px 40px; + box-shadow: none; + font-size: 14px; + } -.public_key_info_btn { - cursor: pointer; - color: var(--accent-color); - font-size: 12px; - position: absolute; - right: 0; - user-select: none; - top: 3px; -} + .public_key_info_btn { + cursor: pointer; + color: var(--accent-color); + font-size: 12px; + position: absolute; + right: 0; + user-select: none; + top: 3px; + } -.public_key_info_ctn { - width: 100%; - margin-top: 10px; - font-size: 16px; - background-color: var(--primary-bg-color); - padding: 20px; - border-radius: 10px; -} + .public_key_info_ctn { + width: 100%; + margin-top: 10px; + font-size: 16px; + background-color: var(--primary-bg-color); + padding: 20px; + border-radius: 10px; + } -.updatebtn:hover { - background-color: var(--accent-color); -} + .updatebtn:hover { + background-color: var(--accent-color); + } -body[data-theme='dark'] .updatebtn:hover { - color: #231f20; -} + body[data-theme='dark'] .updatebtn:hover { + color: #231f20; + } -body[data-theme='dark'] .copy_btn img { - filter: grayscale(1) invert(1); -} + body[data-theme='dark'] .copy_btn img { + filter: grayscale(1) invert(1); + } -body[data-theme='dark'] .copy_btn:hover img { - filter: none; -} + body[data-theme='dark'] .copy_btn:hover img { + filter: none; + } -.change_pw_btn { - position: absolute; - right: 0; - top: 40px; - font-size: 12px; - background-color: var(--primary-bg-color); - border-radius: 100px; - padding: 3px 15px; - cursor: pointer; - user-select: none; -} + .change_pw_btn { + position: absolute; + right: 0; + top: 40px; + font-size: 12px; + background-color: var(--primary-bg-color); + border-radius: 100px; + padding: 3px 15px; + cursor: pointer; + user-select: none; + } -.change_pw_btn:hover { - background-color: var(--accent-color); -} + .change_pw_btn:hover { + background-color: var(--accent-color); + } -.whats_this_btn { - font-size: 12px; - background-color: var(--primary-bg-color); - border-radius: 100px; - padding: 3px 15px; - cursor: pointer; - user-select: none; - float: right; -} + .whats_this_btn { + font-size: 12px; + background-color: var(--primary-bg-color); + border-radius: 100px; + padding: 3px 15px; + cursor: pointer; + user-select: none; + float: right; + } -.whats_this_btn:hover { - background-color: var(--accent-color); -} + .whats_this_btn:hover { + background-color: var(--accent-color); + } -@media (max-width: 960px) { + @media (max-width: 960px) { .account_card, .public_key_card_ctn, .public_key_info_ctn, .label { - max-width: unset; + max-width: unset; } .copy_btn { @@ -225,7 +225,35 @@ body[data-theme='dark'] .copy_btn:hover img { } .updatebtn { - width: 100%; - text-align: center; + width: 100%; + text-align: center; } } + + +.public_key_info_ctn { + width: 100%; +} + +.public_key_info_ctn table { + width: 100%; + border-collapse: collapse; + border-spacing: 0; + margin: 0; + border-radius: 6px; +} + +.public_key_info_ctn th, +.public_key_info_ctn td { + border: none; + width: 100%; +} + +.public_key_info_ctn th { + background-color: black; + color: white; +} + +.public_key_info_ctn tr:nth-child(even) { + background-color: var(--secondary-bg-color); +} diff --git a/pages/account/index.tsx b/pages/account/index.tsx index 546c44e91..915d6d492 100644 --- a/pages/account/index.tsx +++ b/pages/account/index.tsx @@ -17,6 +17,8 @@ import { removeDateFields, removeUnserializableFields } from 'utils/index' import TopBar from 'components/TopBar' import TimezoneSelector from 'components/Timezone Selector' import moment from 'moment-timezone' +import config from 'config' +import ProDisplay from 'components/Account/ProDisplay' export const getServerSideProps: GetServerSideProps = async (context) => { supertokensNode.init(SuperTokensConfig.backendConfig()) @@ -189,7 +191,7 @@ export default function Account ({ user, userPublicKey, organization, orgMembers
-

Organization

+ {config.proSettings.enabled && }
) diff --git a/pages/api/user/remainingProTime/index.ts b/pages/api/user/remainingProTime/index.ts new file mode 100644 index 000000000..0117bb658 --- /dev/null +++ b/pages/api/user/remainingProTime/index.ts @@ -0,0 +1,15 @@ +import { setSession } from 'utils/setSession' +import * as userService from 'services/userService' + +export default async ( + req: any, + res: any +): Promise => { + await setSession(req, res, true) + + if (req.method === 'GET') { + const session = req.session + const remainingTime = await userService.userRemainingProTime(session.userId) + res.status(200).json(remainingTime) + } +} diff --git a/pages/pro/index.tsx b/pages/pro/index.tsx new file mode 100644 index 000000000..f38758b88 --- /dev/null +++ b/pages/pro/index.tsx @@ -0,0 +1,92 @@ +import { PayButton } from '@paybutton/react' +import config from 'config/index' +import React, { useState } from 'react' +import style from './pro.module.css' +import { UserProfile } from '@prisma/client' +import Page from 'components/Page' +import { GetServerSideProps } from 'next' +import supertokensNode from 'supertokens-node' +import * as SuperTokensConfig from '../../config/backendConfig' +import Session from 'supertokens-node/recipe/session' +import { fetchUserProfileFromId } from 'services/userService' +import { removeUnserializableFields } from 'utils' + +interface IProps { + user: UserProfile +} + +export const getServerSideProps: GetServerSideProps = async (context) => { + supertokensNode.init(SuperTokensConfig.backendConfig()) + let session + try { + session = await Session.getSession(context.req, context.res) + } catch (err: any) { + if (err.type === Session.Error.TRY_REFRESH_TOKEN) { + return { props: { fromSupertokens: 'needs-refresh' } } + } else if (err.type === Session.Error.UNAUTHORISED) { + return { props: {} } + } else { + throw err + } + } + + const user = await fetchUserProfileFromId(session.getUserId()) + + removeUnserializableFields(user) + + return { + props: { + user + } + } +} + +export default function Pro ({ user }: IProps): React.ReactElement { + const offeredMonths = Object.keys(config.proSettings.monthsCost) + const [selectedMonths, setSelectedMonths] = useState(null) + + const handleSelect = (months: string): void => { + setSelectedMonths(months) + } + + const renderLabel = (m: string): string => { + if (m === '1') return '1 month' + if (m === '12') return '1 year' + return `${m} months` + } + console.log('oia', user) + + return user === undefined + ? + : ( +
+

Choose your PRO plan

+
+ {offeredMonths.map((m) => { + const selected = selectedMonths === m + return ( +
handleSelect(m)} + className={`${style.card} ${selected ? style.selected : ''}`} + > +
{renderLabel(m)}
+
${config.proSettings.monthsCost[m]}
+
+ ) + })} +
+ + {selectedMonths !== null && ( +
+ +
+ )} +
+ ) +} diff --git a/pages/pro/pro.module.css b/pages/pro/pro.module.css new file mode 100644 index 000000000..d9390a90b --- /dev/null +++ b/pages/pro/pro.module.css @@ -0,0 +1,52 @@ +.container { + padding: 1rem; +} + +.heading { + font-size: 1.5rem; + font-weight: bold; + margin-bottom: 1rem; + text-align: center; +} + +.cardGrid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); + gap: 1rem; + margin-bottom: 1.5rem; +} + +.card { + border: 2px solid #ccc; + border-radius: 12px; + padding: 1rem; + text-align: center; + cursor: pointer; + transition: all 0.2s ease-in-out; +} + +.card:hover { + border-color: #fff; + background-color: #333; +} + +.selected { + border-color: #0070f3; + background-color: #8888f3; + transform: scale(1.05); +} + +.label { + font-size: 1.1rem; + font-weight: 600; +} + +.price { + font-size: 0.9rem; + margin-top: 0.5rem; +} + +.payButtonWrapper { + text-align: center; +} + diff --git a/prisma/migrations/20250604164641_pro_until_column/migration.sql b/prisma/migrations/20250604164641_pro_until_column/migration.sql new file mode 100644 index 000000000..16e745b7a --- /dev/null +++ b/prisma/migrations/20250604164641_pro_until_column/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE `UserProfile` ADD COLUMN `proUntil` DATETIME(3) NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6de5ee27b..cdfc7fa0c 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -171,6 +171,7 @@ model UserProfile { invoices Invoice[] preferredCurrencyId Int @default(1) preferredTimezone String @db.VarChar(255)@default("") + proUntil DateTime? organizationId String? organization Organization? @relation(fields: [organizationId], references: [id], onDelete: SetNull) diff --git a/services/userService.ts b/services/userService.ts index 671ac4eec..7d5d1425e 100644 --- a/services/userService.ts +++ b/services/userService.ts @@ -149,3 +149,17 @@ export async function updatePreferredTimezone (id: string, preferredTimezone: st } }) } + +export async function userRemainingProTime (id: string): Promise { + const today = new Date() + const proUntil = (await prisma.userProfile.findUniqueOrThrow({ + where: { id }, + select: { + proUntil: true + } + })).proUntil + if (proUntil === null) { + return null + } + return proUntil.getTime() - today.getTime() +} diff --git a/styles/global.css b/styles/global.css index b5012b77f..16028a18f 100644 --- a/styles/global.css +++ b/styles/global.css @@ -137,7 +137,7 @@ button:enabled:hover { } .paybutton-table-ctn tr:nth-child(even) { - background: none; + background-color: var(--primary-bg-color); } .paybutton-table-ctn thead th:first-child, diff --git a/tests/mockedObjects.ts b/tests/mockedObjects.ts index a989a800e..eae8728c3 100644 --- a/tests/mockedObjects.ts +++ b/tests/mockedObjects.ts @@ -526,7 +526,8 @@ export const mockedUserProfile: UserProfile = { lastSentVerificationEmailAt: null, preferredCurrencyId: 1, preferredTimezone: '', - emailCredits: 15 + emailCredits: 15, + proUntil: null } export const mockedUserProfileWithPublicKey: UserProfile = { @@ -539,7 +540,8 @@ export const mockedUserProfileWithPublicKey: UserProfile = { lastSentVerificationEmailAt: null, preferredCurrencyId: 1, preferredTimezone: '', - emailCredits: 15 + emailCredits: 15, + proUntil: null } export const mockedAddressesOnButtons: AddressesOnButtons[] = [ diff --git a/yarn.lock b/yarn.lock index 15bb3a8cc..9b779853f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1550,21 +1550,26 @@ fastq "^1.6.0" "@paybutton/react@latest": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@paybutton/react/-/react-2.0.0.tgz#38ab65cc55393a2cbee977e07cd982c9e9c6f1af" - integrity sha512-aoCHZag5QF7yhtBp3PBLkBQ6bw7Kc9kcZGeohs0M0s9HEE+kOPAS4BN9X7M3dn13C/w1yFHz3WaS+iwYmqumHA== + version "4.1.0" + resolved "https://registry.yarnpkg.com/@paybutton/react/-/react-4.1.0.tgz#f7ca742458fe6ef54fb0c9bc4234572083e2157e" + integrity sha512-qpN2N7QjV9BVUnPnj3OPV50B/AwRLfH40dJxnSFK+f0s+jrTKjiikjsI+7IVw2CfJ4z6wdKR2Ag1HCXDHepc6g== dependencies: "@material-ui/core" "4.12.4" "@material-ui/lab" "4.0.0-alpha.61" "@material-ui/styles" "4.11.5" - axios "0.21.4" + "@types/crypto-js" "^4.2.1" + "@types/jest" "^29.5.11" + axios "1.6.5" bignumber.js "9.0.2" - copy-to-clipboard "3.3.1" + copy-to-clipboard "3.3.3" + crypto-js "^4.2.0" + jest "^29.7.0" lodash "4.17.21" notistack "1.0.10" qrcode.react "1.0.1" - react-jss "10.9.0" - socket.io-client "^4.7.1" + react-jss "10.10.0" + socket.io-client "4.7.4" + ts-jest "^29.1.1" xecaddrjs "^0.0.1" "@prisma/client@^6.3.1": @@ -1786,6 +1791,11 @@ dependencies: "@types/node" "*" +"@types/crypto-js@^4.2.1": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-4.2.2.tgz#771c4a768d94eb5922cc202a3009558204df0cea" + integrity sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ== + "@types/engine.io@*": version "3.1.7" resolved "https://registry.npmjs.org/@types/engine.io/-/engine.io-3.1.7.tgz" @@ -1859,6 +1869,14 @@ jest-matcher-utils "^27.0.0" pretty-format "^27.0.0" +"@types/jest@^29.5.11": + version "29.5.14" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.14.tgz#2b910912fa1d6856cadcd0c1f95af7df1d6049e5" + integrity sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz" @@ -2399,12 +2417,14 @@ available-typed-arrays@^1.0.5: resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== -axios@0.21.4: - version "0.21.4" - resolved "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== +axios@1.6.5: + version "1.6.5" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.5.tgz#2c090da14aeeab3770ad30c3a1461bc970fb0cd8" + integrity sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg== dependencies: - follow-redirects "^1.14.0" + follow-redirects "^1.15.4" + form-data "^4.0.0" + proxy-from-env "^1.1.0" axios@^0.26.1: version "0.26.1" @@ -2801,7 +2821,7 @@ chronik-client-cashtokens@^3.1.1-rc0: dependencies: "@types/ws" "^8.2.1" axios "^1.6.3" - ecashaddrjs "file:../.cache/yarn/v6/npm-chronik-client-cashtokens-3.1.1-rc0-e5e4a3538e8010b70623974a731bf2712506c5e3-integrity/node_modules/ecashaddrjs" + ecashaddrjs "file:../../../.cache/yarn/v6/npm-chronik-client-cashtokens-3.1.1-rc0-e5e4a3538e8010b70623974a731bf2712506c5e3-integrity/node_modules/ecashaddrjs" isomorphic-ws "^4.0.1" protobufjs "^6.8.8" ws "^8.3.0" @@ -2984,10 +3004,10 @@ cookie@~0.4.1: resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== -copy-to-clipboard@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" - integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== +copy-to-clipboard@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" + integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA== dependencies: toggle-selection "^1.0.6" @@ -3069,14 +3089,19 @@ crypto-js@^4.1.1: resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== -css-jss@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/css-jss/-/css-jss-10.9.0.tgz#1595c67bacf651100984a05763c1170d1bfa7127" - integrity sha512-CpYclti5ZQ18PfAeXaHQ2bEw4DEUfjC0lTS9sQcUlTRF8hC/Va0h3DIowlRm6AH/Ka/O/+tp41Q5zn9MJQoRsA== +crypto-js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== + +css-jss@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/css-jss/-/css-jss-10.10.0.tgz#bd51fbd255cc24597ac0f0f32368394794d37ef3" + integrity sha512-YyMIS/LsSKEGXEaVJdjonWe18p4vXLo8CMA4FrW/kcaEyqdIGKCFXao31gbJddXEdIxSXFFURWrenBJPlKTgAA== dependencies: "@babel/runtime" "^7.3.1" - jss "10.9.0" - jss-preset-default "10.9.0" + jss "^10.10.0" + jss-preset-default "^10.10.0" css-vendor@^2.0.8: version "2.0.8" @@ -3268,7 +3293,7 @@ ecashaddrjs@^1.0.7: dependencies: big-integer "1.6.36" -ecashaddrjs@^2.0.0, "ecashaddrjs@file:../.cache/yarn/v6/npm-chronik-client-cashtokens-3.1.1-rc0-e5e4a3538e8010b70623974a731bf2712506c5e3-integrity/node_modules/ecashaddrjs": +ecashaddrjs@^2.0.0, "ecashaddrjs@file:../../../.cache/yarn/v6/npm-chronik-client-cashtokens-3.1.1-rc0-e5e4a3538e8010b70623974a731bf2712506c5e3-integrity/node_modules/ecashaddrjs": version "2.0.0" resolved "https://registry.yarnpkg.com/ecashaddrjs/-/ecashaddrjs-2.0.0.tgz#d45ede7fb6168815dbcf664b8e0a6872e485d874" integrity sha512-EvK1V4D3+nIEoD0ggy/b0F4lW39/72R9aOs/scm6kxMVuXu16btc+H74eQv7okNfXaQWKgolEekZkQ6wfcMMLw== @@ -3333,6 +3358,17 @@ engine.io-client@~6.5.1: ws "~8.11.0" xmlhttprequest-ssl "~2.0.0" +engine.io-client@~6.5.2: + version "6.5.4" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.5.4.tgz#b8bc71ed3f25d0d51d587729262486b4b33bd0d0" + integrity sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + engine.io-parser "~5.2.1" + ws "~8.17.1" + xmlhttprequest-ssl "~2.0.0" + engine.io-parser@~5.0.3: version "5.0.6" resolved "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz" @@ -3343,6 +3379,11 @@ engine.io-parser@~5.1.0: resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.1.0.tgz#d593d6372d7f79212df48f807b8cace1ea1cb1b8" integrity sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w== +engine.io-parser@~5.2.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.3.tgz#00dc5b97b1f233a23c9398d0209504cf5f94d92f" + integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q== + engine.io@~6.4.1: version "6.4.1" resolved "https://registry.npmjs.org/engine.io/-/engine.io-6.4.1.tgz" @@ -3724,7 +3765,7 @@ exit@^0.1.2: resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expect@^29.7.0: +expect@^29.0.0, expect@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== @@ -3880,11 +3921,16 @@ flatted@^3.1.0: resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== -follow-redirects@^1.14.0, follow-redirects@^1.14.8: +follow-redirects@^1.14.8: version "1.15.2" resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== +follow-redirects@^1.15.4: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + follow-redirects@^1.15.6: version "1.15.6" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" @@ -5032,16 +5078,7 @@ jsonwebtoken@^9.0.0: ms "^2.1.1" semver "^7.3.8" -jss-plugin-camel-case@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.9.0.tgz#4921b568b38d893f39736ee8c4c5f1c64670aaf7" - integrity sha512-UH6uPpnDk413/r/2Olmw4+y54yEF2lRIV8XIZyuYpgPYTITLlPOsq6XB9qeqv+75SQSg3KLocq5jUBXW8qWWww== - dependencies: - "@babel/runtime" "^7.3.1" - hyphenate-style-name "^1.0.3" - jss "10.9.0" - -jss-plugin-camel-case@^10.5.1: +jss-plugin-camel-case@10.10.0, jss-plugin-camel-case@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz#27ea159bab67eb4837fa0260204eb7925d4daa1c" integrity sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw== @@ -5050,24 +5087,16 @@ jss-plugin-camel-case@^10.5.1: hyphenate-style-name "^1.0.3" jss "10.10.0" -jss-plugin-compose@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-plugin-compose/-/jss-plugin-compose-10.9.0.tgz#4954583227db9b49bd2e29cd055dcc65b12cb19d" - integrity sha512-Q/0FEZhDwGUpf3/b7+PspmMi6MVSlN3YlTDmvrft7I6N346jUpd8MYkYP/6qM1ZMuVj4v8ky/XYqr1v2ganLLg== +jss-plugin-compose@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-compose/-/jss-plugin-compose-10.10.0.tgz#00d7a79adf7fcfe4927a792febdf0deceb0a7cd2" + integrity sha512-F5kgtWpI2XfZ3Z8eP78tZEYFdgTIbpA/TMuX3a8vwrNolYtN1N4qJR/Ob0LAsqIwCMLojtxN7c7Oo/+Vz6THow== dependencies: "@babel/runtime" "^7.3.1" - jss "10.9.0" + jss "10.10.0" tiny-warning "^1.0.2" -jss-plugin-default-unit@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.9.0.tgz#bb23a48f075bc0ce852b4b4d3f7582bc002df991" - integrity sha512-7Ju4Q9wJ/MZPsxfu4T84mzdn7pLHWeqoGd/D8O3eDNNJ93Xc8PxnLmV8s8ZPNRYkLdxZqKtm1nPQ0BM4JRlq2w== - dependencies: - "@babel/runtime" "^7.3.1" - jss "10.9.0" - -jss-plugin-default-unit@^10.5.1: +jss-plugin-default-unit@10.10.0, jss-plugin-default-unit@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz#db3925cf6a07f8e1dd459549d9c8aadff9804293" integrity sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ== @@ -5075,32 +5104,24 @@ jss-plugin-default-unit@^10.5.1: "@babel/runtime" "^7.3.1" jss "10.10.0" -jss-plugin-expand@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-plugin-expand/-/jss-plugin-expand-10.9.0.tgz#96c902f5759fe189184f8418997659d61e927ffe" - integrity sha512-QfZ9jld0HpF1OiYU7cGWQ4q+f6+Wu93mV4X+cA1iVRssiUbSbygwdfZkUwX23UOhS1WWRJeQlLK1aJC94K8/0A== +jss-plugin-expand@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-expand/-/jss-plugin-expand-10.10.0.tgz#5debd80554174ca2d9b9e38d85d4cb6f3e0393ab" + integrity sha512-ymT62W2OyDxBxr7A6JR87vVX9vTq2ep5jZLIdUSusfBIEENLdkkc0lL/Xaq8W9s3opUq7R0sZQpzRWELrfVYzA== dependencies: "@babel/runtime" "^7.3.1" - jss "10.9.0" + jss "10.10.0" -jss-plugin-extend@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-plugin-extend/-/jss-plugin-extend-10.9.0.tgz#b1163ceb25d908888b326e5b5fa780aaaed4884d" - integrity sha512-xvmosUh3RsKVsm9L14ml6PL3i0Ejj5gB6eo/jTMkGW1kIy42gNXV1EthR8cD5xiowWstnvugQ3JF0pI5+QkPMg== +jss-plugin-extend@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-extend/-/jss-plugin-extend-10.10.0.tgz#94eb450847a8941777e77ea4533a579c1c578430" + integrity sha512-sKYrcMfr4xxigmIwqTjxNcHwXJIfvhvjTNxF+Tbc1NmNdyspGW47Ey6sGH8BcQ4FFQhLXctpWCQSpDwdNmXSwg== dependencies: "@babel/runtime" "^7.3.1" - jss "10.9.0" + jss "10.10.0" tiny-warning "^1.0.2" -jss-plugin-global@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.9.0.tgz#fc07a0086ac97aca174e37edb480b69277f3931f" - integrity sha512-4G8PHNJ0x6nwAFsEzcuVDiBlyMsj2y3VjmFAx/uHk/R/gzJV+yRHICjT4MKGGu1cJq2hfowFWCyrr/Gg37FbgQ== - dependencies: - "@babel/runtime" "^7.3.1" - jss "10.9.0" - -jss-plugin-global@^10.5.1: +jss-plugin-global@10.10.0, jss-plugin-global@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz#1c55d3c35821fab67a538a38918292fc9c567efd" integrity sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A== @@ -5108,16 +5129,7 @@ jss-plugin-global@^10.5.1: "@babel/runtime" "^7.3.1" jss "10.10.0" -jss-plugin-nested@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.9.0.tgz#cc1c7d63ad542c3ccc6e2c66c8328c6b6b00f4b3" - integrity sha512-2UJnDrfCZpMYcpPYR16oZB7VAC6b/1QLsRiAutOt7wJaaqwCBvNsosLEu/fUyKNQNGdvg2PPJFDO5AX7dwxtoA== - dependencies: - "@babel/runtime" "^7.3.1" - jss "10.9.0" - tiny-warning "^1.0.2" - -jss-plugin-nested@^10.5.1: +jss-plugin-nested@10.10.0, jss-plugin-nested@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz#db872ed8925688806e77f1fc87f6e62264513219" integrity sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA== @@ -5126,15 +5138,7 @@ jss-plugin-nested@^10.5.1: jss "10.10.0" tiny-warning "^1.0.2" -jss-plugin-props-sort@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.9.0.tgz#30e9567ef9479043feb6e5e59db09b4de687c47d" - integrity sha512-7A76HI8bzwqrsMOJTWKx/uD5v+U8piLnp5bvru7g/3ZEQOu1+PjHvv7bFdNO3DwNPC9oM0a//KwIJsIcDCjDzw== - dependencies: - "@babel/runtime" "^7.3.1" - jss "10.9.0" - -jss-plugin-props-sort@^10.5.1: +jss-plugin-props-sort@10.10.0, jss-plugin-props-sort@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz#67f4dd4c70830c126f4ec49b4b37ccddb680a5d7" integrity sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg== @@ -5142,16 +5146,7 @@ jss-plugin-props-sort@^10.5.1: "@babel/runtime" "^7.3.1" jss "10.10.0" -jss-plugin-rule-value-function@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.9.0.tgz#379fd2732c0746fe45168011fe25544c1a295d67" - integrity sha512-IHJv6YrEf8pRzkY207cPmdbBstBaE+z8pazhPShfz0tZSDtRdQua5jjg6NMz3IbTasVx9FdnmptxPqSWL5tyJg== - dependencies: - "@babel/runtime" "^7.3.1" - jss "10.9.0" - tiny-warning "^1.0.2" - -jss-plugin-rule-value-function@^10.5.1: +jss-plugin-rule-value-function@10.10.0, jss-plugin-rule-value-function@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz#7d99e3229e78a3712f78ba50ab342e881d26a24b" integrity sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g== @@ -5160,34 +5155,25 @@ jss-plugin-rule-value-function@^10.5.1: jss "10.10.0" tiny-warning "^1.0.2" -jss-plugin-rule-value-observable@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-observable/-/jss-plugin-rule-value-observable-10.9.0.tgz#fc48b70f6915a913618fdadb44dedce23982b32d" - integrity sha512-/MWVPJVEn41+ofzQdsvH1GR4wusDqFqNnchh/98HVc580MxPy4NVkmUa2SAEpbHhnJ93sCoETZccW3HJKuvH4A== +jss-plugin-rule-value-observable@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-observable/-/jss-plugin-rule-value-observable-10.10.0.tgz#d17b28c4401156bbe4cd0c4a73a80aad70613e8b" + integrity sha512-ZLMaYrR3QE+vD7nl3oNXuj79VZl9Kp8/u6A1IbTPDcuOu8b56cFdWRZNZ0vNr8jHewooEeq2doy8Oxtymr2ZPA== dependencies: "@babel/runtime" "^7.3.1" - jss "10.9.0" + jss "10.10.0" symbol-observable "^1.2.0" -jss-plugin-template@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-plugin-template/-/jss-plugin-template-10.9.0.tgz#27547e093e04b9dc9e900f35146e874bb196f575" - integrity sha512-lxThUvdt0drCi7xhuJWxADWTgLLy1IWCeFO5k+dtba900xJsNg0IGZplpP9w9UpaJsYS3WUwWMXw8Sxn1dobfQ== +jss-plugin-template@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-template/-/jss-plugin-template-10.10.0.tgz#072cda74a94c91b02d3a895d9e2408fd978ce033" + integrity sha512-ocXZBIOJOA+jISPdsgkTs8wwpK6UbsvtZK5JI7VUggTD6LWKbtoxUzadd2TpfF+lEtlhUmMsCkTRNkITdPKa6w== dependencies: "@babel/runtime" "^7.3.1" - jss "10.9.0" + jss "10.10.0" tiny-warning "^1.0.2" -jss-plugin-vendor-prefixer@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.9.0.tgz#aa9df98abfb3f75f7ed59a3ec50a5452461a206a" - integrity sha512-MbvsaXP7iiVdYVSEoi+blrW+AYnTDvHTW6I6zqi7JcwXdc6I9Kbm234nEblayhF38EftoenbM+5218pidmC5gA== - dependencies: - "@babel/runtime" "^7.3.1" - css-vendor "^2.0.8" - jss "10.9.0" - -jss-plugin-vendor-prefixer@^10.5.1: +jss-plugin-vendor-prefixer@10.10.0, jss-plugin-vendor-prefixer@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz#c01428ef5a89f2b128ec0af87a314d0c767931c7" integrity sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg== @@ -5196,27 +5182,27 @@ jss-plugin-vendor-prefixer@^10.5.1: css-vendor "^2.0.8" jss "10.10.0" -jss-preset-default@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss-preset-default/-/jss-preset-default-10.9.0.tgz#20919ee04e543b3502086001c4179ab15c012153" - integrity sha512-Zdsj+R+UTn7OOJ1TFQi+l8PfEL7APSAM6vRPaU8mJywT8OrMjgslMKckFLrgq1k+qk1hJR1ePAMesvZ5aAXGOQ== +jss-preset-default@10.10.0, jss-preset-default@^10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-preset-default/-/jss-preset-default-10.10.0.tgz#c8209449a0f6d232526c2ba3a3a6ec69ee97e023" + integrity sha512-GL175Wt2FGhjE+f+Y3aWh+JioL06/QWFgZp53CbNNq6ZkVU0TDplD8Bxm9KnkotAYn3FlplNqoW5CjyLXcoJ7Q== dependencies: "@babel/runtime" "^7.3.1" - jss "10.9.0" - jss-plugin-camel-case "10.9.0" - jss-plugin-compose "10.9.0" - jss-plugin-default-unit "10.9.0" - jss-plugin-expand "10.9.0" - jss-plugin-extend "10.9.0" - jss-plugin-global "10.9.0" - jss-plugin-nested "10.9.0" - jss-plugin-props-sort "10.9.0" - jss-plugin-rule-value-function "10.9.0" - jss-plugin-rule-value-observable "10.9.0" - jss-plugin-template "10.9.0" - jss-plugin-vendor-prefixer "10.9.0" - -jss@10.10.0, jss@^10.5.1: + jss "10.10.0" + jss-plugin-camel-case "10.10.0" + jss-plugin-compose "10.10.0" + jss-plugin-default-unit "10.10.0" + jss-plugin-expand "10.10.0" + jss-plugin-extend "10.10.0" + jss-plugin-global "10.10.0" + jss-plugin-nested "10.10.0" + jss-plugin-props-sort "10.10.0" + jss-plugin-rule-value-function "10.10.0" + jss-plugin-rule-value-observable "10.10.0" + jss-plugin-template "10.10.0" + jss-plugin-vendor-prefixer "10.10.0" + +jss@10.10.0, jss@^10.10.0, jss@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss/-/jss-10.10.0.tgz#a75cc85b0108c7ac8c7b7d296c520a3e4fbc6ccc" integrity sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw== @@ -5226,16 +5212,6 @@ jss@10.10.0, jss@^10.5.1: is-in-browser "^1.1.3" tiny-warning "^1.0.2" -jss@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/jss/-/jss-10.9.0.tgz#7583ee2cdc904a83c872ba695d1baab4b59c141b" - integrity sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw== - dependencies: - "@babel/runtime" "^7.3.1" - csstype "^3.0.2" - is-in-browser "^1.1.3" - tiny-warning "^1.0.2" - jwa@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" @@ -6004,7 +5980,7 @@ pretty-format@^27.0.0, pretty-format@^27.5.1: ansi-styles "^5.0.0" react-is "^17.0.1" -pretty-format@^29.7.0: +pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== @@ -6218,18 +6194,18 @@ react-is@^18.0.0: resolved "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== -react-jss@10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/react-jss/-/react-jss-10.9.0.tgz#102332a109d98510f0f812dd090d02f6045b5229" - integrity sha512-xKXTEejrSkzINF+dutFtLllIfYSN6tOA1XmnpiZGjsWZqy7Hum6fjjgAE2TbBmV9h2CW62ekmGj/Mx27ZuMjuw== +react-jss@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/react-jss/-/react-jss-10.10.0.tgz#d08ab3257b0eed01e15d6d8275840055c279b0da" + integrity sha512-WLiq84UYWqNBF6579/uprcIUnM1TSywYq6AIjKTTTG5ziJl9Uy+pwuvpN3apuyVwflMbD60PraeTKT7uWH9XEQ== dependencies: "@babel/runtime" "^7.3.1" "@emotion/is-prop-valid" "^0.7.3" - css-jss "10.9.0" + css-jss "10.10.0" hoist-non-react-statics "^3.2.0" is-in-browser "^1.1.3" - jss "10.9.0" - jss-preset-default "10.9.0" + jss "10.10.0" + jss-preset-default "10.10.0" prop-types "^15.6.0" shallow-equal "^1.2.0" theming "^3.3.0" @@ -6512,6 +6488,11 @@ semver@^7.5.3, semver@^7.5.4, semver@^7.6.3: resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +semver@^7.7.2: + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== + semver@~7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" @@ -6660,6 +6641,16 @@ socket.io-adapter@~2.5.2: dependencies: ws "~8.11.0" +socket.io-client@4.7.4: + version "4.7.4" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.7.4.tgz#5f0e060ff34ac0a4b4c5abaaa88e0d1d928c64c8" + integrity sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.2" + engine.io-client "~6.5.2" + socket.io-parser "~4.2.4" + socket.io-client@^4.7.1: version "4.7.1" resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.7.1.tgz#48e5f703abe4fb0402182bcf9c06b7820fb3453b" @@ -7064,6 +7055,21 @@ ts-essentials@^7.0.3: resolved "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz" integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== +ts-jest@^29.1.1: + version "29.4.0" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.4.0.tgz#bef0ee98d94c83670af7462a1617bf2367a83740" + integrity sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q== + dependencies: + bs-logger "^0.2.6" + ejs "^3.1.10" + fast-json-stable-stringify "^2.1.0" + json5 "^2.2.3" + lodash.memoize "^4.1.2" + make-error "^1.3.6" + semver "^7.7.2" + type-fest "^4.41.0" + yargs-parser "^21.1.1" + ts-jest@^29.2.5: version "29.2.5" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.2.5.tgz#591a3c108e1f5ebd013d3152142cb5472b399d63" @@ -7164,6 +7170,11 @@ type-fest@^0.21.3: resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +type-fest@^4.41.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" + integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== + type-is@^1.6.18, type-is@~1.6.18: version "1.6.18" resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" @@ -7401,6 +7412,11 @@ ws@~8.11.0: resolved "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz" integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== +ws@~8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + xecaddrjs@^0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/xecaddrjs/-/xecaddrjs-0.0.1.tgz"