From 6d3ef6c5bc279bdc8d927deb1edfef94b6f3033a Mon Sep 17 00:00:00 2001 From: Dawid Sowa Date: Mon, 23 Sep 2024 18:46:17 +0200 Subject: [PATCH 01/45] feat: bump valibot version Check https://valibot.dev/guides/migrate-to-v0.31.0/ if you were using valibot for types creation --- package-lock.json | 18 +- packages/dapp-toolkit/package.json | 2 +- .../src/helpers/validate-wallet-response.ts | 2 +- .../dapp-toolkit/src/modules/state/types.ts | 16 +- .../data-request/builders/accounts.ts | 4 +- .../data-request/builders/persona-data.ts | 4 +- .../data-request/builders/persona.ts | 4 +- .../transformations/rdt-to-wallet.ts | 4 +- packages/dapp-toolkit/src/schemas/index.ts | 214 +++++++++--------- 9 files changed, 136 insertions(+), 132 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1e79b74c..805531bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30964,7 +30964,7 @@ "version": "5.4.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -31370,9 +31370,17 @@ "dev": true }, "node_modules/valibot": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/valibot/-/valibot-0.30.0.tgz", - "integrity": "sha512-5POBdbSkM+3nvJ6ZlyQHsggisfRtyT4tVTo1EIIShs6qCdXJnyWU5TJ68vr8iTg5zpOLjXLRiBqNx+9zwZz/rA==" + "version": "0.42.1", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-0.42.1.tgz", + "integrity": "sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw==", + "peerDependencies": { + "typescript": ">=5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } }, "node_modules/validate-npm-package-license": { "version": "3.0.4", @@ -33571,7 +33579,7 @@ "rxjs": "^7.8.1", "tslog": ">=4.8.0", "uuid": "^10.0.0", - "valibot": "0.30.0" + "valibot": "0.42.1" }, "devDependencies": { "@radixdlt/connect-button": "*", diff --git a/packages/dapp-toolkit/package.json b/packages/dapp-toolkit/package.json index 0950c18d..6d8356c4 100644 --- a/packages/dapp-toolkit/package.json +++ b/packages/dapp-toolkit/package.json @@ -72,7 +72,7 @@ "rxjs": "^7.8.1", "tslog": ">=4.8.0", "uuid": "^10.0.0", - "valibot": "0.30.0" + "valibot": "0.42.1" }, "devDependencies": { "@radixdlt/connect-button": "*", diff --git a/packages/dapp-toolkit/src/helpers/validate-wallet-response.ts b/packages/dapp-toolkit/src/helpers/validate-wallet-response.ts index e9f8f072..eb78cd16 100644 --- a/packages/dapp-toolkit/src/helpers/validate-wallet-response.ts +++ b/packages/dapp-toolkit/src/helpers/validate-wallet-response.ts @@ -11,7 +11,7 @@ export const validateWalletResponse = ( ): ResultAsync => { const fn = Result.fromThrowable( (_) => parse(WalletInteractionResponse, _), - (error) => error as ValiError, + (error) => error as ValiError, ) const result = fn(walletResponse) diff --git a/packages/dapp-toolkit/src/modules/state/types.ts b/packages/dapp-toolkit/src/modules/state/types.ts index 39b429e7..3278ca54 100644 --- a/packages/dapp-toolkit/src/modules/state/types.ts +++ b/packages/dapp-toolkit/src/modules/state/types.ts @@ -14,7 +14,7 @@ import { object, variant, string, - Output, + InferOutput, } from 'valibot' export const proofType = { @@ -22,7 +22,7 @@ export const proofType = { account: 'account', } as const -export type SignedChallengePersona = Output +export type SignedChallengePersona = InferOutput export const SignedChallengePersona = object({ challenge: string(), proof: Proof, @@ -30,7 +30,7 @@ export const SignedChallengePersona = object({ type: literal(proofType.persona), }) -export type SignedChallengeAccount = Output +export type SignedChallengeAccount = InferOutput export const SignedChallengeAccount = object({ challenge: string(), proof: Proof, @@ -38,7 +38,7 @@ export const SignedChallengeAccount = object({ type: literal(proofType.account), }) -export type SignedChallenge = Output +export type SignedChallenge = InferOutput export const SignedChallenge = variant('type', [ SignedChallengePersona, SignedChallengeAccount, @@ -59,14 +59,14 @@ export const WalletDataPersonaDataPhoneNumbersAddresses = object({ fields: array(string()), }) -export type WalletDataPersonaData = Output +export type WalletDataPersonaData = InferOutput export const WalletDataPersonaData = variant('entry', [ WalletDataPersonaDataFullName, WalletDataPersonaDataEmailAddresses, WalletDataPersonaDataPhoneNumbersAddresses, ]) -export type WalletData = Output +export type WalletData = InferOutput export const WalletData = object({ accounts: array(Account), personaData: array(WalletDataPersonaData), @@ -74,7 +74,7 @@ export const WalletData = object({ proofs: array(SignedChallenge), }) -export type SharedData = Output +export type SharedData = InferOutput export const SharedData = object({ persona: optional(object({ proof: boolean() })), ongoingAccounts: optional( @@ -86,7 +86,7 @@ export const SharedData = object({ ongoingPersonaData: optional(PersonaDataRequestItem), }) -export type RdtState = Output +export type RdtState = InferOutput export const RdtState = object({ loggedInTimestamp: string(), walletData: WalletData, diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/accounts.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/accounts.ts index 4718b8fc..9406740e 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/accounts.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/accounts.ts @@ -1,5 +1,5 @@ import { produce } from 'immer' -import { boolean, object, Output, optional } from 'valibot' +import { boolean, object, InferOutput, optional } from 'valibot' import { NumberOfValues } from '../../../../schemas' export type AccountsRequestBuilder = { @@ -13,7 +13,7 @@ export type OneTimeAccountsRequestBuilder = { exactly: (n: number) => OneTimeAccountsRequestBuilder withProof: (value?: boolean) => OneTimeAccountsRequestBuilder } -export type AccountsDataRequest = Output +export type AccountsDataRequest = InferOutput export const AccountsDataRequestSchema = object({ numberOfAccounts: NumberOfValues, diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/persona-data.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/persona-data.ts index e9ca6f1f..85b1a07f 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/persona-data.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/persona-data.ts @@ -1,5 +1,5 @@ import { produce } from 'immer' -import { boolean, object, Output, partial } from 'valibot' +import { boolean, object, InferOutput, partial } from 'valibot' import { NumberOfValues } from '../../../../schemas' export type PersonaDataRequestBuilder = { @@ -13,7 +13,7 @@ export type OneTimePersonaDataRequestBuilder = { emailAddresses: (value?: boolean) => PersonaDataRequestBuilder phoneNumbers: (value?: boolean) => PersonaDataRequestBuilder } -export type PersonaDataRequest = Output +export type PersonaDataRequest = InferOutput export const PersonaDataRequestSchema = partial( object({ diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/persona.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/persona.ts index 13247fe5..3279fd3d 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/persona.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/persona.ts @@ -1,10 +1,10 @@ import { produce } from 'immer' -import { boolean, object, Output, optional } from 'valibot' +import { boolean, object, InferOutput, optional } from 'valibot' export type PersonaRequestBuilder = { withProof: (value?: boolean) => PersonaRequestBuilder } -export type PersonaRequest = Output +export type PersonaRequest = InferOutput const schema = object({ withProof: optional(boolean()), diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts index 3e75be74..7aa4d6aa 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts @@ -9,9 +9,9 @@ import { NumberOfValues } from '../../../../schemas' import { produce } from 'immer' import type { Result } from 'neverthrow' import { ok } from 'neverthrow' -import { boolean, object, string, Output, optional } from 'valibot' +import { boolean, object, string, InferOutput, optional } from 'valibot' -export type TransformRdtDataRequestToWalletRequestInput = Output< +export type TransformRdtDataRequestToWalletRequestInput = InferOutput< typeof TransformRdtDataRequestToWalletRequestInput > export const TransformRdtDataRequestToWalletRequestInput = object({ diff --git a/packages/dapp-toolkit/src/schemas/index.ts b/packages/dapp-toolkit/src/schemas/index.ts index 5ee3f8a1..a72732df 100644 --- a/packages/dapp-toolkit/src/schemas/index.ts +++ b/packages/dapp-toolkit/src/schemas/index.ts @@ -9,50 +9,50 @@ import { minValue, string, union, - merge, - Output, + InferOutput, ValiError, - custom, + check, + pipe, } from 'valibot' /** * Wallet schemas */ -export type Account = Output +export type Account = InferOutput export const Account = object({ address: string(), label: string(), appearanceId: number(), }) -export type Proof = Output +export type Proof = InferOutput export const Proof = object({ publicKey: string(), signature: string(), curve: union([literal('curve25519'), literal('secp256k1')]), }) -export type AccountProof = Output +export type AccountProof = InferOutput export const AccountProof = object({ accountAddress: string(), proof: Proof, }) -export type Persona = Output +export type Persona = InferOutput export const Persona = object({ identityAddress: string(), label: string() }) export const personaDataFullNameVariant = { western: 'western', eastern: 'eastern', } as const -export type PersonaDataNameVariant = Output +export type PersonaDataNameVariant = InferOutput export const PersonaDataNameVariant = union([ literal(personaDataFullNameVariant.eastern), literal(personaDataFullNameVariant.western), ]) -export type PersonaDataName = Output +export type PersonaDataName = InferOutput export const PersonaDataName = object({ variant: PersonaDataNameVariant, familyName: string(), @@ -60,45 +60,43 @@ export const PersonaDataName = object({ givenNames: string(), }) -export type NumberOfValues = Output +export type NumberOfValues = InferOutput export const NumberOfValues = object({ quantifier: union([literal('exactly'), literal('atLeast')]), - quantity: number([minValue(0, 'The number must be at least 0.')]), + quantity: pipe(number(), minValue(0, 'The number must be at least 0.')), }) -export type AccountsRequestItem = Output +export type AccountsRequestItem = InferOutput export const AccountsRequestItem = object({ challenge: optional(string()), numberOfAccounts: NumberOfValues, }) -export type AccountsRequestResponseItem = Output< +export type AccountsRequestResponseItem = InferOutput< typeof AccountsRequestResponseItem > -export const AccountsRequestResponseItem = object( - { +export const AccountsRequestResponseItem = pipe( + object({ accounts: array(Account), challenge: optional(string()), proofs: optional(array(AccountProof)), - }, - [ - custom((data) => { - if (data.challenge || data?.proofs) { - return !!(data.challenge && data?.proofs?.length) - } - return true - }, 'missing challenge or proofs'), - ], + }), + check((data) => { + if (data.challenge || data?.proofs) { + return !!(data.challenge && data?.proofs?.length) + } + return true + }, 'missing challenge or proofs'), ) -export type PersonaDataRequestItem = Output +export type PersonaDataRequestItem = InferOutput export const PersonaDataRequestItem = object({ isRequestingName: optional(boolean()), numberOfRequestedEmailAddresses: optional(NumberOfValues), numberOfRequestedPhoneNumbers: optional(NumberOfValues), }) -export type PersonaDataRequestResponseItem = Output< +export type PersonaDataRequestResponseItem = InferOutput< typeof PersonaDataRequestResponseItem > export const PersonaDataRequestResponseItem = object({ @@ -107,30 +105,30 @@ export const PersonaDataRequestResponseItem = object({ phoneNumbers: optional(array(string())), }) -export type ResetRequestItem = Output +export type ResetRequestItem = InferOutput export const ResetRequestItem = object({ accounts: boolean(), personaData: boolean(), }) -export type LoginRequestResponseItem = Output -export const LoginRequestResponseItem = object( - { +export type LoginRequestResponseItem = InferOutput< + typeof LoginRequestResponseItem +> +export const LoginRequestResponseItem = pipe( + object({ persona: Persona, challenge: optional(string()), proof: optional(Proof), - }, - [ - custom((data) => { - if (data.challenge || data.proof) { - return !!(data.challenge && data.proof) - } - return true - }, 'missing challenge or proof'), - ], + }), + check((data) => { + if (data.challenge || data.proof) { + return !!(data.challenge && data.proof) + } + return true + }, 'missing challenge or proof'), ) -export type WalletUnauthorizedRequestItems = Output< +export type WalletUnauthorizedRequestItems = InferOutput< typeof WalletUnauthorizedRequestItems > export const WalletUnauthorizedRequestItems = object({ @@ -139,20 +137,22 @@ export const WalletUnauthorizedRequestItems = object({ oneTimePersonaData: optional(PersonaDataRequestItem), }) -export type AuthUsePersonaRequestItem = Output +export type AuthUsePersonaRequestItem = InferOutput< + typeof AuthUsePersonaRequestItem +> export const AuthUsePersonaRequestItem = object({ discriminator: literal('usePersona'), identityAddress: string(), }) -export type AuthLoginWithoutChallengeRequestItem = Output< +export type AuthLoginWithoutChallengeRequestItem = InferOutput< typeof AuthLoginWithoutChallengeRequestItem > export const AuthLoginWithoutChallengeRequestItem = object({ discriminator: literal('loginWithoutChallenge'), }) -export type AuthLoginWithChallengeRequestItem = Output< +export type AuthLoginWithChallengeRequestItem = InferOutput< typeof AuthLoginWithChallengeRequestItem > export const AuthLoginWithChallengeRequestItem = object({ @@ -169,7 +169,7 @@ export const AuthRequestItem = union([ AuthLoginRequestItem, ]) -export type WalletAuthorizedRequestItems = Output< +export type WalletAuthorizedRequestItems = InferOutput< typeof WalletAuthorizedRequestItems > export const WalletAuthorizedRequestItems = object({ @@ -182,13 +182,13 @@ export const WalletAuthorizedRequestItems = object({ ongoingPersonaData: optional(PersonaDataRequestItem), }) -export type WalletRequestItems = Output +export type WalletRequestItems = InferOutput export const WalletRequestItems = union([ WalletUnauthorizedRequestItems, WalletAuthorizedRequestItems, ]) -export type SendTransactionItem = Output +export type SendTransactionItem = InferOutput export const SendTransactionItem = object({ transactionManifest: string(), version: number(), @@ -196,20 +196,20 @@ export const SendTransactionItem = object({ message: optional(string()), }) -export type WalletTransactionItems = Output +export type WalletTransactionItems = InferOutput export const WalletTransactionItems = object({ discriminator: literal('transaction'), send: SendTransactionItem, }) -export type SendTransactionResponseItem = Output< +export type SendTransactionResponseItem = InferOutput< typeof SendTransactionResponseItem > export const SendTransactionResponseItem = object({ transactionIntentHash: string(), }) -export type WalletTransactionResponseItems = Output< +export type WalletTransactionResponseItems = InferOutput< typeof WalletTransactionResponseItems > const WalletTransactionResponseItems = object({ @@ -217,19 +217,19 @@ const WalletTransactionResponseItems = object({ send: SendTransactionResponseItem, }) -export type CancelRequest = Output +export type CancelRequest = InferOutput export const CancelRequest = object({ discriminator: literal('cancelRequest'), }) -export type WalletInteractionItems = Output +export type WalletInteractionItems = InferOutput export const WalletInteractionItems = union([ WalletRequestItems, WalletTransactionItems, CancelRequest, ]) -export type Metadata = Output +export type Metadata = InferOutput export const Metadata = object({ version: literal(2), networkId: number(), @@ -237,14 +237,14 @@ export const Metadata = object({ origin: string(), }) -export type WalletInteraction = Output +export type WalletInteraction = InferOutput export const WalletInteraction = object({ interactionId: string(), metadata: Metadata, items: WalletInteractionItems, }) -export type WalletUnauthorizedRequestResponseItems = Output< +export type WalletUnauthorizedRequestResponseItems = InferOutput< typeof WalletUnauthorizedRequestResponseItems > const WalletUnauthorizedRequestResponseItems = object({ @@ -253,7 +253,7 @@ const WalletUnauthorizedRequestResponseItems = object({ oneTimePersonaData: optional(PersonaDataRequestResponseItem), }) -export type AuthLoginWithoutChallengeRequestResponseItem = Output< +export type AuthLoginWithoutChallengeRequestResponseItem = InferOutput< typeof AuthLoginWithoutChallengeRequestResponseItem > export const AuthLoginWithoutChallengeRequestResponseItem = object({ @@ -261,7 +261,7 @@ export const AuthLoginWithoutChallengeRequestResponseItem = object({ persona: Persona, }) -export type AuthLoginWithChallengeRequestResponseItem = Output< +export type AuthLoginWithChallengeRequestResponseItem = InferOutput< typeof AuthLoginWithChallengeRequestResponseItem > export const AuthLoginWithChallengeRequestResponseItem = object({ @@ -276,7 +276,7 @@ export const AuthLoginRequestResponseItem = union([ AuthLoginWithChallengeRequestResponseItem, ]) -export type AuthUsePersonaRequestResponseItem = Output< +export type AuthUsePersonaRequestResponseItem = InferOutput< typeof AuthUsePersonaRequestResponseItem > const AuthUsePersonaRequestResponseItem = object({ @@ -284,13 +284,15 @@ const AuthUsePersonaRequestResponseItem = object({ persona: Persona, }) -export type AuthRequestResponseItem = Output +export type AuthRequestResponseItem = InferOutput< + typeof AuthRequestResponseItem +> export const AuthRequestResponseItem = union([ AuthUsePersonaRequestResponseItem, AuthLoginRequestResponseItem, ]) -export type WalletAuthorizedRequestResponseItems = Output< +export type WalletAuthorizedRequestResponseItems = InferOutput< typeof WalletAuthorizedRequestResponseItems > export const WalletAuthorizedRequestResponseItems = object({ @@ -302,7 +304,7 @@ export const WalletAuthorizedRequestResponseItems = object({ ongoingPersonaData: optional(PersonaDataRequestResponseItem), }) -export type WalletRequestResponseItems = Output< +export type WalletRequestResponseItems = InferOutput< typeof WalletRequestResponseItems > export const WalletRequestResponseItems = union([ @@ -310,7 +312,7 @@ export const WalletRequestResponseItems = union([ WalletAuthorizedRequestResponseItems, ]) -export type WalletInteractionResponseItems = Output< +export type WalletInteractionResponseItems = InferOutput< typeof WalletInteractionResponseItems > const WalletInteractionResponseItems = union([ @@ -318,7 +320,7 @@ const WalletInteractionResponseItems = union([ WalletTransactionResponseItems, ]) -export type WalletInteractionSuccessResponse = Output< +export type WalletInteractionSuccessResponse = InferOutput< typeof WalletInteractionSuccessResponse > export const WalletInteractionSuccessResponse = object({ @@ -327,7 +329,7 @@ export const WalletInteractionSuccessResponse = object({ items: WalletInteractionResponseItems, }) -export type WalletInteractionFailureResponse = Output< +export type WalletInteractionFailureResponse = InferOutput< typeof WalletInteractionFailureResponse > export const WalletInteractionFailureResponse = object({ @@ -337,7 +339,9 @@ export const WalletInteractionFailureResponse = object({ message: optional(string()), }) -export type WalletInteractionResponse = Output +export type WalletInteractionResponse = InferOutput< + typeof WalletInteractionResponse +> export const WalletInteractionResponse = union([ WalletInteractionSuccessResponse, WalletInteractionFailureResponse, @@ -355,7 +359,7 @@ export const StatusExtensionInteraction = object({ discriminator: literal(extensionInteractionDiscriminator.extensionStatus), }) -export type StatusExtensionInteraction = Output< +export type StatusExtensionInteraction = InferOutput< typeof StatusExtensionInteraction > @@ -364,11 +368,11 @@ export const OpenPopupExtensionInteraction = object({ discriminator: literal(extensionInteractionDiscriminator.openPopup), }) -export type OpenPopupExtensionInteraction = Output< +export type OpenPopupExtensionInteraction = InferOutput< typeof OpenPopupExtensionInteraction > -export type WalletInteractionExtensionInteraction = Output< +export type WalletInteractionExtensionInteraction = InferOutput< typeof WalletInteractionExtensionInteraction > @@ -379,7 +383,7 @@ export const WalletInteractionExtensionInteraction = object({ sessionId: optional(string()), }) -export type CancelWalletInteractionExtensionInteraction = Output< +export type CancelWalletInteractionExtensionInteraction = InferOutput< typeof CancelWalletInteractionExtensionInteraction > @@ -398,7 +402,7 @@ export const ExtensionInteraction = union([ CancelWalletInteractionExtensionInteraction, ]) -export type ExtensionInteraction = Output +export type ExtensionInteraction = InferOutput export const messageLifeCycleEventType = { extensionStatus: 'extensionStatus', @@ -416,7 +420,7 @@ export const MessageLifeCycleExtensionStatusEvent = object({ canHandleSessions: optional(boolean()), }) -export type MessageLifeCycleExtensionStatusEvent = Output< +export type MessageLifeCycleExtensionStatusEvent = InferOutput< typeof MessageLifeCycleExtensionStatusEvent > @@ -431,9 +435,9 @@ export const MessageLifeCycleEvent = object({ interactionId: string(), }) -export type MessageLifeCycleEvent = Output +export type MessageLifeCycleEvent = InferOutput -export type IncomingMessage = Output +export type IncomingMessage = InferOutput const IncomingMessage = union([ MessageLifeCycleEvent, WalletInteractionResponse, @@ -476,25 +480,21 @@ export const SignalingServerMessage = object({ connectionId: optional(string()), // redundant, to be removed }) -export const AnswerIO = merge([ - SignalingServerMessage, - object({ - method: Answer, - payload: object({ - sdp: string(), - }), +export const AnswerIO = object({ + ...SignalingServerMessage.entries, + method: Answer, + payload: object({ + sdp: string(), }), -]) +}) -export const OfferIO = merge([ - SignalingServerMessage, - object({ - method: Offer, - payload: object({ - sdp: string(), - }), +export const OfferIO = object({ + ...SignalingServerMessage.entries, + method: Offer, + payload: object({ + sdp: string(), }), -]) +}) export const IceCandidatePayloadIO = object({ candidate: string(), @@ -502,28 +502,24 @@ export const IceCandidatePayloadIO = object({ sdpMLineIndex: number(), }) -export const IceCandidateIO = merge([ - SignalingServerMessage, - object({ - method: IceCandidate, - payload: IceCandidatePayloadIO, - }), -]) +export const IceCandidateIO = object({ + ...SignalingServerMessage.entries, + method: IceCandidate, + payload: IceCandidatePayloadIO, +}) -export const IceCandidatesIO = merge([ - SignalingServerMessage, - object({ - method: IceCandidates, - payload: array(IceCandidatePayloadIO), - }), -]) +export const IceCandidatesIO = object({ + ...SignalingServerMessage.entries, + method: IceCandidates, + payload: array(IceCandidatePayloadIO), +}) -export type Answer = Output -export type Offer = Output -export type IceCandidate = Output -export type IceCandidates = Output -export type MessagePayloadTypes = Output -export type MessageSources = Output +export type Answer = InferOutput +export type Offer = InferOutput +export type IceCandidate = InferOutput +export type IceCandidates = InferOutput +export type MessagePayloadTypes = InferOutput +export type MessageSources = InferOutput export type DataTypes = Answer | IceCandidate | Offer | IceCandidates @@ -568,7 +564,7 @@ export type InvalidMessageError = { export type ValidationError = { info: 'validationError' requestId: DataTypes['requestId'] - error: ValiError + error: ValiError } export type SignalingServerResponse = From ad29c8f2664cec41443c8668952d6081c84e3461 Mon Sep 17 00:00:00 2001 From: Dawid Sowa Date: Tue, 24 Sep 2024 09:35:50 +0200 Subject: [PATCH 02/45] fix: improve error type returned from `validateWalletResponse` --- .../src/helpers/validate-wallet-response.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/dapp-toolkit/src/helpers/validate-wallet-response.ts b/packages/dapp-toolkit/src/helpers/validate-wallet-response.ts index eb78cd16..b8856335 100644 --- a/packages/dapp-toolkit/src/helpers/validate-wallet-response.ts +++ b/packages/dapp-toolkit/src/helpers/validate-wallet-response.ts @@ -4,14 +4,17 @@ import { WalletInteractionSuccessResponse, } from '../schemas' import { SdkError } from '../error' -import { ValiError, parse } from 'valibot' +import { parse } from 'valibot' export const validateWalletResponse = ( walletResponse: unknown, -): ResultAsync => { +): ResultAsync< + WalletInteractionSuccessResponse, + SdkError | { discriminator: 'failure'; interactionId: string; error: string } +> => { const fn = Result.fromThrowable( (_) => parse(WalletInteractionResponse, _), - (error) => error as ValiError, + (error) => error, ) const result = fn(walletResponse) @@ -20,7 +23,7 @@ export const validateWalletResponse = ( } else if (result.isOk()) { return result.value.discriminator === 'success' ? okAsync(result.value) - : errAsync(result.value as any) + : errAsync(result.value) } return errAsync(SdkError('walletResponseValidation', '')) From ade0fe7f033b319c13e46431f208cdcbc9f68965 Mon Sep 17 00:00:00 2001 From: Dawid Sowa <119939994+dawidsowardx@users.noreply.github.com> Date: Thu, 3 Oct 2024 16:23:25 +0200 Subject: [PATCH 03/45] feat: add proofOfOwnership request handling (#261) * feat: add new request type * feat: add proof of ownership request builder * docs: update readme to reflect new request type --- packages/common/src/index.ts | 1 + .../src/components/card/request-card.ts | 10 +++ packages/dapp-toolkit/README.md | 72 ++++++++++++++++--- .../data-request/builders/index.ts | 15 ++-- .../builders/proof-of-ownership.ts | 43 +++++++++++ .../data-request/data-request-state.spec.ts | 17 +++++ .../data-request/helpers/to-wallet-request.ts | 7 ++ .../transformations/rdt-to-wallet.ts | 41 ++++++++++- .../transformations/wallet-to-rdt.ts | 29 ++++++++ .../modules/wallet-request/wallet-request.ts | 15 +++- packages/dapp-toolkit/src/schemas/index.ts | 24 +++++++ 11 files changed, 255 insertions(+), 19 deletions(-) create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/proof-of-ownership.ts diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 17b89fa3..bb167105 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -39,6 +39,7 @@ export const RequestItemType = { loginRequest: 'loginRequest', dataRequest: 'dataRequest', sendTransaction: 'sendTransaction', + proofRequest: 'proofRequest', } as const export type RequestItemType = typeof RequestItemType diff --git a/packages/connect-button/src/components/card/request-card.ts b/packages/connect-button/src/components/card/request-card.ts index a33287e2..5f7fa60c 100644 --- a/packages/connect-button/src/components/card/request-card.ts +++ b/packages/connect-button/src/components/card/request-card.ts @@ -93,6 +93,16 @@ export class RadixRequestCard extends LitElement { 'Open Your Radix Wallet App to complete the request', ), }, + proofRequest: { + pending: 'Proof Request Pending', + fail: 'Proof Request Rejected', + cancelled: 'Proof Request Rejected', + success: 'Proof Request', + ignored: '', + content: this.getRequestContentTemplate( + 'Open Your Radix Wallet App to complete the request', + ), + } } return html` ``` +## Using `create-radix-dapp` + +You can easily start experimenting with Radix dApp Toolkit and various frameworks by using our [CLI tool](https://github.com/radixdlt/create-radix-dapp) to scaffold a new project. Just paste following command into your terminal and it will walk you through all required steps! + +```bash +npx create-radix-dapp@latest +``` + # Usage ## Getting started @@ -105,6 +116,9 @@ const rdt = RadixDappToolkit({ - **requires** networkId - Target radix network ID. - _optional_ applicationName - Your dApp name. It's only used for statistics purposes on gateway side - _optional_ applicationVersion - Your dApp version. It's only used for statistics purposes on gateway side +- _optional_ logger - Configure and provide `Logger` instance if you want to deep dive into what's happening in RDT + +There are more configuration options which are not described here. Please look up [`OptionalRadixDappToolkitOptions`](https://github.com/radixdlt/radix-dapp-toolkit/blob/c65fa2ad016b22e3b5a5410a0a1adc24bbee86fe/packages/dapp-toolkit/src/_types.ts#L48) to learn more. ## Login requests @@ -156,6 +170,8 @@ In order to request a persona or account with proof of ownership a challenge is A challenge is a random 32 bytes hex encoded string that looks something like: `4ccb0555d6b4faad0d7f5ed40bf4e4f0665c8ba35929c638e232e09775d0fa0e` +If you're using JS for your backend you can use `generateRolaChallenge` function from Radix dApp Toolkit which will generate valid ROLA challenge for you. + **Why do we need a challenge?** The challenge plays an important role in the authentication flow, namely preventing replay attacks from bad actors. The challenge ensures that an authentication request payload sent from the client can only be used once. After a challenge is claimed by a request, the subsequent requests can no longer be resolved successfully with the same payload. As a security best practice, a stored challenge should have a short expiration time. In this case, just enough time for a user to interact with the wallet. @@ -165,19 +181,11 @@ The challenge plays an important role in the authentication flow, namely prevent In order to request a proof, it is required to provide a function to RDT that produces a challenge. ```typescript -// type requestChallengeFromDappBackendFn = () => Promise +// const requestChallengeFromDappBackendFn = (): Promise => +// http.get('/api/auth/challenge') rdt.walletApi.provideChallengeGenerator(requestChallengeFromDappBackendFn) - rdt.walletApi.setRequestData(DataRequestBuilder.persona.withProof()) - -// handle the wallet response -rdt.walletApi.dataRequestControl(async (walletData) => { - const personaProof = walletData.proofs.find( - (proof) => proof.type === 'persona', - ) - if (personaProof) await handleLogin(personaProof) -}) ``` ### Handle user authentication @@ -205,6 +213,30 @@ rdt.walletApi.dataRequestControl(async (walletData) => { See [ROLA example](https://github.com/radixdlt/rola-examples) for an end-to-end implementation. +### Authenticate specific account or persona + +Sometimes you want to restrict access to some parts of the system. For example you have admin part of your dApp which only people with specific identities can access. On the other hand, you don't want every user to go through ROLA process every time they login. Here's where ["one-time proof of ownership"](#one-time-data-request) request comes handy. Radix dApp Toolkit gives you you a way to ask Radix Wallet about **specific account addresses and identity**. + +**Example:** + +```typescript + // const verifyProofInBackend = (proof: SignedChallenge): ResultAsync => { ... } + + rdt.walletApi.sendOneTimeRequest( + OneTimeDataRequestBuilder.proofOfOwnership().identity( + 'identity_tdx_2_12g3f29r62450l03ejucc2cf0pz52uawkwwm4um3chqxjjl2ffhq6f8', + ), + ).andThen((response) => { + const proof = response.proofs.find((proof) => proof.address ==='identity_tdx_2_12g3f29r62450l03ejucc2cf0pz52uawkwwm4um3chqxjjl2ffhq6f8') + return verifyProofInBackend(proof) + }) +``` + +> [!IMPORTANT] +> If you want to use that, you need to configure challenge generator with `provideChallengeGenerator` + + + ### User authentication management After a successful ROLA verification it is up to the dApp's business logic to handle user authentication session in order to keep the user logged-in between requests. Although RDT is persisting state between page reloads, it is not aware of user authentication. The dApp logic needs to control the login state and sign out a user when needed. @@ -340,6 +372,24 @@ rdt.walletApi.sendOneTimeRequest( ) ``` +#### `OneTimeDataRequestBuilderItem.proofOfOwnership()` + +```typescript +accounts: (value: string[]) => ProofOfOwnershipRequestBuilder +identity: (value: string) => ProofOfOwnershipRequestBuilder +``` + +Example: Prove that user who is trying access admin page right is owner of given identity + +```typescript +// const currentUserState = { .... } +rdt.walletApi.sendOneTimeRequest( + OneTimeDataRequestBuilder.proofOfOwnership().identity( + currentUserState.identity + ), +) +``` + #### `DataRequestBuilder.config(input: DataRequestState)` Use this method if you prefer to provide a raw data request object. @@ -369,7 +419,7 @@ rdt.walletApi.provideConnectResponseCallback((result) => { ### One Time Data Request -One-time data requests do not have a Persona context, and so will always result in the Radix Wallet asking the user to select where to draw personal data from. The wallet response from a one time data request is meant to be discarded after usage. A typical use case would be to populate a web-form with user data. +Sometimes you want to get some data from the Radix Wallet based on various user actions like custom button click, page event, route change etc. One-time data requests are perfect way of doing that. One time data requests neither need any "auth" context nor they keep any state. The wallet response from a one time data request is meant to be discarded after usage. A typical use case would be to populate a web-form with user data, choose account, prove identity etc. ```typescript const result = rdt.walletApi.sendOneTimeRequest( diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/index.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/index.ts index 9763d609..32e53b74 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/index.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/index.ts @@ -11,6 +11,7 @@ import { PersonaDataRequestBuilder, personaData, } from './persona-data' +import { proofOfOwnership, ProofOfOwnershipRequest, ProofOfOwnershipRequestBuilder } from './proof-of-ownership' export type DataRequestBuilderItem = | AccountsRequestBuilder @@ -21,12 +22,14 @@ export type DataRequestBuilderItem = export type OneTimeDataRequestBuilderItem = | OneTimeAccountsRequestBuilder | OneTimePersonaDataRequestBuilder + | ProofOfOwnershipRequestBuilder -export type DataRequestState = Partial< - { accounts: AccountsDataRequest } & { personaData: PersonaDataRequest } & { - persona: PersonaRequest - } -> +export type DataRequestState = Partial<{ + accounts: AccountsDataRequest + personaData: PersonaDataRequest + persona: PersonaRequest + proofOfOwnership: ProofOfOwnershipRequest +}> export type ConfigRequestBuilder = {} @@ -57,9 +60,11 @@ export const DataRequestBuilder: DataRequestBuilder = { export type OneTimeDataRequestBuilder = { accounts: () => OneTimeAccountsRequestBuilder personaData: (input?: PersonaDataRequest) => OneTimePersonaDataRequestBuilder + proofOfOwnership: () => ProofOfOwnershipRequestBuilder } export const OneTimeDataRequestBuilder: OneTimeDataRequestBuilder = { accounts, personaData, + proofOfOwnership, } diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/proof-of-ownership.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/proof-of-ownership.ts new file mode 100644 index 00000000..884e4234 --- /dev/null +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/builders/proof-of-ownership.ts @@ -0,0 +1,43 @@ +import { produce } from 'immer' +import { object, InferOutput, string, array, optional } from 'valibot' + +export type ProofOfOwnershipRequestBuilder = { + accounts: (value: string[]) => ProofOfOwnershipRequestBuilder + identity: (value: string) => ProofOfOwnershipRequestBuilder +} +export type ProofOfOwnershipRequest = InferOutput + +const schema = object({ + accountAddresses: optional(array(string())), + identityAddress: optional(string()), +}) + +export const proofOfOwnership = (initialData: ProofOfOwnershipRequest = {}) => { + let data: ProofOfOwnershipRequest = produce(initialData, () => {}) + + const accounts = (value: string[]) => { + data = produce(data, (draft) => { + draft.accountAddresses = value + }) + return methods + } + + const identity = (value: string) => { + data = produce(data, (draft) => { + draft.identityAddress = value + }) + return methods + } + + const _toObject = (): { proofOfOwnership: ProofOfOwnershipRequest } => ({ + proofOfOwnership: data, + }) + + const methods = { + accounts, + identity, + _toObject, + } + + return methods +} diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/data-request-state.spec.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/data-request-state.spec.ts index d3de0502..6877dbaa 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/data-request-state.spec.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/data-request-state.spec.ts @@ -1,3 +1,4 @@ +import { OneTimeDataRequestBuilder } from './builders' import { accounts } from './builders/accounts' import { persona } from './builders/persona' import { personaData } from './builders/persona-data' @@ -17,6 +18,22 @@ describe('DataRequestStateModule', () => { }) }) + describe('toDataRequestState', () => { + it('should consume one time data request builder proofOfOwnership', () => { + const state = dataRequest.toDataRequestState( + OneTimeDataRequestBuilder.proofOfOwnership() + .identity('identity_abc') + .accounts(['account_abc']), + ) + expect(state).toEqual({ + proofOfOwnership: { + identityAddress: 'identity_abc', + accountAddresses: ['account_abc'], + }, + }) + }) + }) + it('should be instantiated with default values', () => { expect(dataRequest.getState()).toEqual({ accounts: { diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/helpers/to-wallet-request.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/helpers/to-wallet-request.ts index f6c8206c..4b62c66b 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/helpers/to-wallet-request.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/helpers/to-wallet-request.ts @@ -20,6 +20,13 @@ export const toWalletRequest = ({ transformRdtDataRequestToWalletRequest( isConnect, produce({}, (draft: TransformRdtDataRequestToWalletRequestInput) => { + if (dataRequestState.proofOfOwnership) { + draft.proofOfOwnership = { + ...dataRequestState.proofOfOwnership, + challenge, + } + } + if (dataRequestState.accounts) { draft.accounts = { numberOfAccounts: dataRequestState.accounts.numberOfAccounts || { diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts index 7aa4d6aa..f88cf299 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts @@ -9,12 +9,19 @@ import { NumberOfValues } from '../../../../schemas' import { produce } from 'immer' import type { Result } from 'neverthrow' import { ok } from 'neverthrow' -import { boolean, object, string, InferOutput, optional } from 'valibot' +import { boolean, object, string, InferOutput, optional, array } from 'valibot' export type TransformRdtDataRequestToWalletRequestInput = InferOutput< typeof TransformRdtDataRequestToWalletRequestInput > export const TransformRdtDataRequestToWalletRequestInput = object({ + proofOfOwnership: optional( + object({ + challenge: optional(string()), + accountAddresses: optional(array(string())), + identityAddress: optional(string()), + }), + ), accounts: optional( object({ numberOfAccounts: NumberOfValues, @@ -112,6 +119,36 @@ const withAccountRequestItem = return updatedRequestItems } +const withProofOfOwnershipRequestItem = + (input: TransformRdtDataRequestToWalletRequestInput) => + ( + requestItems: T, + ) => { + const updatedRequestItems = { ...requestItems } + + if (input.proofOfOwnership) { + const { challenge, accountAddresses, identityAddress } = + input.proofOfOwnership + + if (challenge) { + updatedRequestItems['proofOfOwnership'] = { + challenge, + } + if (accountAddresses) { + updatedRequestItems['proofOfOwnership'].accountAddresses = + accountAddresses + } + + if (identityAddress) { + updatedRequestItems['proofOfOwnership'].identityAddress = + identityAddress + } + } + } + + return updatedRequestItems + } + const withPersonaDataRequestItem = (input: TransformRdtDataRequestToWalletRequestInput) => ( @@ -170,6 +207,7 @@ const createUnauthorizedRequestItems = ( }) .map(withAccountRequestItem(input)) .map(withPersonaDataRequestItem(input)) + .map(withProofOfOwnershipRequestItem(input)) const createAuthorizedRequestItems = ( input: TransformRdtDataRequestToWalletRequestInput, @@ -181,6 +219,7 @@ const createAuthorizedRequestItems = ( .map(withAccountRequestItem(input)) .map(withPersonaDataRequestItem(input)) .map(withResetRequestItem(input)) + .map(withProofOfOwnershipRequestItem(input)) const transformConnectRequest = ( isConnect: boolean, diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/wallet-to-rdt.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/wallet-to-rdt.ts index cea15995..1bbfbbbe 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/wallet-to-rdt.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/wallet-to-rdt.ts @@ -2,11 +2,14 @@ import { produce } from 'immer' import { okAsync, type ResultAsync } from 'neverthrow' import type { Account, + AccountProof, PersonaDataRequestResponseItem, + PersonaProof, WalletAuthorizedRequestResponseItems, WalletUnauthorizedRequestResponseItems, } from '../../../../schemas' import { + SignedChallenge, type SignedChallengeAccount, type WalletData, proofType, @@ -62,6 +65,24 @@ const withPersonaDataEntries = ( return entries } +const convertOwnershipProofsToSignedChallenge = ( + challenge: string, + proofs: (PersonaProof | AccountProof)[], +): SignedChallenge[] => { + return proofs.map((proof) => { + const type = + 'identityAddress' in proof ? proofType.persona : proofType.account + const address = + 'identityAddress' in proof ? proof.identityAddress : proof.accountAddress + return { + type, + challenge, + address, + proof: proof.proof, + } + }) +} + const withPersonaData = (input: WalletDataRequestResponse) => (walletData: WalletData) => produce(walletData, (draft) => { @@ -147,6 +168,14 @@ const withProofs = draft.proofs.push(...accountProofs) } } + if (input.proofOfOwnership) { + draft.proofs.push( + ...convertOwnershipProofsToSignedChallenge( + input.proofOfOwnership.challenge, + input.proofOfOwnership.proofs, + ), + ) + } }) export const transformWalletResponseToRdtWalletData = ( diff --git a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts index 2e05c099..6658e9f9 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts @@ -172,7 +172,9 @@ export const WalletRequestModule = (input: { ) => ResultAsync const isChallengeNeeded = (dataRequestState: DataRequestState) => - dataRequestState.accounts?.withProof || dataRequestState.persona?.withProof + dataRequestState.accounts?.withProof || + dataRequestState.persona?.withProof || + dataRequestState.proofOfOwnership const getChallenge = ( dataRequestState: DataRequestState, @@ -304,9 +306,18 @@ export const WalletRequestModule = (input: { !state.walletData.persona && walletDataRequest.discriminator === 'authorizedRequest' + const isProofOfOwnershipRequest = + !!walletDataRequest.proofOfOwnership + + const requestItemType = isLoginRequest + ? 'loginRequest' + : isProofOfOwnershipRequest + ? 'proofRequest' + : 'dataRequest' + return requestItemModule .add({ - type: isLoginRequest ? 'loginRequest' : 'dataRequest', + type: requestItemType, walletInteraction, isOneTimeRequest: oneTime, }) diff --git a/packages/dapp-toolkit/src/schemas/index.ts b/packages/dapp-toolkit/src/schemas/index.ts index a72732df..e82d17f1 100644 --- a/packages/dapp-toolkit/src/schemas/index.ts +++ b/packages/dapp-toolkit/src/schemas/index.ts @@ -39,6 +39,26 @@ export const AccountProof = object({ proof: Proof, }) +export type PersonaProof = InferOutput +export const PersonaProof = object({ + identityAddress: string(), + proof: Proof, +}) + +export type ProofOfOwnershipRequestItem = InferOutput< + typeof ProofOfOwnershipRequestItem +> +export const ProofOfOwnershipRequestItem = object({ + challenge: string(), + identityAddress: optional(string()), + accountAddresses: optional(array(string())), +}) + +export const ProofOfOwnershipResponseItem = object({ + challenge: string(), + proofs: array(union([AccountProof, PersonaProof])), +}) + export type Persona = InferOutput export const Persona = object({ identityAddress: string(), label: string() }) @@ -133,6 +153,7 @@ export type WalletUnauthorizedRequestItems = InferOutput< > export const WalletUnauthorizedRequestItems = object({ discriminator: literal('unauthorizedRequest'), + proofOfOwnership: optional(ProofOfOwnershipRequestItem), oneTimeAccounts: optional(AccountsRequestItem), oneTimePersonaData: optional(PersonaDataRequestItem), }) @@ -176,6 +197,7 @@ export const WalletAuthorizedRequestItems = object({ discriminator: literal('authorizedRequest'), auth: AuthRequestItem, reset: optional(ResetRequestItem), + proofOfOwnership: optional(ProofOfOwnershipRequestItem), oneTimeAccounts: optional(AccountsRequestItem), ongoingAccounts: optional(AccountsRequestItem), oneTimePersonaData: optional(PersonaDataRequestItem), @@ -249,6 +271,7 @@ export type WalletUnauthorizedRequestResponseItems = InferOutput< > const WalletUnauthorizedRequestResponseItems = object({ discriminator: literal('unauthorizedRequest'), + proofOfOwnership: optional(ProofOfOwnershipResponseItem), oneTimeAccounts: optional(AccountsRequestResponseItem), oneTimePersonaData: optional(PersonaDataRequestResponseItem), }) @@ -298,6 +321,7 @@ export type WalletAuthorizedRequestResponseItems = InferOutput< export const WalletAuthorizedRequestResponseItems = object({ discriminator: literal('authorizedRequest'), auth: AuthRequestResponseItem, + proofOfOwnership: optional(ProofOfOwnershipResponseItem), oneTimeAccounts: optional(AccountsRequestResponseItem), ongoingAccounts: optional(AccountsRequestResponseItem), oneTimePersonaData: optional(PersonaDataRequestResponseItem), From 2dd51550719cdce03b9dbae0a813c6866a8dc1ff Mon Sep 17 00:00:00 2001 From: Alex Stelea Date: Mon, 30 Sep 2024 16:00:24 +0200 Subject: [PATCH 04/45] feat: implement resolve request module --- examples/simple-dapp/src/main.ts | 28 +- package-lock.json | 15 +- packages/common/src/index.ts | 3 + packages/dapp-toolkit/package.json | 4 +- .../dapp-toolkit/src/helpers/parse-json.ts | 3 +- .../connect-button/connect-button.module.ts | 47 +- .../src/modules/connect-button/types.ts | 1 - .../src/modules/state/state.module.ts | 12 +- .../request-items/request-item.module.ts | 16 +- .../wallet-request/request-resolver/index.ts | 3 + .../request-resolver.module.ts | 187 +++++++ .../resolvers/data-response.ts | 125 +++++ .../resolvers/failed-response.ts | 42 ++ .../request-resolver/resolvers/index.ts | 3 + .../resolvers/send-transaction-response.ts | 73 +++ .../wallet-request/request-resolver/type.ts | 16 + .../connector-extension.module.ts | 36 +- .../radix-connect-relay.module.ts | 105 ++-- .../radix-connect-relay/rcfm-page.module.ts | 83 --- .../modules/wallet-request/wallet-request.ts | 506 +++++++----------- 20 files changed, 759 insertions(+), 549 deletions(-) create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/request-resolver/index.ts create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/request-resolver/request-resolver.module.ts create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/data-response.ts create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/failed-response.ts create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/index.ts create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/send-transaction-response.ts create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/request-resolver/type.ts delete mode 100644 packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/rcfm-page.module.ts diff --git a/examples/simple-dapp/src/main.ts b/examples/simple-dapp/src/main.ts index 041797da..60c191b7 100644 --- a/examples/simple-dapp/src/main.ts +++ b/examples/simple-dapp/src/main.ts @@ -11,7 +11,6 @@ import { } from '@radixdlt/radix-dapp-toolkit' const dAppDefinitionAddress = import.meta.env.VITE_DAPP_DEFINITION_ADDRESS -const widgetUrl = import.meta.env.VITE_WIDGET_DAPP_URL const networkId = RadixNetwork.Stokenet const storageModule = LocalStorageModule( `rdt:${dAppDefinitionAddress}:${networkId}`, @@ -76,7 +75,6 @@ addCb.onclick = () => { const dAppToolkit = RadixDappToolkit({ dAppDefinitionAddress, networkId, - featureFlags: ['ExperimentalMobileSupport'], logger, }) @@ -84,7 +82,9 @@ const gatewayApi = GatewayApiClient.initialize( dAppToolkit.gatewayApi.clientConfig, ) -dAppToolkit.walletApi.provideChallengeGenerator(async () => generateRolaChallenge()) +dAppToolkit.walletApi.provideChallengeGenerator(async () => + generateRolaChallenge(), +) dAppToolkit.walletApi.setRequestData( DataRequestBuilder.persona().withProof(), @@ -107,16 +107,18 @@ resetButton.onclick = () => { sendTxButton.onclick = () => { dAppToolkit.walletApi.sendTransaction({ - transactionManifest: `CALL_METHOD - Address("component_tdx_2_1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxyulkzl") - "free" -; -CALL_METHOD - Address("account_tdx_2_12yfw30hdc445j4lnepw7dmrkjcqcswsrxlff5r07mrjq9f8mnnn2r5") - "try_deposit_batch_or_abort" - Expression("ENTIRE_WORKTOP") - Enum<0u8>() -;`, + transactionManifest: ` + CALL_METHOD + Address("component_tdx_2_1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxyulkzl") + "free" + ; + + CALL_METHOD + Address("account_tdx_2_1299trm47s3x648jemhu3lfm4d6gt73289rd9s2hpdjm3tp5pdwq4m5") + "try_deposit_batch_or_abort" + Expression("ENTIRE_WORKTOP") + Enum<0u8>() + ;`, }) } diff --git a/package-lock.json b/package-lock.json index 805531bb..cb635e7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21481,11 +21481,6 @@ "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", "dev": true }, - "node_modules/neverthrow": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/neverthrow/-/neverthrow-6.1.0.tgz", - "integrity": "sha512-xNbNjp/6M5vUV+mststgneJN9eJeJCDSYSBTaf3vxgvcKooP+8L0ATFpM8DGfmH7UWKJeoa24Qi33tBP9Ya3zA==" - }, "node_modules/no-case": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", @@ -33575,7 +33570,7 @@ "immer": "^10.0.4", "lit": "^3.1.2", "lit-html": "^3.1.2", - "neverthrow": "^6.1.0", + "neverthrow": "^8.0.0", "rxjs": "^7.8.1", "tslog": ">=4.8.0", "uuid": "^10.0.0", @@ -34745,6 +34740,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "packages/dapp-toolkit/node_modules/neverthrow": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/neverthrow/-/neverthrow-8.0.0.tgz", + "integrity": "sha512-SX2Z50+U27I+CF3NwHE9J8MB6+bYRRub3U+1nAKxnL6c+2vW2l/WsYEC0e3Wqg8DwiJvrquqE0YhxlVTzGJGsg==", + "engines": { + "node": ">=18" + } + }, "packages/dapp-toolkit/node_modules/node-emoji": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index bb167105..dd4f450c 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -59,6 +59,7 @@ export type WalletRequest< timestamp: number showCancel?: boolean transactionIntentHash?: string + transactionStatus?: string walletInteraction: any walletResponse?: any metadata: Record @@ -76,4 +77,6 @@ export type RequestItem = { walletResponse?: any sentToWallet?: boolean isOneTimeRequest?: boolean + metadata?: Record + walletData?: any } diff --git a/packages/dapp-toolkit/package.json b/packages/dapp-toolkit/package.json index 6d8356c4..837dcc1d 100644 --- a/packages/dapp-toolkit/package.json +++ b/packages/dapp-toolkit/package.json @@ -68,7 +68,7 @@ "immer": "^10.0.4", "lit": "^3.1.2", "lit-html": "^3.1.2", - "neverthrow": "^6.1.0", + "neverthrow": "^8.0.0", "rxjs": "^7.8.1", "tslog": ">=4.8.0", "uuid": "^10.0.0", @@ -95,4 +95,4 @@ "publishConfig": { "registry": "https://registry.npmjs.org" } -} \ No newline at end of file +} diff --git a/packages/dapp-toolkit/src/helpers/parse-json.ts b/packages/dapp-toolkit/src/helpers/parse-json.ts index 37c03c7b..7b3ba89d 100644 --- a/packages/dapp-toolkit/src/helpers/parse-json.ts +++ b/packages/dapp-toolkit/src/helpers/parse-json.ts @@ -1,6 +1,5 @@ import type { Result } from 'neverthrow' import { err, ok } from 'neverthrow' -import { typedError } from './typed-error' export const parseJSON = >( text: string, @@ -8,6 +7,6 @@ export const parseJSON = >( try { return ok(JSON.parse(text)) } catch (error) { - return err(typedError(error)) + return err(error as Error) } } diff --git a/packages/dapp-toolkit/src/modules/connect-button/connect-button.module.ts b/packages/dapp-toolkit/src/modules/connect-button/connect-button.module.ts index 001d3c19..ea527513 100644 --- a/packages/dapp-toolkit/src/modules/connect-button/connect-button.module.ts +++ b/packages/dapp-toolkit/src/modules/connect-button/connect-button.module.ts @@ -1,7 +1,10 @@ import { + concatMap, + delay, filter, finalize, first, + from, fromEvent, map, merge, @@ -10,12 +13,10 @@ import { Subscription, switchMap, tap, - timer, } from 'rxjs' import { ConnectButton } from '@radixdlt/connect-button' import type { Account, - RadixButtonStatus, RadixButtonTheme, RequestItem, } from 'radix-connect-common' @@ -314,7 +315,6 @@ export const ConnectButtonModule = ( onCancelRequestItem$: subjects.onCancelRequestItem.asObservable(), onIgnoreTransactionItem$: subjects.onIgnoreTransactionItem.asObservable(), onLinkClick$: subjects.onLinkClick.asObservable(), - setStatus: (value: RadixButtonStatus) => subjects.status.next(value), setTheme: (value: RadixButtonTheme) => subjects.theme.next(value), setMode: (value: 'light' | 'dark') => subjects.mode.next(value), setActiveTab: (value: 'sharing' | 'requests') => @@ -385,12 +385,6 @@ export const ConnectButtonModule = ( walletRequestModule.requestItems$ .pipe( tap((items) => { - const hasPendingItem = items.find((item) => item.status === 'pending') - - if (hasPendingItem) { - connectButtonApi.setStatus('pending') - } - connectButtonApi.setRequestItems([...items].reverse()) }), ) @@ -465,22 +459,27 @@ export const ConnectButtonModule = ( subscriptions.add( walletRequestModule.interactionStatusChange$ .pipe( - mergeMap((newStatus) => { - statusStorage.setState({ - status: newStatus === 'success' ? 'success' : 'error', - }) - - return timer(2000).pipe( - tap(() => { - const result = walletRequestModule.getPendingRequests() - result.map((pendingItems) => { - statusStorage.setState({ - status: pendingItems.length ? 'pending' : 'default', - }) - }) + mergeMap((newStatus) => + from( + statusStorage.setState({ + status: + newStatus === 'success' + ? 'success' + : newStatus === 'fail' + ? 'error' + : 'pending', }), - ) - }), + ).pipe( + delay(2000), + concatMap(() => + walletRequestModule.getPendingRequests().andThen((items) => + statusStorage.setState({ + status: items.length ? 'pending' : 'default', + }), + ), + ), + ), + ), ) .subscribe(), ) diff --git a/packages/dapp-toolkit/src/modules/connect-button/types.ts b/packages/dapp-toolkit/src/modules/connect-button/types.ts index 043f463c..0655460c 100644 --- a/packages/dapp-toolkit/src/modules/connect-button/types.ts +++ b/packages/dapp-toolkit/src/modules/connect-button/types.ts @@ -26,7 +26,6 @@ export type ConnectButtonModuleOutput = { type: 'account' | 'transaction' | 'showQrCode' | 'setupGuide' | 'getWallet' data: string }> - setStatus: (value: RadixButtonStatus) => void setMode: (value: 'light' | 'dark') => void setTheme: (value: RadixButtonTheme) => void setActiveTab: (value: 'sharing' | 'requests') => void diff --git a/packages/dapp-toolkit/src/modules/state/state.module.ts b/packages/dapp-toolkit/src/modules/state/state.module.ts index c6c2faba..42ecb8b2 100644 --- a/packages/dapp-toolkit/src/modules/state/state.module.ts +++ b/packages/dapp-toolkit/src/modules/state/state.module.ts @@ -2,7 +2,7 @@ import { BehaviorSubject, Subscription, filter } from 'rxjs' import { RdtState, WalletData, walletDataDefault } from './types' import { Logger } from '../../helpers' import { StorageModule } from '../storage' -import { ok, okAsync } from 'neverthrow' +import { ok, okAsync, ResultAsync } from 'neverthrow' export type StateModule = ReturnType @@ -13,20 +13,22 @@ export const StateModule = (input: { } }) => { const logger = input?.logger?.getSubLogger({ name: 'StateModule' }) - const storageModule = input.providers.storageModule + const storageModule: StorageModule = input.providers.storageModule const subscriptions = new Subscription() const setState = (state: RdtState) => storageModule.setState(state) - const getState = () => + const getState = (): ResultAsync => storageModule .getState() .orElse(() => okAsync(defaultState)) .andThen((state) => (state ? ok(state) : ok(defaultState))) - + const patchState = (state: Partial) => - getState().andThen((oldState) => setState({ ...oldState, ...state } as RdtState)) + getState().andThen((oldState) => + setState({ ...oldState, ...state } as RdtState), + ) const defaultState = { walletData: walletDataDefault, diff --git a/packages/dapp-toolkit/src/modules/wallet-request/request-items/request-item.module.ts b/packages/dapp-toolkit/src/modules/wallet-request/request-items/request-item.module.ts index 33818a19..8f6a2a98 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/request-items/request-item.module.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/request-items/request-item.module.ts @@ -9,6 +9,7 @@ import { ErrorType } from '../../../error' import { WalletInteraction } from '../../../schemas' import type { StorageModule } from '../../storage' import { ResultAsync, errAsync } from 'neverthrow' +import { WalletData } from '../../state' export type RequestItemModuleInput = { logger?: Logger providers: { storageModule: StorageModule } @@ -70,11 +71,15 @@ export const RequestItemModule = (input: RequestItemModuleInput) => { status, error, transactionIntentHash, + metadata = {}, + walletData, }: { id: string status: RequestStatusTypes error?: string transactionIntentHash?: string + walletData?: WalletData + metadata?: Record }): ResultAsync => { return storageModule .getItemById(id) @@ -83,10 +88,16 @@ export const RequestItemModule = (input: RequestItemModuleInput) => { if (item) { const updated = { ...item, + walletData, status: item.status === RequestStatus.ignored ? item.status : status, + metadata: item.metadata + ? { ...item.metadata, ...metadata } + : metadata, } as RequestItem + if (updated.status === 'fail') { + updated.transactionIntentHash = transactionIntentHash! updated.error = error! } if ( @@ -95,9 +106,10 @@ export const RequestItemModule = (input: RequestItemModuleInput) => { ) { updated.transactionIntentHash = transactionIntentHash! } - if (['success', 'fail', 'ignored', 'cancelled'].includes(updated.status)) { + if ( + ['success', 'fail', 'ignored', 'cancelled'].includes(updated.status) + ) { delete updated.walletInteraction - delete updated.walletResponse } logger?.debug({ method: 'updateRequestItemStatus', updated }) return storageModule diff --git a/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/index.ts b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/index.ts new file mode 100644 index 00000000..7ff8789d --- /dev/null +++ b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/index.ts @@ -0,0 +1,3 @@ +export * from './resolvers' +export * from './request-resolver.module' +export * from './type' diff --git a/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/request-resolver.module.ts b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/request-resolver.module.ts new file mode 100644 index 00000000..31c122ca --- /dev/null +++ b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/request-resolver.module.ts @@ -0,0 +1,187 @@ +import { err, ok, okAsync, ResultAsync } from 'neverthrow' +import type { Logger } from '../../../helpers' +import type { WalletInteractionResponse } from '../../../schemas' +import type { StorageModule } from '../../storage' +import type { RequestItemModule } from '../request-items' +import { SdkError } from '../../../error' +import { StateModule } from '../../state' +import { filter, firstValueFrom, map } from 'rxjs' +import { GatewayModule } from '../../gateway' +import { WalletResponseResolver } from './type' +import { RequestItem } from 'radix-connect-common' + +export type RequestResolverModule = ReturnType +export const RequestResolverModule = (input: { + logger?: Logger + providers: { + stateModule: StateModule + storageModule: StorageModule + requestItemModule: RequestItemModule + updateConnectButtonStatus: (status: 'fail' | 'success') => void + gatewayModule: GatewayModule + resolvers: WalletResponseResolver[] + } +}) => { + const WAIT_TIME = 1_000 + const { providers } = input + const { requestItemModule, storageModule, resolvers } = providers + const logger = input.logger?.getSubLogger({ name: 'RequestResolverModule' }) + + let shouldRun = true + + const walletResponses: StorageModule = + storageModule.getPartition('walletResponses') + + const getPendingRequests = () => + requestItemModule + .getPending() + .orElse((error) => { + logger?.error({ method: 'getPendingRequests', error }) + return ok([]) + }) + .andThen((pendingItems) => + pendingItems.length === 0 + ? err('PendingItemsNotFound') + : ok(pendingItems), + ) + + const getPendingRequestById = (interactionId: string) => + requestItemModule + .getById(interactionId) + .mapErr(() => SdkError('FailedToGetPendingItems', interactionId)) + .andThen((pendingItem) => + pendingItem?.status === 'pending' + ? ok(pendingItem) + : err(SdkError('PendingItemNotFound', interactionId)), + ) + + const getWalletResponseById = ( + interactionId: string, + ): ResultAsync => + requestItemModule + .getById(interactionId) + .mapErr(() => SdkError('FailedToGetWalletResponse', interactionId)) + .map((item) => item?.walletResponse) + + const markRequestAsSent = (interactionId: string) => + requestItemModule.patch(interactionId, { sentToWallet: true }) + + const addWalletResponses = (responses: WalletInteractionResponse[]) => + walletResponses.setItems( + responses.reduce>( + (acc, response) => { + acc[response.interactionId] = response + return acc + }, + {}, + ), + ) + + const toRequestItemMap = (items: RequestItem[]) => + items.reduce>( + (acc, item) => ({ ...acc, [item.interactionId]: item }), + {}, + ) + + const matchRequestItemToResponses = ( + requestItems: Record, + ) => { + const ids = Object.keys(requestItems) + return walletResponses + .getItemList() + .map((responses) => + responses.filter((response) => ids.includes(response.interactionId)), + ) + .andThen((responses) => + responses.length ? ok(responses) : err('WalletResponsesNotFound'), + ) + .map((responses) => + responses.map((response) => ({ + walletInteractionResponse: response, + requestItem: requestItems[response.interactionId], + })), + ) + } + + const resolveRequests = ( + unresolvedRequests: { + walletInteractionResponse: WalletInteractionResponse + requestItem: RequestItem + }[], + ) => + ResultAsync.combine(unresolvedRequests.map(resolveRequest)).map( + () => unresolvedRequests, + ) + + // Remove data from RequestItem and WalletResponse that is no longer needed + const cleanup = (requestItems: RequestItem[]) => { + return okAsync(undefined) + } + + const resolveRequest = ({ + requestItem, + walletInteractionResponse, + }: { + walletInteractionResponse: WalletInteractionResponse + requestItem: RequestItem + }) => { + const { walletInteraction } = requestItem + + return ResultAsync.combine( + resolvers.map((resolver) => + resolver({ walletInteraction, walletInteractionResponse, requestItem }), + ), + ) + } + + const waitForWalletResponse = (interactionId: string) => + ResultAsync.fromSafePromise( + firstValueFrom( + requestItemModule.requests$.pipe( + filter((items) => + items.some( + (item) => + item.interactionId === interactionId && + item.status !== 'pending', + ), + ), + map( + (items) => + items.find((item) => item.interactionId === interactionId)!, + ), + ), + ), + ) + + const requestResolverLoop = async () => { + await getPendingRequests() + .map(toRequestItemMap) + .andThen(matchRequestItemToResponses) + .andThen(resolveRequests) + .map((unresolvedRequests) => + unresolvedRequests.map((item) => item.requestItem), + ) + .andThen(cleanup) + + await new Promise((resolve) => setTimeout(resolve, WAIT_TIME)) + + if (shouldRun) requestResolverLoop() + } + + requestResolverLoop() + + return { + waitForWalletResponse, + getPendingRequestById, + getPendingRequestIds: () => + getPendingRequests().map((items) => + items.map((item) => item.interactionId), + ), + markRequestAsSent, + addWalletResponses, + getWalletResponseById, + destroy: () => { + shouldRun = false + }, + } +} diff --git a/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/data-response.ts b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/data-response.ts new file mode 100644 index 00000000..72c569c7 --- /dev/null +++ b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/data-response.ts @@ -0,0 +1,125 @@ +import { err, okAsync, ResultAsync } from 'neverthrow' +import { + WalletInteraction, + WalletInteractionResponse, +} from '../../../../schemas' +import { + transformWalletRequestToSharedData, + transformWalletResponseToRdtWalletData, + WalletDataRequestResponse, +} from '../../data-request' +import { RequestItemModule } from '../../request-items' +import { StateModule, WalletData } from '../../../state' +import { SdkError } from '../../../../error' +import { UpdateConnectButtonStatus, WalletResponseResolver } from '../type' +import { RequestItem } from 'radix-connect-common' + +const matchResponse = ( + input: WalletInteractionResponse, +): WalletDataRequestResponse | undefined => { + if (input.discriminator === 'success') { + if ( + input.items.discriminator === 'authorizedRequest' || + input.items.discriminator === 'unauthorizedRequest' + ) { + return input.items + } + } +} + +type GetDataRequestController = () => + | undefined + | (( + walletData: WalletData, + ) => ResultAsync) + +const useDataRequestController = + (getDataRequestController: GetDataRequestController, interactionId: string) => + (walletData: WalletData) => { + const maybeDataRequestController = getDataRequestController() + + if (!maybeDataRequestController) return okAsync(walletData) + + return maybeDataRequestController(walletData) + .map(() => walletData) + .mapErr((error) => SdkError(error.error, interactionId, error.message)) + } + +const handleAuthorizedRequestResponse = ({ + requestItem, + walletInteraction, + walletData, + stateModule, +}: { + requestItem: RequestItem + walletInteraction: WalletInteraction + walletData: WalletData + stateModule: StateModule +}) => + stateModule + .getState() + .andThen((state) => + stateModule.setState({ + loggedInTimestamp: + requestItem.type === 'loginRequest' + ? Date.now().toString() + : state!.loggedInTimestamp, + walletData, + sharedData: transformWalletRequestToSharedData( + walletInteraction, + state!.sharedData, + ), + }), + ) + .orElse(() => + err(SdkError('FailedToUpdateRdtState', walletInteraction.interactionId)), + ) + +export const dataResponseResolver = + (dependencies: { + requestItemModule: RequestItemModule + getDataRequestController: GetDataRequestController + stateModule: StateModule + updateConnectButtonStatus: UpdateConnectButtonStatus + }): WalletResponseResolver => + ({ walletInteraction, walletInteractionResponse, requestItem }) => { + const dataResponse = matchResponse(walletInteractionResponse) + if (!dataResponse) return okAsync(undefined) + + const { requestItemModule, getDataRequestController, stateModule } = + dependencies + + const { interactionId } = walletInteraction + + return transformWalletResponseToRdtWalletData(dataResponse) + .andThen( + useDataRequestController(getDataRequestController, interactionId), + ) + .andThen((walletData) => + dataResponse.discriminator === 'authorizedRequest' + ? handleAuthorizedRequestResponse({ + requestItem, + walletInteraction, + walletData, + stateModule, + }).map(() => walletData) + : okAsync(walletData), + ) + .andThen((walletData) => + requestItemModule + .updateStatus({ + id: walletInteraction.interactionId, + status: 'success', + walletData, + }) + .mapErr((error) => + SdkError(error.reason, walletInteraction.interactionId), + ), + ) + .andTee(() => dependencies.updateConnectButtonStatus('success')) + .orElse((error) => { + dependencies.updateConnectButtonStatus('fail') + return err(error) + }) + .map(() => undefined) + } diff --git a/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/failed-response.ts b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/failed-response.ts new file mode 100644 index 00000000..3e180856 --- /dev/null +++ b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/failed-response.ts @@ -0,0 +1,42 @@ +import { err, okAsync } from 'neverthrow' +import { + WalletInteractionFailureResponse, + WalletInteractionResponse, +} from '../../../../schemas' +import { RequestItemModule } from '../../request-items' +import { SdkError } from '../../../../error' +import { UpdateConnectButtonStatus, WalletResponseResolver } from '../type' + +const matchResponse = ( + input: WalletInteractionResponse, +): WalletInteractionFailureResponse | undefined => { + if (input.discriminator === 'failure') { + return input + } +} + +export const failedResponseResolver = + (dependencies: { + requestItemModule: RequestItemModule + updateConnectButtonStatus: UpdateConnectButtonStatus + }): WalletResponseResolver => + ({ walletInteraction, walletInteractionResponse }) => { + const failedResponse = matchResponse(walletInteractionResponse) + if (!failedResponse) return okAsync(undefined) + + const { interactionId } = walletInteraction + + const { requestItemModule } = dependencies + + return requestItemModule + .updateStatus({ + id: interactionId, + status: 'fail', + }) + .orElse((error) => { + dependencies.updateConnectButtonStatus('fail') + return err(SdkError(error.reason, interactionId)) + }) + .andTee(() => dependencies.updateConnectButtonStatus('fail')) + .map(() => undefined) + } diff --git a/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/index.ts b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/index.ts new file mode 100644 index 00000000..c3965723 --- /dev/null +++ b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/index.ts @@ -0,0 +1,3 @@ +export * from './data-response' +export * from './failed-response' +export * from './send-transaction-response' diff --git a/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/send-transaction-response.ts b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/send-transaction-response.ts new file mode 100644 index 00000000..2250c06d --- /dev/null +++ b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/send-transaction-response.ts @@ -0,0 +1,73 @@ +import { err, okAsync } from 'neverthrow' +import { + WalletInteractionResponse, + WalletTransactionResponseItems, +} from '../../../../schemas' +import { GatewayModule, TransactionStatus } from '../../../gateway' +import { RequestItemModule } from '../../request-items' +import { SdkError } from '../../../../error' +import { UpdateConnectButtonStatus, WalletResponseResolver } from '../type' + +const matchResponse = ( + input: WalletInteractionResponse, +): WalletTransactionResponseItems | undefined => { + if ( + input.discriminator === 'success' && + input.items.discriminator === 'transaction' + ) { + return input.items + } +} + +const determineFailedTransaction = (status: TransactionStatus) => { + const failedTransactionStatus: TransactionStatus[] = [ + TransactionStatus.Rejected, + TransactionStatus.CommittedFailure, + ] + + return failedTransactionStatus.includes(status) +} + +export const sendTransactionResponseResolver = + (dependencies: { + gatewayModule: GatewayModule + requestItemModule: RequestItemModule + updateConnectButtonStatus: UpdateConnectButtonStatus + }): WalletResponseResolver => + ({ walletInteraction, walletInteractionResponse }) => { + const transactionResponse = matchResponse(walletInteractionResponse) + if (!transactionResponse) return okAsync(undefined) + + const { gatewayModule, requestItemModule, updateConnectButtonStatus } = + dependencies + const { interactionId } = walletInteraction + + const { + send: { transactionIntentHash }, + } = transactionResponse + + return gatewayModule + .pollTransactionStatus(transactionIntentHash) + .andThen(({ status }) => { + const isFailedTransaction = determineFailedTransaction(status) + const requestItemStatus = isFailedTransaction ? 'fail' : 'success' + + return requestItemModule + .updateStatus({ + id: interactionId, + status: requestItemStatus, + transactionIntentHash, + metadata: { transactionStatus: status }, + }) + .orElse((error) => err(SdkError(error.reason, interactionId))) + .andThen(() => { + updateConnectButtonStatus(requestItemStatus) + return okAsync(undefined) + }) + .orElse((error) => { + updateConnectButtonStatus('fail') + return err(error) + }) + }) + .map(() => undefined) + } diff --git a/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/type.ts b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/type.ts new file mode 100644 index 00000000..dec31a44 --- /dev/null +++ b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/type.ts @@ -0,0 +1,16 @@ +import { ResultAsync } from 'neverthrow' +import { WalletInteraction, WalletInteractionResponse } from '../../../schemas' +import { SdkError } from '../../../error' +import { RequestItem } from 'radix-connect-common' + +export type WalletResponseResolverInput = { + walletInteraction: WalletInteraction + walletInteractionResponse: WalletInteractionResponse + requestItem: RequestItem +} + +export type WalletResponseResolver = ( + input: WalletResponseResolverInput, +) => ResultAsync + +export type UpdateConnectButtonStatus = (status: 'fail' | 'success') => void diff --git a/packages/dapp-toolkit/src/modules/wallet-request/transport/connector-extension/connector-extension.module.ts b/packages/dapp-toolkit/src/modules/wallet-request/transport/connector-extension/connector-extension.module.ts index 0cceadfd..642196a5 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/transport/connector-extension/connector-extension.module.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/transport/connector-extension/connector-extension.module.ts @@ -7,6 +7,7 @@ import { filter, first, firstValueFrom, + from, map, merge, mergeMap, @@ -26,14 +27,13 @@ import { MessageLifeCycleExtensionStatusEvent, WalletInteraction, WalletInteractionExtensionInteraction, - WalletInteractionResponse, eventType, } from '../../../../schemas' -import { RequestItemModule } from '../../request-items' import { StorageModule } from '../../../storage' import { SdkError } from '../../../../error' import { TransportProvider } from '../../../../_types' import { v4 as uuidV4 } from 'uuid' +import type { RequestResolverModule } from '../../request-resolver/request-resolver.module' export type ConnectorExtensionModule = ReturnType< typeof ConnectorExtensionModule @@ -44,7 +44,7 @@ export const ConnectorExtensionModule = (input: { logger?: Logger extensionDetectionTime?: number providers: { - requestItemModule: RequestItemModule + requestResolverModule: RequestResolverModule storageModule: StorageModule<{ sessionId?: string }> } }) => { @@ -56,7 +56,7 @@ export const ConnectorExtensionModule = (input: { const subjects = input?.subjects ?? ConnectorExtensionSubjects() const subscription = new Subscription() const extensionDetectionTime = input?.extensionDetectionTime ?? 200 - const requestItemModule = input.providers.requestItemModule + const requestResolverModule = input.providers.requestResolverModule const storage = input.providers.storageModule.getPartition('connectorExtension') @@ -77,6 +77,15 @@ export const ConnectorExtensionModule = (input: { ) .subscribe(), ) + subscription.add( + subjects.responseSubject + .pipe( + mergeMap((walletResponse) => + from(requestResolverModule.addWalletResponses([walletResponse])), + ), + ) + .subscribe(), + ) subscription.add( subjects.outgoingMessageSubject .pipe( @@ -137,22 +146,18 @@ export const ConnectorExtensionModule = (input: { ): ResultAsync => { const cancelRequestSubject = new Subject>() + const maybeResolved$ = from( + requestResolverModule.getWalletResponseById( + walletInteraction.interactionId, + ), + ).pipe(filter((result) => result.isOk() && !!result.value)) + const walletResponse$ = subjects.responseSubject.pipe( filter( (response) => response.interactionId === walletInteraction.interactionId, ), - mergeMap( - (walletResponse): ResultAsync => - requestItemModule - .patch(walletResponse.interactionId, { - walletResponse, - }) - .mapErr(() => - SdkError('requestItemPatchError', walletResponse.interactionId), - ) - .map(() => walletResponse), - ), + map((walletResponse) => ok(walletResponse)), ) const cancelResponse$ = subjects.messageLifeCycleEventSubject.pipe( @@ -206,6 +211,7 @@ export const ConnectorExtensionModule = (input: { }) const walletResponseOrCancelRequest$ = merge( + maybeResolved$, walletResponse$, cancelRequestSubject, ).pipe(first()) diff --git a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/radix-connect-relay.module.ts b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/radix-connect-relay.module.ts index b2ed636b..c90eba7d 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/radix-connect-relay.module.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/radix-connect-relay.module.ts @@ -1,4 +1,4 @@ -import { ResultAsync, err, errAsync, ok, okAsync } from 'neverthrow' +import { ResultAsync, errAsync } from 'neverthrow' import { Subscription } from 'rxjs' import { EncryptionModule, transformBufferToSealbox } from '../../encryption' import { Session, SessionModule } from '../../session/session.module' @@ -20,6 +20,7 @@ import { } from './radix-connect-relay-api.service' import type { TransportProvider } from '../../../../_types' import { base64urlEncode } from './helpers/base64url' +import type { RequestResolverModule } from '../../request-resolver/request-resolver.module' export type RadixConnectRelayModule = ReturnType export const RadixConnectRelayModule = (input: { @@ -30,6 +31,7 @@ export const RadixConnectRelayModule = (input: { providers: { requestItemModule: RequestItemModule storageModule: StorageModule + requestResolverModule: RequestResolverModule encryptionModule?: EncryptionModule identityModule?: IdentityModule sessionModule?: SessionModule @@ -38,10 +40,7 @@ export const RadixConnectRelayModule = (input: { }): TransportProvider => { const logger = input.logger?.getSubLogger({ name: 'RadixConnectRelayModule' }) const { baseUrl, providers, walletUrl } = input - const { requestItemModule, storageModule } = providers - - const walletResponses: StorageModule = - storageModule.getPartition('walletResponses') + const { requestItemModule, storageModule, requestResolverModule } = providers const encryptionModule = providers?.encryptionModule ?? EncryptionModule() @@ -102,32 +101,16 @@ export const RadixConnectRelayModule = (input: { } const checkRelayLoop = async () => { - await requestItemModule.getPending().andThen((pendingItems) => { - if (pendingItems.length === 0) { - return okAsync(undefined) - } - - return sessionModule + await requestResolverModule.getPendingRequestIds().andThen(() => + sessionModule .getCurrentSession() - .andThen((session) => - radixConnectRelayApiService.getResponses(session.sessionId), - ) + .map((session) => session.sessionId) + .andThen(radixConnectRelayApiService.getResponses) .andThen((responses) => - ResultAsync.combine( - responses.map((response) => decryptWalletResponse(response)), - ).andThen((decryptedResponses) => { - return walletResponses.setItems( - decryptedResponses.reduce( - (acc, response) => { - acc[response.interactionId] = response - return acc - }, - {} as Record, - ), - ) - }), + ResultAsync.combine(responses.map(decryptWalletResponse)), ) - }) + .andThen(requestResolverModule.addWalletResponses), + ) await wait() checkRelayLoop() } @@ -149,33 +132,24 @@ export const RadixConnectRelayModule = (input: { publicKey: string identity: string }) => - requestItemModule - .getById(walletInteraction.interactionId) - .mapErr(() => - SdkError('FailedToGetPendingItems', walletInteraction.interactionId), - ) - .andThen((pendingItem) => - pendingItem - ? ok(pendingItem) - : err( - SdkError('PendingItemNotFound', walletInteraction.interactionId), - ), + requestResolverModule + .getPendingRequestById(walletInteraction.interactionId) + .andThen(() => + requestResolverModule.markRequestAsSent( + walletInteraction.interactionId, + ), ) .andThen(() => - requestItemModule - .patch(walletInteraction.interactionId, { sentToWallet: true }) - .andThen(() => - deepLinkModule.deepLinkToWallet({ - sessionId: session.sessionId, - request: base64urlEncode(walletInteraction), - signature, - publicKey, - identity: identity, - origin: walletInteraction.metadata.origin, - dAppDefinitionAddress: - walletInteraction.metadata.dAppDefinitionAddress, - }), - ), + deepLinkModule.deepLinkToWallet({ + sessionId: session.sessionId, + request: base64urlEncode(walletInteraction), + signature, + publicKey, + identity, + origin: walletInteraction.metadata.origin, + dAppDefinitionAddress: + walletInteraction.metadata.dAppDefinitionAddress, + }), ) .mapErr(() => SdkError('FailedToSendDappRequest', walletInteraction.interactionId), @@ -260,31 +234,24 @@ export const RadixConnectRelayModule = (input: { const requestItemResult = await requestItemModule.getById(interactionId) - if (requestItemResult.isOk()) { + const requestItem = + requestItemResult.isOk() && requestItemResult.value + + if (requestItem) { logger?.trace({ method: 'waitForWalletResponse.requestItemResult', - requestItemResult: requestItemResult.value, + requestItem, }) - if (requestItemResult.value?.status !== 'pending') { + + if (requestItem.status !== 'pending') { error = SdkError( 'RequestItemNotPending', interactionId, 'request not in pending state', ) break - } - } - - const walletResponse = - await walletResponses.getItemById(interactionId) - - if (walletResponse.isOk()) { - if (walletResponse.value) { - response = walletResponse.value - await walletResponses.removeItemById(interactionId) - await requestItemModule.patch(interactionId, { - walletResponse: walletResponse.value, - }) + } else if (requestItem.walletResponse) { + response = requestItem.walletResponse } } diff --git a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/rcfm-page.module.ts b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/rcfm-page.module.ts deleted file mode 100644 index dc410f7f..00000000 --- a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/rcfm-page.module.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { isBrowser } from '../../../../helpers/is-browser' -import { Logger } from '../../../../helpers' - -export const RcfmPageState = { - loading: 'loading', - dAppVerified: 'dAppVerified', - timedOut: 'timedOut', -} as const - -export type RcfmPageState = (typeof RcfmPageState)[keyof typeof RcfmPageState] - -export type RcfmPageModule = ReturnType -export const RcfmPageModule = (input: { logger?: Logger }) => { - const logger = input.logger?.getSubLogger({ name: 'RcfmPageModule' }) - if (!isBrowser()) { - logger?.debug({ method: 'isBrowser', isBrowser: false }) - return { - show: () => {}, - hide: () => {}, - showWithData: () => {}, - } - } - - const rcfmPageHtmlElement = document.createElement('radix-rcfm-page') - document.body.appendChild(rcfmPageHtmlElement) - - const showWithData = (values: { - header?: string - subheader?: string - isError?: boolean - isLoading?: boolean - }) => { - const { header, subheader, isError, isLoading } = values - rcfmPageHtmlElement.header = header || '' - rcfmPageHtmlElement.subheader = subheader || '' - rcfmPageHtmlElement.isError = isError || false - rcfmPageHtmlElement.isLoading = isLoading || false - rcfmPageHtmlElement.isHidden = false - logger?.debug({ - method: 'showWithData', - values, - }) - } - const hide = () => { - logger?.debug({ method: 'hide', isHidden: true }) - rcfmPageHtmlElement.isHidden = true - } - - const show = (state: RcfmPageState) => { - logger?.debug({ method: 'show', state }) - switch (state) { - case RcfmPageState.dAppVerified: - showWithData({ - header: 'Connection succesful!', - subheader: 'You can now close this tab', - isError: false, - isLoading: false, - }) - break - case RcfmPageState.loading: - showWithData({ - isLoading: true, - }) - break - case RcfmPageState.timedOut: - showWithData({ - header: 'Connection timed out', - subheader: 'Close this tab and try connecting again', - isError: true, - isLoading: false, - }) - break - default: - break - } - } - - return { - show, - hide, - showWithData, - } -} diff --git a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts index 6658e9f9..b38bcf12 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts @@ -5,18 +5,13 @@ import { filter, firstValueFrom, map, - mergeMap, switchMap, tap, } from 'rxjs' import { validateRolaChallenge, type Logger } from '../../helpers' import { TransactionStatus } from '../gateway' -import { Result, ResultAsync, err, ok, okAsync } from 'neverthrow' -import type { - MessageLifeCycleEvent, - WalletInteraction, - WalletInteractionResponse, -} from '../../schemas' +import { ResultAsync, err, ok, okAsync } from 'neverthrow' +import type { MessageLifeCycleEvent, WalletInteraction } from '../../schemas' import { SdkError } from '../../error' import { DataRequestBuilderItem, @@ -25,11 +20,9 @@ import { canDataRequestBeResolvedByRdtState, toWalletRequest, transformSharedDataToDataRequestState, - transformWalletRequestToSharedData, - transformWalletResponseToRdtWalletData, } from './data-request' import { StorageModule } from '../storage' -import { StateModule, WalletData } from '../state' +import type { StateModule, WalletData } from '../state' import { AwaitedWalletDataRequestResult, TransportProvider, @@ -38,6 +31,12 @@ import { import { ConnectorExtensionModule, RadixConnectRelayModule } from './transport' import { GatewayModule } from '../gateway' import { RequestItemModule } from './request-items' +import { RequestResolverModule } from './request-resolver/request-resolver.module' +import { + dataResponseResolver, + failedResponseResolver, + sendTransactionResponseResolver, +} from './request-resolver' type SendTransactionInput = { transactionManifest: string @@ -63,6 +62,7 @@ export const WalletRequestModule = (input: { dataRequestStateModule?: DataRequestStateModule requestItemModule?: RequestItemModule walletRequestSdk?: WalletRequestSdk + requestResolverModule?: RequestResolverModule } }) => { const logger = input.logger?.getSubLogger({ name: 'WalletRequestModule' }) @@ -70,7 +70,9 @@ export const WalletRequestModule = (input: { const networkId = input.networkId const cancelRequestSubject = new Subject() const ignoreTransactionSubject = new Subject() - const interactionStatusChangeSubject = new Subject<'fail' | 'success'>() + const interactionStatusChangeSubject = new Subject< + 'fail' | 'success' | 'pending' + >() const gatewayModule = input.providers.gatewayModule const dAppDefinitionAddress = input.dAppDefinitionAddress @@ -89,10 +91,48 @@ export const WalletRequestModule = (input: { }, }) + const updateConnectButtonStatus = ( + status: 'success' | 'fail' | 'pending', + ) => { + interactionStatusChangeSubject.next(status) + } + + const requestResolverModule = + input.providers.requestResolverModule ?? + RequestResolverModule({ + logger, + providers: { + storageModule, + requestItemModule, + stateModule, + resolvers: [ + sendTransactionResponseResolver({ + gatewayModule, + requestItemModule, + updateConnectButtonStatus, + }), + failedResponseResolver({ + requestItemModule, + updateConnectButtonStatus, + }), + dataResponseResolver({ + requestItemModule, + getDataRequestController: () => dataRequestControl, + stateModule, + updateConnectButtonStatus, + }), + ], + updateConnectButtonStatus: (status) => { + interactionStatusChangeSubject.next(status) + }, + gatewayModule, + }, + }) + const transports: TransportProvider[] = input.providers.transports ?? [ ConnectorExtensionModule({ logger, - providers: { requestItemModule, storageModule }, + providers: { storageModule, requestResolverModule }, }), RadixConnectRelayModule({ logger, @@ -102,6 +142,7 @@ export const WalletRequestModule = (input: { providers: { requestItemModule, storageModule, + requestResolverModule, }, }), ] @@ -206,6 +247,24 @@ export const WalletRequestModule = (input: { })) } + const sendRequestAndAwaitResponse = ( + walletInteraction: WalletInteraction, + type: 'transaction' | 'data', + ) => { + updateConnectButtonStatus('pending') + return ResultAsync.combine([ + (type === 'data' + ? walletRequestSdk.request + : walletRequestSdk.sendTransaction)( + walletInteraction, + cancelRequestControl(walletInteraction.interactionId), + ), + requestResolverModule.waitForWalletResponse( + walletInteraction.interactionId, + ), + ]).map(([_, response]) => response) + } + const sendOneTimeRequest = (...items: DataRequestBuilderItem[]) => sendRequest({ dataRequestState: dataRequestStateModule.toDataRequestState(...items), @@ -213,62 +272,38 @@ export const WalletRequestModule = (input: { oneTime: true, }) - const resolveWalletResponse = ( - walletInteraction: WalletInteraction, - walletInteractionResponse: WalletInteractionResponse, - ) => { - if ( - walletInteractionResponse.discriminator === 'success' && - walletInteractionResponse.items.discriminator === 'authorizedRequest' - ) { - return ResultAsync.combine([ - transformWalletResponseToRdtWalletData(walletInteractionResponse.items), - stateModule.getState(), - ]).andThen(([walletData, state]) => { - return stateModule - .setState({ - loggedInTimestamp: Date.now().toString(), - walletData, - sharedData: transformWalletRequestToSharedData( - walletInteraction, - state!.sharedData, - ), - }) - .andThen(() => - requestItemModule.updateStatus({ - id: walletInteractionResponse.interactionId, - status: 'success', - }), - ) - }) - } - - return okAsync(undefined) - } - - const sendDataRequest = (walletInteraction: WalletInteraction) => { - return walletRequestSdk - .request( - walletInteraction, - cancelRequestControl(walletInteraction.interactionId), - ) - .map((response: WalletInteractionResponse) => { + const sendDataRequest = (walletInteraction: WalletInteraction) => + sendRequestAndAwaitResponse(walletInteraction, 'data') + .andThen((response) => { logger?.debug({ method: 'sendDataRequest.successResponse', response }) - - return response + return ok(response.walletData! as WalletData) }) .mapErr((error) => { logger?.debug({ method: 'sendDataRequest.errorResponse', error }) + return error + }) - requestItemModule.updateStatus({ - id: walletInteraction.interactionId, - status: 'fail', - error: error.error, - }) + const getRdtState = () => + stateModule.getState().mapErr(() => SdkError('FailedToReadRdtState', '')) - return error + const addNewRequest = ( + type: 'loginRequest' | 'dataRequest' | 'proofRequest', + walletInteraction: WalletInteraction, + isOneTimeRequest: boolean, + ) => + requestItemModule + .add({ + type, + walletInteraction, + isOneTimeRequest, }) - } + .mapErr(({ message }) => + SdkError( + 'FailedToCreateRequestItem', + walletInteraction.interactionId, + message, + ), + ) const sendRequest = ({ isConnect, @@ -278,146 +313,46 @@ export const WalletRequestModule = (input: { dataRequestState: DataRequestState isConnect: boolean oneTime: boolean - }): WalletDataRequestResult => { - return ResultAsync.combine([ + }): WalletDataRequestResult => + ResultAsync.combine([ getChallenge(dataRequestState), - stateModule.getState().mapErr(() => SdkError('FailedToReadRdtState', '')), - ]) - .andThen(([challenge, state]) => - toWalletRequest({ - dataRequestState, - isConnect, - oneTime, - challenge, - walletData: state.walletData, - }) - .mapErr(() => SdkError('FailedToTransformWalletRequest', '')) - .asyncAndThen((walletDataRequest) => { - const walletInteraction: WalletInteraction = - walletRequestSdk.createWalletInteraction(walletDataRequest) - - if ( - canDataRequestBeResolvedByRdtState(walletDataRequest, state) && - useCache - ) - return okAsync(state.walletData) - - const isLoginRequest = - !state.walletData.persona && - walletDataRequest.discriminator === 'authorizedRequest' - - const isProofOfOwnershipRequest = - !!walletDataRequest.proofOfOwnership - - const requestItemType = isLoginRequest - ? 'loginRequest' - : isProofOfOwnershipRequest - ? 'proofRequest' - : 'dataRequest' - - return requestItemModule - .add({ - type: requestItemType, - walletInteraction, - isOneTimeRequest: oneTime, - }) - .mapErr(({ message }) => - SdkError( - 'FailedToCreateRequestItem', - walletInteraction.interactionId, - message, - ), - ) - .andThen(() => - sendDataRequest(walletInteraction) - .andThen((walletInteractionResponse) => { - if ( - walletInteractionResponse.discriminator === 'success' && - walletInteractionResponse.items.discriminator !== - 'transaction' - ) - return ok(walletInteractionResponse.items) - - return err( - SdkError( - 'WalletResponseFailure', - walletInteractionResponse.interactionId, - 'expected data response', - ), - ) - }) - .andThen(transformWalletResponseToRdtWalletData) - .andThen((transformedWalletResponse) => { - if (dataRequestControl) - return dataRequestControl(transformedWalletResponse) - .andThen(() => - requestItemModule - .updateStatus({ - id: walletInteraction.interactionId, - status: 'success', - }) - .mapErr((error) => - SdkError( - error.reason, - walletInteraction.interactionId, - ), - ) - .map(() => transformedWalletResponse), - ) - .mapErr((error) => { - requestItemModule.updateStatus({ - id: walletInteraction.interactionId, - status: 'fail', - error: error.error, - }) - return SdkError( - error.error, - walletInteraction.interactionId, - ) - }) - - return requestItemModule - .updateStatus({ - id: walletInteraction.interactionId, - status: 'success', - }) - .map(() => transformedWalletResponse) - .mapErr((error) => - SdkError(error.reason, walletInteraction.interactionId), - ) - }) - .map((transformedWalletResponse) => { - interactionStatusChangeSubject.next('success') - - if (!oneTime) { - stateModule - .setState({ - loggedInTimestamp: Date.now().toString(), - walletData: transformedWalletResponse, - sharedData: transformWalletRequestToSharedData( - walletInteraction, - state.sharedData, - ), - }) - .map(() => { - stateModule.emitWalletData() - }) - } - - return transformedWalletResponse - }) - .mapErr((err) => { - interactionStatusChangeSubject.next('fail') - return err - }), - ) - }), - ) - .mapErr((error) => { - logger?.error(error) - return error + getRdtState(), + ]).andThen(([challenge, state]) => + toWalletRequest({ + dataRequestState, + isConnect, + oneTime, + challenge, + walletData: state.walletData, }) - } + .mapErr(() => SdkError('FailedToTransformWalletRequest', '')) + .asyncAndThen((walletDataRequest) => { + const walletInteraction: WalletInteraction = + walletRequestSdk.createWalletInteraction(walletDataRequest) + + if ( + canDataRequestBeResolvedByRdtState(walletDataRequest, state) && + useCache + ) + return okAsync(state.walletData) + + const isLoginRequest = + !state.walletData.persona && + walletDataRequest.discriminator === 'authorizedRequest' + + const isProofOfOwnershipRequest = !!walletDataRequest.proofOfOwnership + + const requestType = isLoginRequest + ? 'loginRequest' + : isProofOfOwnershipRequest + ? 'proofRequest' + : 'dataRequest' + + return addNewRequest(requestType, walletInteraction, oneTime).andThen( + () => sendDataRequest(walletInteraction), + ) + }), + ) const setRequestDataState = (...items: DataRequestBuilderItem[]) => { dataRequestStateModule.setState(...items) @@ -454,25 +389,6 @@ export const WalletRequestModule = (input: { const subscriptions = new Subscription() - subscriptions.add( - requestItemModule.requests$ - .pipe( - mergeMap((items) => { - const unresolvedItems = items - .filter((item) => item.status === 'pending' && item.walletResponse) - .map((item) => - resolveWalletResponse( - item.walletInteraction, - item.walletResponse, - ), - ) - - return ResultAsync.combineWithAllErrors(unresolvedItems) - }), - ) - .subscribe(), - ) - const sendTransaction = ( value: SendTransactionInput, ): ResultAsync< @@ -482,107 +398,45 @@ export const WalletRequestModule = (input: { }, SdkError > => { - const walletInteraction = walletRequestSdk.createWalletInteraction({ - discriminator: 'transaction', - send: { - blobs: value.blobs, - transactionManifest: value.transactionManifest, - message: value.message, - version: value.version ?? 1, - }, - }) - - requestItemModule.add({ - type: 'sendTransaction', - walletInteraction, - isOneTimeRequest: false, - }) - - return walletRequestSdk - .sendTransaction( - walletInteraction, - cancelRequestControl(walletInteraction.interactionId), - ) - .mapErr((response): SdkError => { - requestItemModule.updateStatus({ - id: walletInteraction.interactionId, - status: 'fail', - error: response.error, - }) - interactionStatusChangeSubject.next('fail') - logger?.debug({ method: 'sendTransaction.errorResponse', response }) - return response - }) - .andThen( - (response): Result<{ transactionIntentHash: string }, SdkError> => { - logger?.debug({ method: 'sendTransaction.successResponse', response }) - if ( - response.discriminator === 'success' && - response.items.discriminator === 'transaction' - ) - return ok(response.items.send) - - if (response.discriminator === 'failure') - return err( - SdkError( - response.error, - response.interactionId, - response.message, - ), - ) - - return err(SdkError('WalletResponseFailure', response.interactionId)) + const createTransactionRequest = () => { + const walletInteraction = walletRequestSdk.createWalletInteraction({ + discriminator: 'transaction', + send: { + blobs: value.blobs, + transactionManifest: value.transactionManifest, + message: value.message, + version: value.version ?? 1, }, - ) - .andThen(({ transactionIntentHash }) => { - if (value.onTransactionId) value.onTransactionId(transactionIntentHash) - return gatewayModule - .pollTransactionStatus(transactionIntentHash) - .map((transactionStatusResponse) => ({ - transactionIntentHash, - status: transactionStatusResponse.status, - })) }) - .andThen((response) => { - const failedTransactionStatus: TransactionStatus[] = [ - TransactionStatus.Rejected, - TransactionStatus.CommittedFailure, - ] - const isFailedTransaction = failedTransactionStatus.includes( - response.status, + return requestItemModule + .add({ + type: 'sendTransaction', + walletInteraction, + isOneTimeRequest: false, + }) + .mapErr(() => + SdkError('FailedToAddRequestItem', walletInteraction.interactionId), ) + .map(() => walletInteraction) + } - logger?.debug({ - method: 'sendTransaction.pollTransactionStatus.completed', - response, - }) + return createTransactionRequest() + .andThen((walletInteraction) => + sendRequestAndAwaitResponse(walletInteraction, 'transaction'), + ) + .andThen(({ status, transactionIntentHash, metadata, interactionId }) => { + const output = { + transactionIntentHash: transactionIntentHash!, + status: metadata!.transactionStatus as TransactionStatus, + } - const status = isFailedTransaction ? 'fail' : 'success' - - return requestItemModule - .updateStatus({ - id: walletInteraction.interactionId, - status, - transactionIntentHash: response.transactionIntentHash, - }) - .mapErr(() => - SdkError( - 'FailedToUpdateRequestItem', - walletInteraction.interactionId, - ), - ) - .andThen(() => { - interactionStatusChangeSubject.next(status) - return isFailedTransaction - ? err( - SdkError( - 'TransactionNotSuccessful', - walletInteraction.interactionId, - ), - ) - : ok(response) - }) + if (value.onTransactionId) + value.onTransactionId(output.transactionIntentHash) + + return status === 'success' + ? ok(output) + : err(SdkError(output.status, interactionId)) }) } @@ -595,6 +449,7 @@ export const WalletRequestModule = (input: { cancelRequestSubject.next(id) requestItemModule.cancel(id) interactionStatusChangeSubject.next('fail') + updateConnectButtonStatus('fail') } const ignoreTransaction = (id: string) => { @@ -625,30 +480,27 @@ export const WalletRequestModule = (input: { const destroy = () => { stateModule.destroy() requestItemModule.destroy() + requestResolverModule.destroy() input.providers.transports?.forEach((transport) => transport.destroy()) subscriptions.unsubscribe() } return { - sendRequest: (input: { isConnect: boolean; oneTime: boolean }) => { - const result = sendRequest({ + sendRequest: (input: { isConnect: boolean; oneTime: boolean }) => + sendRequest({ isConnect: input.isConnect, oneTime: input.oneTime, dataRequestState: dataRequestStateModule.getState(), }) - - if (connectResponseCallback) - result - .map((result) => { - connectResponseCallback!(ok(result)) - }) - .mapErr((error) => { - connectResponseCallback!(err(error)) - }) - - return result - }, + .andThen((response) => { + if (connectResponseCallback) connectResponseCallback!(ok(response)) + return ok(response) + }) + .orElse((error) => { + if (connectResponseCallback) connectResponseCallback!(err(error)) + return err(error) + }), sendTransaction, cancelRequest, ignoreTransaction, From 5380b44a1ff8d517636be7adf99384fdbffe7c0c Mon Sep 17 00:00:00 2001 From: Alex Stelea Date: Wed, 9 Oct 2024 14:24:22 +0100 Subject: [PATCH 05/45] fix(rdt): update rdt state after ongoing response --- examples/simple-dapp/src/main.ts | 33 ++++++++++++++++++- .../resolvers/data-response.ts | 24 +++++++------- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/examples/simple-dapp/src/main.ts b/examples/simple-dapp/src/main.ts index 60c191b7..c5081059 100644 --- a/examples/simple-dapp/src/main.ts +++ b/examples/simple-dapp/src/main.ts @@ -28,7 +28,12 @@ content.innerHTML = ` -
+
+ +
+
+ +

   

@@ -49,6 +54,9 @@ const state = document.getElementById('state')!
 const gatewayConfig = document.getElementById('gatewayConfig')!
 const gatewayStatus = document.getElementById('gatewayStatus')!
 const oneTimeRequest = document.getElementById('one-time-request')!
+const proofOfOwnershipRequest = document.getElementById(
+  'proof-of-ownership-request',
+)!
 
 const logger = Logger()
 
@@ -128,6 +136,29 @@ oneTimeRequest.onclick = () => {
   )
 }
 
+proofOfOwnershipRequest.onclick = async () => {
+  const connectedAccounts =
+    dAppToolkit.walletApi.getWalletData()?.accounts ?? []
+  const connectedPersona = dAppToolkit.walletApi.getWalletData()?.persona
+
+  if (connectedAccounts.length === 0 || !connectedPersona) {
+    alert('No connected account or persona')
+    return
+  }
+
+  const result = await dAppToolkit.walletApi
+    .sendOneTimeRequest(
+      OneTimeDataRequestBuilder.accounts().exactly(1),
+      OneTimeDataRequestBuilder.proofOfOwnership()
+        .accounts(connectedAccounts.map((account) => account.address))
+        .identity(connectedPersona.identityAddress),
+    )
+    .map(() => 'success')
+    .unwrapOr('error')
+
+  alert(result)
+}
+
 setInterval(() => {
   requestsStore.getState().map((value: any) => {
     requests.innerHTML = JSON.stringify({ requests: value ?? {} }, null, 2)
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/data-response.ts b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/data-response.ts
index 72c569c7..724d24b4 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/data-response.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/data-response.ts
@@ -59,17 +59,19 @@ const handleAuthorizedRequestResponse = ({
   stateModule
     .getState()
     .andThen((state) =>
-      stateModule.setState({
-        loggedInTimestamp:
-          requestItem.type === 'loginRequest'
-            ? Date.now().toString()
-            : state!.loggedInTimestamp,
-        walletData,
-        sharedData: transformWalletRequestToSharedData(
-          walletInteraction,
-          state!.sharedData,
-        ),
-      }),
+      stateModule
+        .setState({
+          loggedInTimestamp:
+            requestItem.type === 'loginRequest'
+              ? Date.now().toString()
+              : state!.loggedInTimestamp,
+          walletData,
+          sharedData: transformWalletRequestToSharedData(
+            walletInteraction,
+            state!.sharedData,
+          ),
+        })
+        .andTee(() => stateModule.emitWalletData()),
     )
     .orElse(() =>
       err(SdkError('FailedToUpdateRdtState', walletInteraction.interactionId)),

From 566da1c5cf1ec43876f59dbde89fd7164f974676 Mon Sep 17 00:00:00 2001
From: Alex Stelea 
Date: Mon, 14 Oct 2024 11:49:37 +0100
Subject: [PATCH 06/45] build(rdt): resolve dependency types

---
 package-lock.json                    | 395 +++++++++++++++------------
 packages/dapp-toolkit/package.json   |   2 +-
 packages/dapp-toolkit/tsup.config.ts |   2 +-
 3 files changed, 223 insertions(+), 176 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index cb635e7b..19f3d2bb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5890,9 +5890,9 @@
       "dev": true
     },
     "node_modules/@esbuild/aix-ppc64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
-      "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz",
+      "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==",
       "cpu": [
         "ppc64"
       ],
@@ -5902,7 +5902,7 @@
         "aix"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/android-arm": {
@@ -6194,6 +6194,22 @@
         "node": ">=12"
       }
     },
+    "node_modules/@esbuild/openbsd-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz",
+      "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
     "node_modules/@esbuild/openbsd-x64": {
       "version": "0.18.20",
       "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
@@ -14079,9 +14095,9 @@
       }
     },
     "node_modules/bundle-require": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.0.2.tgz",
-      "integrity": "sha512-jwzPOChofl67PSTW2SGubV9HBQAhhR2i6nskiOThauo9dzwDUgOWQScFVaJkjEfYX+UXiD+LEx8EblQMc2wIag==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.0.0.tgz",
+      "integrity": "sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==",
       "dev": true,
       "dependencies": {
         "load-tsconfig": "^0.2.3"
@@ -14090,7 +14106,7 @@
         "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
       },
       "peerDependencies": {
-        "esbuild": ">=0.17"
+        "esbuild": ">=0.18"
       }
     },
     "node_modules/busboy": {
@@ -16373,12 +16389,12 @@
       }
     },
     "node_modules/debug": {
-      "version": "4.3.4",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "version": "4.3.7",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+      "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
       "dev": true,
       "dependencies": {
-        "ms": "2.1.2"
+        "ms": "^2.1.3"
       },
       "engines": {
         "node": ">=6.0"
@@ -20452,9 +20468,9 @@
       }
     },
     "node_modules/lilconfig": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz",
-      "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==",
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
+      "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
       "dev": true,
       "engines": {
         "node": ">=14"
@@ -21420,9 +21436,9 @@
       "dev": true
     },
     "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==",
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
       "dev": true
     },
     "node_modules/mute-stream": {
@@ -26075,9 +26091,9 @@
       }
     },
     "node_modules/postcss-load-config": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
-      "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
+      "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
       "dev": true,
       "funding": [
         {
@@ -26090,21 +26106,28 @@
         }
       ],
       "dependencies": {
-        "lilconfig": "^3.0.0",
-        "yaml": "^2.3.4"
+        "lilconfig": "^3.1.1"
       },
       "engines": {
-        "node": ">= 14"
+        "node": ">= 18"
       },
       "peerDependencies": {
+        "jiti": ">=1.21.0",
         "postcss": ">=8.0.9",
-        "ts-node": ">=9.0.0"
+        "tsx": "^4.8.1",
+        "yaml": "^2.4.2"
       },
       "peerDependenciesMeta": {
+        "jiti": {
+          "optional": true
+        },
         "postcss": {
           "optional": true
         },
-        "ts-node": {
+        "tsx": {
+          "optional": true
+        },
+        "yaml": {
           "optional": true
         }
       }
@@ -28185,12 +28208,6 @@
         "node": ">=4"
       }
     },
-    "node_modules/send/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "dev": true
-    },
     "node_modules/serialize-javascript": {
       "version": "6.0.2",
       "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
@@ -30139,6 +30156,45 @@
       "integrity": "sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==",
       "dev": true
     },
+    "node_modules/tinyglobby": {
+      "version": "0.2.9",
+      "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.9.tgz",
+      "integrity": "sha512-8or1+BGEdk1Zkkw2ii16qSS7uVrQJPre5A9o/XkWPATkk23FZh/15BKFxPnlTy6vkljZxLqYCzzBMj30ZrSvjw==",
+      "dev": true,
+      "dependencies": {
+        "fdir": "^6.4.0",
+        "picomatch": "^4.0.2"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/tinyglobby/node_modules/fdir": {
+      "version": "6.4.0",
+      "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.0.tgz",
+      "integrity": "sha512-3oB133prH1o4j/L5lLW7uOCF1PlD+/It2L0eL/iAqWMB91RBbqTewABqxhj0ibBd90EEmWZq7ntIWzVaWcXTGQ==",
+      "dev": true,
+      "peerDependencies": {
+        "picomatch": "^3 || ^4"
+      },
+      "peerDependenciesMeta": {
+        "picomatch": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/tinyglobby/node_modules/picomatch": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
+      "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
     "node_modules/tinypool": {
       "version": "0.8.2",
       "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.2.tgz",
@@ -30335,24 +30391,26 @@
       "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
     },
     "node_modules/tsup": {
-      "version": "8.0.2",
-      "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.0.2.tgz",
-      "integrity": "sha512-NY8xtQXdH7hDUAZwcQdY/Vzlw9johQsaqf7iwZ6g1DOUlFYQ5/AtVAjTvihhEyeRlGo4dLRVHtrRaL35M1daqQ==",
+      "version": "8.3.0",
+      "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.3.0.tgz",
+      "integrity": "sha512-ALscEeyS03IomcuNdFdc0YWGVIkwH1Ws7nfTbAPuoILvEV2hpGQAY72LIOjglGo4ShWpZfpBqP/jpQVCzqYQag==",
       "dev": true,
       "dependencies": {
-        "bundle-require": "^4.0.0",
-        "cac": "^6.7.12",
-        "chokidar": "^3.5.1",
-        "debug": "^4.3.1",
-        "esbuild": "^0.19.2",
-        "execa": "^5.0.0",
-        "globby": "^11.0.3",
-        "joycon": "^3.0.1",
-        "postcss-load-config": "^4.0.1",
+        "bundle-require": "^5.0.0",
+        "cac": "^6.7.14",
+        "chokidar": "^3.6.0",
+        "consola": "^3.2.3",
+        "debug": "^4.3.5",
+        "esbuild": "^0.23.0",
+        "execa": "^5.1.1",
+        "joycon": "^3.1.1",
+        "picocolors": "^1.0.1",
+        "postcss-load-config": "^6.0.1",
         "resolve-from": "^5.0.0",
-        "rollup": "^4.0.2",
+        "rollup": "^4.19.0",
         "source-map": "0.8.0-beta.0",
-        "sucrase": "^3.20.3",
+        "sucrase": "^3.35.0",
+        "tinyglobby": "^0.2.1",
         "tree-kill": "^1.2.2"
       },
       "bin": {
@@ -30384,9 +30442,9 @@
       }
     },
     "node_modules/tsup/node_modules/@esbuild/android-arm": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz",
-      "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz",
+      "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==",
       "cpu": [
         "arm"
       ],
@@ -30396,13 +30454,13 @@
         "android"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/android-arm64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz",
-      "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz",
+      "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==",
       "cpu": [
         "arm64"
       ],
@@ -30412,13 +30470,13 @@
         "android"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/android-x64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz",
-      "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz",
+      "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==",
       "cpu": [
         "x64"
       ],
@@ -30428,13 +30486,13 @@
         "android"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/darwin-arm64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz",
-      "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz",
+      "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==",
       "cpu": [
         "arm64"
       ],
@@ -30444,13 +30502,13 @@
         "darwin"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/darwin-x64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz",
-      "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz",
+      "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==",
       "cpu": [
         "x64"
       ],
@@ -30460,13 +30518,13 @@
         "darwin"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/freebsd-arm64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz",
-      "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz",
+      "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==",
       "cpu": [
         "arm64"
       ],
@@ -30476,13 +30534,13 @@
         "freebsd"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/freebsd-x64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz",
-      "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz",
+      "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==",
       "cpu": [
         "x64"
       ],
@@ -30492,13 +30550,13 @@
         "freebsd"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/linux-arm": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz",
-      "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz",
+      "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==",
       "cpu": [
         "arm"
       ],
@@ -30508,13 +30566,13 @@
         "linux"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/linux-arm64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz",
-      "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz",
+      "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==",
       "cpu": [
         "arm64"
       ],
@@ -30524,13 +30582,13 @@
         "linux"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/linux-ia32": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz",
-      "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz",
+      "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==",
       "cpu": [
         "ia32"
       ],
@@ -30540,13 +30598,13 @@
         "linux"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/linux-loong64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz",
-      "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz",
+      "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==",
       "cpu": [
         "loong64"
       ],
@@ -30556,13 +30614,13 @@
         "linux"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/linux-mips64el": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz",
-      "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz",
+      "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==",
       "cpu": [
         "mips64el"
       ],
@@ -30572,13 +30630,13 @@
         "linux"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/linux-ppc64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz",
-      "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz",
+      "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==",
       "cpu": [
         "ppc64"
       ],
@@ -30588,13 +30646,13 @@
         "linux"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/linux-riscv64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz",
-      "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz",
+      "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==",
       "cpu": [
         "riscv64"
       ],
@@ -30604,13 +30662,13 @@
         "linux"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/linux-s390x": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz",
-      "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz",
+      "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==",
       "cpu": [
         "s390x"
       ],
@@ -30620,13 +30678,13 @@
         "linux"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/linux-x64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz",
-      "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz",
+      "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==",
       "cpu": [
         "x64"
       ],
@@ -30636,13 +30694,13 @@
         "linux"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/netbsd-x64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz",
-      "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz",
+      "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==",
       "cpu": [
         "x64"
       ],
@@ -30652,13 +30710,13 @@
         "netbsd"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/openbsd-x64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz",
-      "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz",
+      "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==",
       "cpu": [
         "x64"
       ],
@@ -30668,13 +30726,13 @@
         "openbsd"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/sunos-x64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz",
-      "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz",
+      "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==",
       "cpu": [
         "x64"
       ],
@@ -30684,13 +30742,13 @@
         "sunos"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/win32-arm64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz",
-      "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz",
+      "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==",
       "cpu": [
         "arm64"
       ],
@@ -30700,13 +30758,13 @@
         "win32"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/win32-ia32": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz",
-      "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz",
+      "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==",
       "cpu": [
         "ia32"
       ],
@@ -30716,13 +30774,13 @@
         "win32"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/@esbuild/win32-x64": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz",
-      "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz",
+      "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==",
       "cpu": [
         "x64"
       ],
@@ -30732,45 +30790,46 @@
         "win32"
       ],
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/tsup/node_modules/esbuild": {
-      "version": "0.19.12",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz",
-      "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==",
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz",
+      "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==",
       "dev": true,
       "hasInstallScript": true,
       "bin": {
         "esbuild": "bin/esbuild"
       },
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       },
       "optionalDependencies": {
-        "@esbuild/aix-ppc64": "0.19.12",
-        "@esbuild/android-arm": "0.19.12",
-        "@esbuild/android-arm64": "0.19.12",
-        "@esbuild/android-x64": "0.19.12",
-        "@esbuild/darwin-arm64": "0.19.12",
-        "@esbuild/darwin-x64": "0.19.12",
-        "@esbuild/freebsd-arm64": "0.19.12",
-        "@esbuild/freebsd-x64": "0.19.12",
-        "@esbuild/linux-arm": "0.19.12",
-        "@esbuild/linux-arm64": "0.19.12",
-        "@esbuild/linux-ia32": "0.19.12",
-        "@esbuild/linux-loong64": "0.19.12",
-        "@esbuild/linux-mips64el": "0.19.12",
-        "@esbuild/linux-ppc64": "0.19.12",
-        "@esbuild/linux-riscv64": "0.19.12",
-        "@esbuild/linux-s390x": "0.19.12",
-        "@esbuild/linux-x64": "0.19.12",
-        "@esbuild/netbsd-x64": "0.19.12",
-        "@esbuild/openbsd-x64": "0.19.12",
-        "@esbuild/sunos-x64": "0.19.12",
-        "@esbuild/win32-arm64": "0.19.12",
-        "@esbuild/win32-ia32": "0.19.12",
-        "@esbuild/win32-x64": "0.19.12"
+        "@esbuild/aix-ppc64": "0.23.1",
+        "@esbuild/android-arm": "0.23.1",
+        "@esbuild/android-arm64": "0.23.1",
+        "@esbuild/android-x64": "0.23.1",
+        "@esbuild/darwin-arm64": "0.23.1",
+        "@esbuild/darwin-x64": "0.23.1",
+        "@esbuild/freebsd-arm64": "0.23.1",
+        "@esbuild/freebsd-x64": "0.23.1",
+        "@esbuild/linux-arm": "0.23.1",
+        "@esbuild/linux-arm64": "0.23.1",
+        "@esbuild/linux-ia32": "0.23.1",
+        "@esbuild/linux-loong64": "0.23.1",
+        "@esbuild/linux-mips64el": "0.23.1",
+        "@esbuild/linux-ppc64": "0.23.1",
+        "@esbuild/linux-riscv64": "0.23.1",
+        "@esbuild/linux-s390x": "0.23.1",
+        "@esbuild/linux-x64": "0.23.1",
+        "@esbuild/netbsd-x64": "0.23.1",
+        "@esbuild/openbsd-arm64": "0.23.1",
+        "@esbuild/openbsd-x64": "0.23.1",
+        "@esbuild/sunos-x64": "0.23.1",
+        "@esbuild/win32-arm64": "0.23.1",
+        "@esbuild/win32-ia32": "0.23.1",
+        "@esbuild/win32-x64": "0.23.1"
       }
     },
     "node_modules/tsup/node_modules/resolve-from": {
@@ -33285,18 +33344,6 @@
       "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
       "dev": true
     },
-    "node_modules/yaml": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",
-      "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==",
-      "dev": true,
-      "bin": {
-        "yaml": "bin.mjs"
-      },
-      "engines": {
-        "node": ">= 14"
-      }
-    },
     "node_modules/yargs": {
       "version": "17.7.2",
       "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
@@ -33583,7 +33630,7 @@
         "radix-connect-common": "*",
         "semantic-release": "^23.0.0",
         "semantic-release-replace-plugin": "^1.2.7",
-        "tsup": "^8.0.2",
+        "tsup": "^8.3.0",
         "typescript": "^5.4.4",
         "vite-plugin-singlefile": "^2.0.2",
         "vitest": "^1.4.0",
diff --git a/packages/dapp-toolkit/package.json b/packages/dapp-toolkit/package.json
index 837dcc1d..9285b12c 100644
--- a/packages/dapp-toolkit/package.json
+++ b/packages/dapp-toolkit/package.json
@@ -81,7 +81,7 @@
     "radix-connect-common": "*",
     "semantic-release": "^23.0.0",
     "semantic-release-replace-plugin": "^1.2.7",
-    "tsup": "^8.0.2",
+    "tsup": "^8.3.0",
     "typescript": "^5.4.4",
     "vite-plugin-singlefile": "^2.0.2",
     "vitest": "^1.4.0",
diff --git a/packages/dapp-toolkit/tsup.config.ts b/packages/dapp-toolkit/tsup.config.ts
index 5b3ccb6f..1f65dac4 100644
--- a/packages/dapp-toolkit/tsup.config.ts
+++ b/packages/dapp-toolkit/tsup.config.ts
@@ -2,7 +2,7 @@ import { defineConfig } from 'tsup'
 
 export default defineConfig({
   entry: ['src/index.ts', 'src/connect-button.ts'],
-  dts: true,
+  dts: { resolve: true },
   format: ['esm', 'cjs'],
   noExternal: ['@radixdlt/connect-button', 'radix-connect-common'],
 })

From 94e543a4912cd42b308bd5d3f928c6e1fa11b79b Mon Sep 17 00:00:00 2001
From: Dawid Sowa 
Date: Mon, 14 Oct 2024 21:53:21 +0200
Subject: [PATCH 07/45] feat: add subintents support

---
 examples/simple-dapp/src/main.ts              | 22 +++++++
 packages/common/src/index.ts                  |  1 +
 .../src/components/card/request-card.ts       | 12 +++-
 packages/dapp-toolkit/src/_types.ts           | 18 +++++-
 .../wallet-request/wallet-request-sdk.ts      | 26 +-------
 .../modules/wallet-request/wallet-request.ts  | 59 +++++++++++++------
 .../dapp-toolkit/src/radix-dapp-toolkit.ts    |  1 +
 packages/dapp-toolkit/src/schemas/index.ts    | 38 ++++++++++++
 8 files changed, 135 insertions(+), 42 deletions(-)

diff --git a/examples/simple-dapp/src/main.ts b/examples/simple-dapp/src/main.ts
index c5081059..47ed5f18 100644
--- a/examples/simple-dapp/src/main.ts
+++ b/examples/simple-dapp/src/main.ts
@@ -34,6 +34,10 @@ content.innerHTML = `
   
+
+ + +

   

@@ -48,6 +52,10 @@ const sendTxButton = document.getElementById('sendTx')!
 const sessions = document.getElementById('sessions')!
 const removeCb = document.getElementById('removeCb')!
 const addCb = document.getElementById('addCb')!
+const subintentButton = document.getElementById('subintent')!
+const subintentManifest = document.getElementById(
+  'subintentManifest',
+)! as HTMLTextAreaElement
 const requests = document.getElementById('requests')!
 const logs = document.getElementById('logs')!
 const state = document.getElementById('state')!
@@ -75,6 +83,20 @@ removeCb.onclick = () => {
   document.querySelector('radix-connect-button')?.remove()
 }
 
+subintentButton.onclick = async () => {
+  console.log(subintentManifest.value)
+  const result = await dAppToolkit.walletApi.sendPreAuthorizationRequest({
+    transactionManifest: subintentManifest.value,
+    childSubintentHashes: [],
+    expiration: {
+      discriminator: 'expireAfterSignature',
+      value: '3600',
+    },
+  })
+
+  console.log(result);
+}
+
 addCb.onclick = () => {
   const connectButton = document.createElement('radix-connect-button')
   const header = document.querySelector('header')!
diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts
index dd4f450c..42c5bfa3 100644
--- a/packages/common/src/index.ts
+++ b/packages/common/src/index.ts
@@ -40,6 +40,7 @@ export const RequestItemType = {
   dataRequest: 'dataRequest',
   sendTransaction: 'sendTransaction',
   proofRequest: 'proofRequest',
+  preAuthorizationRequest: 'preAuthorizationRequest',
 } as const
 
 export type RequestItemType = typeof RequestItemType
diff --git a/packages/connect-button/src/components/card/request-card.ts b/packages/connect-button/src/components/card/request-card.ts
index 5f7fa60c..c4fe3716 100644
--- a/packages/connect-button/src/components/card/request-card.ts
+++ b/packages/connect-button/src/components/card/request-card.ts
@@ -102,7 +102,17 @@ export class RadixRequestCard extends LitElement {
         content: this.getRequestContentTemplate(
           'Open Your Radix Wallet App to complete the request',
         ),
-      }
+      },
+      preAuthorizationRequest: {
+        pending: 'Preauthorization Request Pending',
+        fail: 'Preauthorization Request Rejected',
+        cancelled: 'Preauthorization Request Rejected',
+        success: 'Preauthorization Request',
+        ignored: '',
+        content: this.getRequestContentTemplate(
+          'Open Your Radix Wallet App to complete the request',
+        ),
+      },
     }
 
     return html`[0]
+export type WalletDataRequest = Parameters<
+  WalletRequestSdk['sendInteraction']
+>[0]
 
 export type WalletRequest =
   | { type: 'sendTransaction'; payload: WalletInteraction }
@@ -96,6 +100,15 @@ export type SendTransactionInput = {
   onTransactionId?: (transactionId: string) => void
 }
 
+export type SendPreAuthorizationRequestInput = {
+  transactionManifest: string
+  version?: number
+  blobs?: string[]
+  message?: string
+  childSubintentHashes: string[]
+  expiration: ExpireAtTime | ExpireAfterSignature
+}
+
 export type ButtonApi = {
   setMode: (value: 'light' | 'dark') => void
   setTheme: (value: RadixButtonTheme) => void
@@ -128,6 +141,9 @@ export type WalletApi = {
   dataRequestControl: (fn: (walletResponse: WalletData) => Promise) => void
   updateSharedAccounts: () => WalletDataRequestResult
   sendTransaction: (input: SendTransactionInput) => SendTransactionResult
+  sendPreAuthorizationRequest: (
+    input: SendPreAuthorizationRequestInput,
+  ) => ResultAsync<{ signedPartialTransaction: string }, SdkError>
   setRequestData: (...dataRequestBuilderItem: DataRequestBuilderItem[]) => void
   sendRequest: () => WalletDataRequestResult
   sendOneTimeRequest: (
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request-sdk.ts b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request-sdk.ts
index ec9ec97b..92921bf8 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request-sdk.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request-sdk.ts
@@ -80,11 +80,11 @@ export const WalletRequestSdk = (input: WalletRequestSdkInput) => {
         })
   }
 
-  const request = (
+  const sendInteraction = (
     {
       interactionId = uuidV4(),
       items,
-    }: Pick & { interactionId?: string },
+    }: { interactionId?: string; items: WalletInteraction['items'] },
     callbackFns: Partial = {},
   ): ResultAsync =>
     withInterceptor({
@@ -99,28 +99,8 @@ export const WalletRequestSdk = (input: WalletRequestSdkInput) => {
       ),
     )
 
-  const sendTransaction = (
-    {
-      interactionId = uuidV4(),
-      items,
-    }: { interactionId?: string; items: WalletInteraction['items'] },
-    callbackFns: Partial = {},
-  ): ResultAsync =>
-    withInterceptor({
-      interactionId,
-      items,
-      metadata,
-    }).andThen((walletInteraction) =>
-      getTransport(interactionId).asyncAndThen((transport) =>
-        transport
-          .send(walletInteraction, callbackFns)
-          .andThen(validateWalletResponse),
-      ),
-    )
-
   return {
-    request,
-    sendTransaction,
+    sendInteraction,
     createWalletInteraction,
     getTransport,
   }
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
index b38bcf12..a97f2f9f 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
@@ -11,7 +11,12 @@ import {
 import { validateRolaChallenge, type Logger } from '../../helpers'
 import { TransactionStatus } from '../gateway'
 import { ResultAsync, err, ok, okAsync } from 'neverthrow'
-import type { MessageLifeCycleEvent, WalletInteraction } from '../../schemas'
+import type {
+  ExpireAfterSignature,
+  ExpireAtTime,
+  MessageLifeCycleEvent,
+  WalletInteraction,
+} from '../../schemas'
 import { SdkError } from '../../error'
 import {
   DataRequestBuilderItem,
@@ -25,6 +30,8 @@ import { StorageModule } from '../storage'
 import type { StateModule, WalletData } from '../state'
 import {
   AwaitedWalletDataRequestResult,
+  SendPreAuthorizationRequestInput,
+  SendTransactionInput,
   TransportProvider,
   WalletDataRequestResult,
 } from '../../_types'
@@ -37,14 +44,7 @@ import {
   failedResponseResolver,
   sendTransactionResponseResolver,
 } from './request-resolver'
-
-type SendTransactionInput = {
-  transactionManifest: string
-  version?: number
-  blobs?: string[]
-  message?: string
-  onTransactionId?: (transactionId: string) => void
-}
+import { RequestItemTypes } from 'radix-connect-common'
 
 export type WalletRequestModule = ReturnType
 export const WalletRequestModule = (input: {
@@ -199,7 +199,7 @@ export const WalletRequestModule = (input: {
           ),
         )
       },
-    } satisfies Parameters[1]
+    } satisfies Parameters[1]
   }
 
   let challengeGeneratorFn: () => Promise = () => Promise.resolve('')
@@ -249,13 +249,10 @@ export const WalletRequestModule = (input: {
 
   const sendRequestAndAwaitResponse = (
     walletInteraction: WalletInteraction,
-    type: 'transaction' | 'data',
   ) => {
     updateConnectButtonStatus('pending')
     return ResultAsync.combine([
-      (type === 'data'
-        ? walletRequestSdk.request
-        : walletRequestSdk.sendTransaction)(
+      walletRequestSdk.sendInteraction(
         walletInteraction,
         cancelRequestControl(walletInteraction.interactionId),
       ),
@@ -273,7 +270,7 @@ export const WalletRequestModule = (input: {
     })
 
   const sendDataRequest = (walletInteraction: WalletInteraction) =>
-    sendRequestAndAwaitResponse(walletInteraction, 'data')
+    sendRequestAndAwaitResponse(walletInteraction)
       .andThen((response) => {
         logger?.debug({ method: 'sendDataRequest.successResponse', response })
         return ok(response.walletData! as WalletData)
@@ -287,7 +284,7 @@ export const WalletRequestModule = (input: {
     stateModule.getState().mapErr(() => SdkError('FailedToReadRdtState', ''))
 
   const addNewRequest = (
-    type: 'loginRequest' | 'dataRequest' | 'proofRequest',
+    type: RequestItemTypes,
     walletInteraction: WalletInteraction,
     isOneTimeRequest: boolean,
   ) =>
@@ -305,6 +302,33 @@ export const WalletRequestModule = (input: {
         ),
       )
 
+  const sendPreAuthorizationRequest = (
+    value: SendPreAuthorizationRequestInput,
+  ): ResultAsync<
+    {
+      signedPartialTransaction: string
+    },
+    SdkError
+  > => {
+    const walletInteraction = walletRequestSdk.createWalletInteraction({
+      discriminator: 'preAuthorizedRequest',
+      subintent: {
+        discriminator: 'subintent',
+        blobs: value.blobs,
+        transactionManifest: value.transactionManifest,
+        message: value.message,
+        version: value.version ?? 1,
+      },
+    })
+
+    return addNewRequest('preAuthorizationRequest', walletInteraction, false)
+      .andThen(() => sendRequestAndAwaitResponse(walletInteraction))
+      .map((requestItem) => ({
+        signedPartialTransaction:
+          requestItem.walletResponse.signedPartialTransaction,
+      }))
+  }
+
   const sendRequest = ({
     isConnect,
     oneTime,
@@ -423,7 +447,7 @@ export const WalletRequestModule = (input: {
 
     return createTransactionRequest()
       .andThen((walletInteraction) =>
-        sendRequestAndAwaitResponse(walletInteraction, 'transaction'),
+        sendRequestAndAwaitResponse(walletInteraction),
       )
       .andThen(({ status, transactionIntentHash, metadata, interactionId }) => {
         const output = {
@@ -502,6 +526,7 @@ export const WalletRequestModule = (input: {
           return err(error)
         }),
     sendTransaction,
+    sendPreAuthorizationRequest,
     cancelRequest,
     ignoreTransaction,
     requestItemModule,
diff --git a/packages/dapp-toolkit/src/radix-dapp-toolkit.ts b/packages/dapp-toolkit/src/radix-dapp-toolkit.ts
index 50ce4f84..5973ef90 100644
--- a/packages/dapp-toolkit/src/radix-dapp-toolkit.ts
+++ b/packages/dapp-toolkit/src/radix-dapp-toolkit.ts
@@ -119,6 +119,7 @@ export const RadixDappToolkit = (
         walletRequestModule.provideConnectResponseCallback,
       updateSharedAccounts: () => walletRequestModule.updateSharedAccounts(),
       sendOneTimeRequest: walletRequestModule.sendOneTimeRequest,
+      sendPreAuthorizationRequest: walletRequestModule.sendPreAuthorizationRequest,
       sendTransaction: (input: SendTransactionInput) =>
         walletRequestModule.sendTransaction(input),
       walletData$: stateModule.walletData$,
diff --git a/packages/dapp-toolkit/src/schemas/index.ts b/packages/dapp-toolkit/src/schemas/index.ts
index e82d17f1..1d72b34a 100644
--- a/packages/dapp-toolkit/src/schemas/index.ts
+++ b/packages/dapp-toolkit/src/schemas/index.ts
@@ -244,11 +244,49 @@ export const CancelRequest = object({
   discriminator: literal('cancelRequest'),
 })
 
+export type ExpireAtTime = InferOutput
+export const ExpireAtTime = object({
+  discriminator: literal('expireAtTime'),
+  value: string(),
+})
+
+export type ExpireAfterSignature = InferOutput
+export const ExpireAfterSignature = object({
+  discriminator: literal('expireAfterSignature'),
+  value: string(),
+})
+
+export type SubintentRequestItem = InferOutput
+export const SubintentRequestItem = object({
+  discriminator: literal('subintent'),
+  version: number(),
+  transactionManifest: string(),
+  blobs: optional(array(string())),
+  message: optional(string()),
+  childSubintentHashes: optional(array(string())),
+  expiration: optional(union([ExpireAtTime, ExpireAfterSignature])),
+})
+
+export type SubintentResponseItem = InferOutput
+export const SubintentResponseItem = object({
+  discriminator: literal('subintent'),
+  signedPartialTransaction: string(),
+})
+
+export type WalletPreAuthorizationItems = InferOutput<
+  typeof WalletPreAuthorizationItems
+>
+export const WalletPreAuthorizationItems = object({
+  discriminator: literal('preAuthorizedRequest'),
+  subintent: optional(SubintentRequestItem),
+})
+
 export type WalletInteractionItems = InferOutput
 export const WalletInteractionItems = union([
   WalletRequestItems,
   WalletTransactionItems,
   CancelRequest,
+  WalletPreAuthorizationItems,
 ])
 
 export type Metadata = InferOutput

From 4ccd67c5bf219503dc62be07dbaf2bc34a7db94a Mon Sep 17 00:00:00 2001
From: Dawid Sowa 
Date: Tue, 15 Oct 2024 14:00:53 +0200
Subject: [PATCH 08/45] fix: add missing response types & rename discriminator

---
 examples/simple-dapp/src/main.ts                  |  2 +-
 .../src/modules/wallet-request/wallet-request.ts  |  4 +---
 packages/dapp-toolkit/src/schemas/index.ts        | 15 ++++++++++++---
 3 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/examples/simple-dapp/src/main.ts b/examples/simple-dapp/src/main.ts
index 47ed5f18..9f34c98d 100644
--- a/examples/simple-dapp/src/main.ts
+++ b/examples/simple-dapp/src/main.ts
@@ -90,7 +90,7 @@ subintentButton.onclick = async () => {
     childSubintentHashes: [],
     expiration: {
       discriminator: 'expireAfterSignature',
-      value: '3600',
+      value: 3600,
     },
   })
 
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
index a97f2f9f..43e27f89 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
@@ -12,8 +12,6 @@ import { validateRolaChallenge, type Logger } from '../../helpers'
 import { TransactionStatus } from '../gateway'
 import { ResultAsync, err, ok, okAsync } from 'neverthrow'
 import type {
-  ExpireAfterSignature,
-  ExpireAtTime,
   MessageLifeCycleEvent,
   WalletInteraction,
 } from '../../schemas'
@@ -311,7 +309,7 @@ export const WalletRequestModule = (input: {
     SdkError
   > => {
     const walletInteraction = walletRequestSdk.createWalletInteraction({
-      discriminator: 'preAuthorizedRequest',
+      discriminator: 'preAuthorizationRequest',
       subintent: {
         discriminator: 'subintent',
         blobs: value.blobs,
diff --git a/packages/dapp-toolkit/src/schemas/index.ts b/packages/dapp-toolkit/src/schemas/index.ts
index 1d72b34a..200a0caa 100644
--- a/packages/dapp-toolkit/src/schemas/index.ts
+++ b/packages/dapp-toolkit/src/schemas/index.ts
@@ -247,13 +247,13 @@ export const CancelRequest = object({
 export type ExpireAtTime = InferOutput
 export const ExpireAtTime = object({
   discriminator: literal('expireAtTime'),
-  value: string(),
+  value: number(),
 })
 
 export type ExpireAfterSignature = InferOutput
 export const ExpireAfterSignature = object({
   discriminator: literal('expireAfterSignature'),
-  value: string(),
+  value: number(),
 })
 
 export type SubintentRequestItem = InferOutput
@@ -277,7 +277,7 @@ export type WalletPreAuthorizationItems = InferOutput<
   typeof WalletPreAuthorizationItems
 >
 export const WalletPreAuthorizationItems = object({
-  discriminator: literal('preAuthorizedRequest'),
+  discriminator: literal('preAuthorizationRequest'),
   subintent: optional(SubintentRequestItem),
 })
 
@@ -332,6 +332,14 @@ export const AuthLoginWithChallengeRequestResponseItem = object({
   proof: Proof,
 })
 
+export type WalletPreAuthorizationResponseItems = InferOutput<
+  typeof WalletPreAuthorizationResponseItems
+>
+export const WalletPreAuthorizationResponseItems = object({
+  discriminator: literal('preAuthorizationRequest'),
+  subintent: optional(SubintentResponseItem),
+})
+
 export const AuthLoginRequestResponseItem = union([
   AuthLoginWithoutChallengeRequestResponseItem,
   AuthLoginWithChallengeRequestResponseItem,
@@ -380,6 +388,7 @@ export type WalletInteractionResponseItems = InferOutput<
 const WalletInteractionResponseItems = union([
   WalletRequestResponseItems,
   WalletTransactionResponseItems,
+  WalletPreAuthorizationResponseItems,
 ])
 
 export type WalletInteractionSuccessResponse = InferOutput<

From b316c027a715be90c9c19a778c9496b083f406ab Mon Sep 17 00:00:00 2001
From: Alex Stelea 
Date: Thu, 17 Oct 2024 11:17:47 +0100
Subject: [PATCH 09/45] feat(rdt): add subintent request builder

---
 examples/simple-dapp/src/main.ts              |  16 ++-
 packages/dapp-toolkit/src/_types.ts           |  10 +-
 .../src/modules/wallet-request/index.ts       |   1 +
 .../pre-authorization-request/index.ts        |   1 +
 .../subintent-builder.spec.ts                 |  55 +++++++++
 .../subintent-builder.ts                      | 106 ++++++++++++++++++
 .../modules/wallet-request/wallet-request.ts  |  13 +--
 packages/dapp-toolkit/src/schemas/index.ts    |   2 +-
 8 files changed, 175 insertions(+), 29 deletions(-)
 create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/index.ts
 create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.spec.ts
 create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts

diff --git a/examples/simple-dapp/src/main.ts b/examples/simple-dapp/src/main.ts
index 9f34c98d..56e41af1 100644
--- a/examples/simple-dapp/src/main.ts
+++ b/examples/simple-dapp/src/main.ts
@@ -8,6 +8,7 @@ import {
   OneTimeDataRequestBuilder,
   LocalStorageModule,
   generateRolaChallenge,
+  SubintentRequestBuilder,
 } from '@radixdlt/radix-dapp-toolkit'
 
 const dAppDefinitionAddress = import.meta.env.VITE_DAPP_DEFINITION_ADDRESS
@@ -85,16 +86,13 @@ removeCb.onclick = () => {
 
 subintentButton.onclick = async () => {
   console.log(subintentManifest.value)
-  const result = await dAppToolkit.walletApi.sendPreAuthorizationRequest({
-    transactionManifest: subintentManifest.value,
-    childSubintentHashes: [],
-    expiration: {
-      discriminator: 'expireAfterSignature',
-      value: 3600,
-    },
-  })
+  const result = await dAppToolkit.walletApi.sendPreAuthorizationRequest(
+    SubintentRequestBuilder()
+      .manifest(subintentManifest.value)
+      .setExpiration('secondsAfterSignature', 3600),
+  )
 
-  console.log(result);
+  console.log(result)
 }
 
 addCb.onclick = () => {
diff --git a/packages/dapp-toolkit/src/_types.ts b/packages/dapp-toolkit/src/_types.ts
index b84fbd8f..bc4f670d 100644
--- a/packages/dapp-toolkit/src/_types.ts
+++ b/packages/dapp-toolkit/src/_types.ts
@@ -26,6 +26,7 @@ import type {
   WalletRequestModule,
   ConnectButtonModule,
 } from './modules'
+import { BuildableSubintentRequest } from './modules/wallet-request/pre-authorization-request/subintent-builder'
 
 export type Providers = {
   connectButtonModule: ConnectButtonModule
@@ -100,14 +101,7 @@ export type SendTransactionInput = {
   onTransactionId?: (transactionId: string) => void
 }
 
-export type SendPreAuthorizationRequestInput = {
-  transactionManifest: string
-  version?: number
-  blobs?: string[]
-  message?: string
-  childSubintentHashes: string[]
-  expiration: ExpireAtTime | ExpireAfterSignature
-}
+export type SendPreAuthorizationRequestInput = BuildableSubintentRequest
 
 export type ButtonApi = {
   setMode: (value: 'light' | 'dark') => void
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/index.ts b/packages/dapp-toolkit/src/modules/wallet-request/index.ts
index 2db1f238..9ba1455d 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/index.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/index.ts
@@ -6,3 +6,4 @@ export * from './session/session.module'
 export * from './transport'
 export * from './wallet-request-sdk'
 export * from './wallet-request'
+export * from './pre-authorization-request'
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/index.ts b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/index.ts
new file mode 100644
index 00000000..7b48a2e5
--- /dev/null
+++ b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/index.ts
@@ -0,0 +1 @@
+export * from './subintent-builder'
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.spec.ts b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.spec.ts
new file mode 100644
index 00000000..b36f85b9
--- /dev/null
+++ b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.spec.ts
@@ -0,0 +1,55 @@
+import { describe, expect, it } from 'vitest'
+import { SubintentRequestBuilder } from './subintent-builder'
+
+describe('SubintentRequestBuilder', () => {
+  it('should build a subintent request', () => {
+    const tx = SubintentRequestBuilder()
+      .manifest('...')
+      .setExpiration('secondsAfterSignature', 60)
+      .addBlobs('deadbeef', 'beefdead')
+      .message('hello')
+      .toRequestItem()
+
+    expect(tx).toEqual({
+      discriminator: 'subintent',
+      version: 1,
+      transactionManifestVersion: 1,
+      transactionManifest: '...',
+      expiration: {
+        discriminator: 'expireAfterSignature',
+        value: 60,
+      },
+      blobs: ['deadbeef', 'beefdead'],
+      message: 'hello',
+    })
+  })
+
+  it('should build a subintent request using raw object', () => {
+    const tx = SubintentRequestBuilder()
+      .rawConfig({
+        version: 1,
+        transactionManifestVersion: 1,
+        transactionManifest: '...',
+        expiration: {
+          discriminator: 'expireAfterSignature',
+          value: 60,
+        },
+        blobs: ['deadbeef', 'beefdead'],
+        message: 'hello',
+      })
+      .toRequestItem()
+
+    expect(tx).toEqual({
+      discriminator: 'subintent',
+      version: 1,
+      transactionManifestVersion: 1,
+      transactionManifest: '...',
+      expiration: {
+        discriminator: 'expireAfterSignature',
+        value: 60,
+      },
+      blobs: ['deadbeef', 'beefdead'],
+      message: 'hello',
+    })
+  })
+})
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts
new file mode 100644
index 00000000..aa3a89cc
--- /dev/null
+++ b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts
@@ -0,0 +1,106 @@
+import { SubintentRequestItem } from '../../../schemas'
+
+export type BuildableSubintentRequest = {
+  toRequestItem: () => SubintentRequestItem
+}
+/**
+ * A builder function for creating a SubintentRequest.
+ *
+ * @returns An object with methods to configure and build a SubintentRequestItem.
+ *
+ * @example
+ * const builder = SubintentRequestBuilder();
+ * const requestItem = builder
+ *   .manifest('some-manifest')
+ *   .setExpiration('atTime', 1234567890)
+ *   .addBlobs('blob1', 'blob2')
+ *   .message('This is a message')
+ *
+ * @method setExpiration
+ * Sets the expiration for the subintent request.
+ *
+ * @param type - The type of expiration, either 'atTime' or 'secondsAfterSignature'.
+ * @param value - The value of the expiration. If type is 'atTime', this is a Unix timestamp. If type is 'secondsAfterSignature', this is the number of seconds after the signature is created.
+ * @returns The API object for chaining.
+ *
+ * @method addBlobs
+ * Adds blobs to the subintent request.
+ *
+ * @param values - The blobs to add.
+ * @returns The API object for chaining.
+ *
+ * @method message
+ * Sets a message for the subintent request.
+ *
+ * @param value - The message to set.
+ * @returns The API object for chaining.
+ *
+ * @method manifest
+ * Sets the transaction manifest for the subintent request.
+ *
+ * @param value - The transaction manifest to set.
+ * @returns The API object for chaining.
+ *
+ * @method toRequestItem
+ * Converts the current state to a SubintentRequestItem.
+ *
+ * @returns The SubintentRequestItem.
+ *
+ * @method rawConfig
+ * Sets the raw configuration for the subintent request.
+ *
+ * @param rawConfig - The raw configuration object, excluding the discriminator.
+ * @returns An object with the toRequestItem method.
+ */
+export const SubintentRequestBuilder = () => {
+  let state: Partial = {
+    discriminator: 'subintent',
+    version: 1,
+    transactionManifestVersion: 1,
+  }
+
+  const setExpiration = (
+    type: 'atTime' | 'secondsAfterSignature',
+    value: number,
+  ) => {
+    state.expiration = {
+      discriminator:
+        type === 'atTime' ? 'expireAtTime' : 'expireAfterSignature',
+      value,
+    }
+    return api
+  }
+
+  const addBlobs = (...values: string[]) => {
+    state.blobs = values
+    return api
+  }
+
+  const message = (value: string) => {
+    state.message = value
+    return api
+  }
+
+  const manifest = (value: string) => {
+    state.transactionManifest = value
+    return api
+  }
+
+  const toRequestItem = () => state as SubintentRequestItem
+
+  const rawConfig = (
+    rawConfig: Omit,
+  ) => {
+    state = { ...rawConfig, discriminator: 'subintent' }
+    return { toRequestItem }
+  }
+
+  const api = {
+    setExpiration,
+    addBlobs,
+    message,
+    toRequestItem,
+  } as const
+
+  return { manifest, rawConfig }
+}
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
index 43e27f89..df5a0878 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
@@ -11,10 +11,7 @@ import {
 import { validateRolaChallenge, type Logger } from '../../helpers'
 import { TransactionStatus } from '../gateway'
 import { ResultAsync, err, ok, okAsync } from 'neverthrow'
-import type {
-  MessageLifeCycleEvent,
-  WalletInteraction,
-} from '../../schemas'
+import type { MessageLifeCycleEvent, WalletInteraction } from '../../schemas'
 import { SdkError } from '../../error'
 import {
   DataRequestBuilderItem,
@@ -310,13 +307,7 @@ export const WalletRequestModule = (input: {
   > => {
     const walletInteraction = walletRequestSdk.createWalletInteraction({
       discriminator: 'preAuthorizationRequest',
-      subintent: {
-        discriminator: 'subintent',
-        blobs: value.blobs,
-        transactionManifest: value.transactionManifest,
-        message: value.message,
-        version: value.version ?? 1,
-      },
+      subintent: value.toRequestItem(),
     })
 
     return addNewRequest('preAuthorizationRequest', walletInteraction, false)
diff --git a/packages/dapp-toolkit/src/schemas/index.ts b/packages/dapp-toolkit/src/schemas/index.ts
index 200a0caa..85c86c4c 100644
--- a/packages/dapp-toolkit/src/schemas/index.ts
+++ b/packages/dapp-toolkit/src/schemas/index.ts
@@ -260,10 +260,10 @@ export type SubintentRequestItem = InferOutput
 export const SubintentRequestItem = object({
   discriminator: literal('subintent'),
   version: number(),
+  transactionManifestVersion: number(),
   transactionManifest: string(),
   blobs: optional(array(string())),
   message: optional(string()),
-  childSubintentHashes: optional(array(string())),
   expiration: optional(union([ExpireAtTime, ExpireAfterSignature])),
 })
 

From c43fdbb3088ca88d24635ffe37ad423858785dc3 Mon Sep 17 00:00:00 2001
From: Alex Stelea 
Date: Thu, 17 Oct 2024 11:50:19 +0100
Subject: [PATCH 10/45] code: move location of inline docs

---
 .../subintent-builder.ts                      | 81 ++++++++++---------
 1 file changed, 41 insertions(+), 40 deletions(-)

diff --git a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts
index aa3a89cc..150a3675 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts
@@ -15,42 +15,7 @@ export type BuildableSubintentRequest = {
  *   .setExpiration('atTime', 1234567890)
  *   .addBlobs('blob1', 'blob2')
  *   .message('This is a message')
- *
- * @method setExpiration
- * Sets the expiration for the subintent request.
- *
- * @param type - The type of expiration, either 'atTime' or 'secondsAfterSignature'.
- * @param value - The value of the expiration. If type is 'atTime', this is a Unix timestamp. If type is 'secondsAfterSignature', this is the number of seconds after the signature is created.
- * @returns The API object for chaining.
- *
- * @method addBlobs
- * Adds blobs to the subintent request.
- *
- * @param values - The blobs to add.
- * @returns The API object for chaining.
- *
- * @method message
- * Sets a message for the subintent request.
- *
- * @param value - The message to set.
- * @returns The API object for chaining.
- *
- * @method manifest
- * Sets the transaction manifest for the subintent request.
- *
- * @param value - The transaction manifest to set.
- * @returns The API object for chaining.
- *
- * @method toRequestItem
- * Converts the current state to a SubintentRequestItem.
- *
- * @returns The SubintentRequestItem.
- *
- * @method rawConfig
- * Sets the raw configuration for the subintent request.
- *
- * @param rawConfig - The raw configuration object, excluding the discriminator.
- * @returns An object with the toRequestItem method.
+
  */
 export const SubintentRequestBuilder = () => {
   let state: Partial = {
@@ -59,6 +24,13 @@ export const SubintentRequestBuilder = () => {
     transactionManifestVersion: 1,
   }
 
+  /**
+   * Sets the expiration for a request.
+   *
+   * @param type - The type of expiration. Can be 'atTime' for a specific time or 'secondsAfterSignature' for a duration after the signature.
+   * @param value - The value associated with the expiration type. For 'atTime', this is a timestamp. For 'secondsAfterSignature', this is the number of seconds.
+   * @returns The API object for chaining.
+   */
   const setExpiration = (
     type: 'atTime' | 'secondsAfterSignature',
     value: number,
@@ -71,23 +43,52 @@ export const SubintentRequestBuilder = () => {
     return api
   }
 
-  const addBlobs = (...values: string[]) => {
-    state.blobs = values
+  /**
+   * Adds the provided blobs to the state.
+   *
+   * @param blobs - A list of blob strings to be added to the state.
+   * @returns The API object for chaining.
+   */
+  const addBlobs = (...blobs: string[]) => {
+    state.blobs = blobs
     return api
   }
 
-  const message = (value: string) => {
-    state.message = value
+  /**
+   * Sets the message to be included in the subintent transaction.
+   *
+   * @param message - The message to be set in the state.
+   * @returns The API object for chaining further calls.
+   */
+  const message = (message: string) => {
+    state.message = message
     return api
   }
 
+  /**
+   * Sets the transaction manifest in the state and returns the API object.
+   *
+   * @param value - The transaction manifest to be set.
+   * @returns The API object for method chaining.
+   */
   const manifest = (value: string) => {
     state.transactionManifest = value
     return api
   }
 
+  /**
+   * Converts the current state to a SubintentRequestItem.
+   *
+   * @returns {SubintentRequestItem} The current state cast as a SubintentRequestItem.
+   */
   const toRequestItem = () => state as SubintentRequestItem
 
+  /**
+   * Sets the raw configuration for the builder.
+   *
+   * @param rawConfig - The raw configuration to set.
+   * @returns The API object for method chaining.
+   */
   const rawConfig = (
     rawConfig: Omit,
   ) => {

From c19ed47a4ef6a87a599bdde5c555e6a6ebb9c235 Mon Sep 17 00:00:00 2001
From: Alex Stelea 
Date: Thu, 17 Oct 2024 15:08:01 +0100
Subject: [PATCH 11/45] fix(rdt): deep link issue for telegram mini apps

---
 examples/simple-dapp/index.html                        |  1 +
 .../transport/radix-connect-relay/deep-link.module.ts  | 10 ++++++++--
 .../transport/radix-connect-relay/helpers/index.ts     |  2 ++
 .../transport/radix-connect-relay/helpers/isTma.ts     |  8 ++++++++
 4 files changed, 19 insertions(+), 2 deletions(-)
 create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/index.ts
 create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/isTma.ts

diff --git a/examples/simple-dapp/index.html b/examples/simple-dapp/index.html
index faa6ed96..a6c1f65a 100644
--- a/examples/simple-dapp/index.html
+++ b/examples/simple-dapp/index.html
@@ -3,6 +3,7 @@
   
     
     
+    
     Simple dApp
   
   
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/deep-link.module.ts b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/deep-link.module.ts
index 6fba667b..57729e22 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/deep-link.module.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/deep-link.module.ts
@@ -3,6 +3,7 @@ import { errAsync, okAsync } from 'neverthrow'
 import { Logger, isMobile } from '../../../../helpers'
 import Bowser from 'bowser'
 import { SdkError } from '../../../../error'
+import { isTMA } from './helpers'
 
 export type DeepLinkModule = ReturnType
 export const DeepLinkModule = (input: {
@@ -13,6 +14,7 @@ export const DeepLinkModule = (input: {
   const userAgent = Bowser.parse(window.navigator.userAgent)
   const { platform } = userAgent
   const logger = input?.logger?.getSubLogger({ name: 'DeepLinkModule' })
+  const isTelegramMiniApp = isTMA(globalThis)
 
   logger?.debug({
     platform,
@@ -34,8 +36,12 @@ export const DeepLinkModule = (input: {
       data: { ...values },
     })
 
-    if (isMobile() && globalThis.location?.href) {
-      globalThis.location.href = outboundUrl.toString()
+    if (isMobile()) {
+      const deepLink = outboundUrl.toString()
+
+      // Telegram Mini App does not support deep linking by changing location.href value
+      if (isTelegramMiniApp) globalThis.open(deepLink, '_blank')
+      else if (globalThis.location?.href) globalThis.location.href = deepLink
 
       return okAsync(undefined)
     }
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/index.ts b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/index.ts
new file mode 100644
index 00000000..502b20aa
--- /dev/null
+++ b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/index.ts
@@ -0,0 +1,2 @@
+export * from './base64url'
+export * from './isTma'
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/isTma.ts b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/isTma.ts
new file mode 100644
index 00000000..f2218c1e
--- /dev/null
+++ b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/isTma.ts
@@ -0,0 +1,8 @@
+/**
+ * Checks if the provided object is a Telegram Mobile App (TMA) global object.
+ *
+ * @param maybeTgGlobalObject - The object to check.
+ * @returns `true` if the object has WebView initialization parameters, otherwise `false`.
+ */
+export const isTMA = (globalObject: any) =>
+  Object.keys(globalObject?.Telegram?.WebView?.initParams || {}).length > 0

From 4b1ade9d732422a009e921f5c81d54bebafe4863 Mon Sep 17 00:00:00 2001
From: Dawid Sowa 
Date: Fri, 18 Oct 2024 18:55:20 +0200
Subject: [PATCH 12/45] chore: add test coverage tool, bump `vitest` dependency

---
 package-lock.json                             | 2000 ++++-------------
 packages/dapp-toolkit/package.json            |    6 +-
 ...ange.test.ts => ecdh-key-exchange.spec.ts} |    0
 packages/dapp-toolkit/vitest.config.ts        |    6 +
 4 files changed, 493 insertions(+), 1519 deletions(-)
 rename packages/dapp-toolkit/src/modules/wallet-request/identity/tests/{ecdh-key-exchange.test.ts => ecdh-key-exchange.spec.ts} (100%)

diff --git a/package-lock.json b/package-lock.json
index 19f3d2bb..6ff2f2d4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3630,18 +3630,18 @@
       }
     },
     "node_modules/@babel/helper-string-parser": {
-      "version": "7.24.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz",
-      "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==",
+      "version": "7.25.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz",
+      "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==",
       "dev": true,
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-validator-identifier": {
-      "version": "7.22.20",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
-      "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
+      "version": "7.25.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz",
+      "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==",
       "dev": true,
       "engines": {
         "node": ">=6.9.0"
@@ -3700,10 +3700,13 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.24.1",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz",
-      "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==",
+      "version": "7.25.8",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz",
+      "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==",
       "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.25.8"
+      },
       "bin": {
         "parser": "bin/babel-parser.js"
       },
@@ -5210,19 +5213,25 @@
       }
     },
     "node_modules/@babel/types": {
-      "version": "7.24.0",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz",
-      "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==",
+      "version": "7.25.8",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz",
+      "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-string-parser": "^7.23.4",
-        "@babel/helper-validator-identifier": "^7.22.20",
+        "@babel/helper-string-parser": "^7.25.7",
+        "@babel/helper-validator-identifier": "^7.25.7",
         "to-fast-properties": "^2.0.0"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
+    "node_modules/@bcoe/v8-coverage": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+      "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+      "dev": true
+    },
     "node_modules/@cdklabs/tskb": {
       "version": "0.0.3",
       "resolved": "https://registry.npmjs.org/@cdklabs/tskb/-/tskb-0.0.3.tgz",
@@ -6515,9 +6524,9 @@
       }
     },
     "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
-      "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+      "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
       "dev": true,
       "engines": {
         "node": ">=12"
@@ -6905,9 +6914,9 @@
       }
     },
     "node_modules/@jridgewell/sourcemap-codec": {
-      "version": "1.4.15",
-      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
-      "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+      "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
       "dev": true
     },
     "node_modules/@jridgewell/trace-mapping": {
@@ -12021,97 +12030,13 @@
       "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
       "dev": true
     },
-    "node_modules/@vitest/expect": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.4.0.tgz",
-      "integrity": "sha512-Jths0sWCJZ8BxjKe+p+eKsoqev1/T8lYcrjavEaz8auEJ4jAVY0GwW3JKmdVU4mmNPLPHixh4GNXP7GFtAiDHA==",
-      "dev": true,
-      "dependencies": {
-        "@vitest/spy": "1.4.0",
-        "@vitest/utils": "1.4.0",
-        "chai": "^4.3.10"
-      },
-      "funding": {
-        "url": "https://opencollective.com/vitest"
-      }
-    },
-    "node_modules/@vitest/runner": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.4.0.tgz",
-      "integrity": "sha512-EDYVSmesqlQ4RD2VvWo3hQgTJ7ZrFQ2VSJdfiJiArkCerDAGeyF1i6dHkmySqk573jLp6d/cfqCN+7wUB5tLgg==",
-      "dev": true,
-      "dependencies": {
-        "@vitest/utils": "1.4.0",
-        "p-limit": "^5.0.0",
-        "pathe": "^1.1.1"
-      },
-      "funding": {
-        "url": "https://opencollective.com/vitest"
-      }
-    },
-    "node_modules/@vitest/runner/node_modules/p-limit": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz",
-      "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==",
-      "dev": true,
-      "dependencies": {
-        "yocto-queue": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=18"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@vitest/runner/node_modules/yocto-queue": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
-      "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
-      "dev": true,
-      "engines": {
-        "node": ">=12.20"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@vitest/snapshot": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.4.0.tgz",
-      "integrity": "sha512-saAFnt5pPIA5qDGxOHxJ/XxhMFKkUSBJmVt5VgDsAqPTX6JP326r5C/c9UuCMPoXNzuudTPsYDZCoJ5ilpqG2A==",
-      "dev": true,
-      "dependencies": {
-        "magic-string": "^0.30.5",
-        "pathe": "^1.1.1",
-        "pretty-format": "^29.7.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/vitest"
-      }
-    },
-    "node_modules/@vitest/spy": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.4.0.tgz",
-      "integrity": "sha512-Ywau/Qs1DzM/8Uc+yA77CwSegizMlcgTJuYGAi0jujOteJOUf1ujunHThYo243KG9nAyWT3L9ifPYZ5+As/+6Q==",
-      "dev": true,
-      "dependencies": {
-        "tinyspy": "^2.2.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/vitest"
-      }
-    },
-    "node_modules/@vitest/utils": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.4.0.tgz",
-      "integrity": "sha512-mx3Yd1/6e2Vt/PUC98DcqTirtfxUyAZ32uK82r8rZzbtBeBo+nqgnjx/LvqQdWsrvNtm14VmurNgcf4nqY5gJg==",
+    "node_modules/@vitest/pretty-format": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz",
+      "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==",
       "dev": true,
       "dependencies": {
-        "diff-sequences": "^29.6.3",
-        "estree-walker": "^3.0.3",
-        "loupe": "^2.3.7",
-        "pretty-format": "^29.7.0"
+        "tinyrainbow": "^1.2.0"
       },
       "funding": {
         "url": "https://opencollective.com/vitest"
@@ -12847,15 +12772,6 @@
         "util": "^0.12.5"
       }
     },
-    "node_modules/assertion-error": {
-      "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": "*"
-      }
-    },
     "node_modules/astral-regex": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
@@ -15176,24 +15092,6 @@
         "readable-stream": "^3.6.0"
       }
     },
-    "node_modules/chai": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz",
-      "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==",
-      "dev": true,
-      "dependencies": {
-        "assertion-error": "^1.1.0",
-        "check-error": "^1.0.3",
-        "deep-eql": "^4.1.3",
-        "get-func-name": "^2.0.2",
-        "loupe": "^2.3.6",
-        "pathval": "^1.1.1",
-        "type-detect": "^4.0.8"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
     "node_modules/chalk": {
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -15217,18 +15115,6 @@
         "node": ">=10"
       }
     },
-    "node_modules/check-error": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
-      "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==",
-      "dev": true,
-      "dependencies": {
-        "get-func-name": "^2.0.2"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
     "node_modules/chokidar": {
       "version": "3.6.0",
       "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@@ -16447,18 +16333,6 @@
       "optional": true,
       "peer": true
     },
-    "node_modules/deep-eql": {
-      "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"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/deep-extend": {
       "version": "0.6.0",
       "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
@@ -18054,15 +17928,6 @@
         "node": "6.* || 8.* || >= 10.*"
       }
     },
-    "node_modules/get-func-name": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
-      "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
-      "dev": true,
-      "engines": {
-        "node": "*"
-      }
-    },
     "node_modules/get-intrinsic": {
       "version": "1.2.4",
       "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
@@ -18247,23 +18112,21 @@
       "dev": true
     },
     "node_modules/glob": {
-      "version": "10.3.10",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
-      "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+      "version": "10.4.5",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+      "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
       "dev": true,
       "dependencies": {
         "foreground-child": "^3.1.0",
-        "jackspeak": "^2.3.5",
-        "minimatch": "^9.0.1",
-        "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
-        "path-scurry": "^1.10.1"
+        "jackspeak": "^3.1.2",
+        "minimatch": "^9.0.4",
+        "minipass": "^7.1.2",
+        "package-json-from-dist": "^1.0.0",
+        "path-scurry": "^1.11.1"
       },
       "bin": {
         "glob": "dist/esm/bin.mjs"
       },
-      "engines": {
-        "node": ">=16 || 14 >=14.17"
-      },
       "funding": {
         "url": "https://github.com/sponsors/isaacs"
       }
@@ -18647,6 +18510,12 @@
         "node": ">=12"
       }
     },
+    "node_modules/html-escaper": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+      "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+      "dev": true
+    },
     "node_modules/html-minifier": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz",
@@ -19498,16 +19367,90 @@
         "semver": "bin/semver.js"
       }
     },
-    "node_modules/jackspeak": {
-      "version": "2.3.6",
-      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
-      "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+    "node_modules/istanbul-lib-report": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+      "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
       "dev": true,
       "dependencies": {
-        "@isaacs/cliui": "^8.0.2"
+        "istanbul-lib-coverage": "^3.0.0",
+        "make-dir": "^4.0.0",
+        "supports-color": "^7.1.0"
       },
       "engines": {
-        "node": ">=14"
+        "node": ">=10"
+      }
+    },
+    "node_modules/istanbul-lib-report/node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-report/node_modules/make-dir": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+      "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+      "dev": true,
+      "dependencies": {
+        "semver": "^7.5.3"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/istanbul-lib-report/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-source-maps": {
+      "version": "5.0.6",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz",
+      "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/trace-mapping": "^0.3.23",
+        "debug": "^4.1.1",
+        "istanbul-lib-coverage": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/istanbul-reports": {
+      "version": "3.1.7",
+      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
+      "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
+      "dev": true,
+      "dependencies": {
+        "html-escaper": "^2.0.0",
+        "istanbul-lib-report": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/jackspeak": {
+      "version": "3.4.3",
+      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+      "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+      "dev": true,
+      "dependencies": {
+        "@isaacs/cliui": "^8.0.2"
       },
       "funding": {
         "url": "https://github.com/sponsors/isaacs"
@@ -20211,12 +20154,6 @@
         "node": ">=6"
       }
     },
-    "node_modules/jsonc-parser": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
-      "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
-      "dev": true
-    },
     "node_modules/jsonfile": {
       "version": "6.1.0",
       "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
@@ -20566,22 +20503,6 @@
         "node": ">=6.11.5"
       }
     },
-    "node_modules/local-pkg": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz",
-      "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==",
-      "dev": true,
-      "dependencies": {
-        "mlly": "^1.4.2",
-        "pkg-types": "^1.0.3"
-      },
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      }
-    },
     "node_modules/locate-path": {
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -20793,15 +20714,6 @@
         "loose-envify": "cli.js"
       }
     },
-    "node_modules/loupe": {
-      "version": "2.3.7",
-      "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
-      "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==",
-      "dev": true,
-      "dependencies": {
-        "get-func-name": "^2.0.1"
-      }
-    },
     "node_modules/lower-case": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
@@ -20818,15 +20730,23 @@
       }
     },
     "node_modules/magic-string": {
-      "version": "0.30.8",
-      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
-      "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
+      "version": "0.30.12",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
+      "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==",
       "dev": true,
       "dependencies": {
-        "@jridgewell/sourcemap-codec": "^1.4.15"
-      },
-      "engines": {
-        "node": ">=12"
+        "@jridgewell/sourcemap-codec": "^1.5.0"
+      }
+    },
+    "node_modules/magicast": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz",
+      "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/parser": "^7.25.4",
+        "@babel/types": "^7.25.4",
+        "source-map-js": "^1.2.0"
       }
     },
     "node_modules/make-dir": {
@@ -21191,9 +21111,9 @@
       "dev": true
     },
     "node_modules/minimatch": {
-      "version": "9.0.3",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
-      "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+      "version": "9.0.5",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
       "dev": true,
       "dependencies": {
         "brace-expansion": "^2.0.1"
@@ -21238,9 +21158,9 @@
       }
     },
     "node_modules/minipass": {
-      "version": "7.0.4",
-      "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
-      "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+      "version": "7.1.2",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+      "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
       "dev": true,
       "engines": {
         "node": ">=16 || 14 >=14.17"
@@ -21295,18 +21215,6 @@
       "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
       "dev": true
     },
-    "node_modules/mlly": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz",
-      "integrity": "sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==",
-      "dev": true,
-      "dependencies": {
-        "acorn": "^8.11.3",
-        "pathe": "^1.1.2",
-        "pkg-types": "^1.0.3",
-        "ufo": "^1.3.2"
-      }
-    },
     "node_modules/mnemonist": {
       "version": "0.39.8",
       "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.8.tgz",
@@ -25520,6 +25428,12 @@
         "node": ">=6"
       }
     },
+    "node_modules/package-json-from-dist": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+      "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+      "dev": true
+    },
     "node_modules/pako": {
       "version": "0.2.9",
       "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
@@ -25668,29 +25582,26 @@
       "dev": true
     },
     "node_modules/path-scurry": {
-      "version": "1.10.1",
-      "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
-      "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+      "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
       "dev": true,
       "dependencies": {
-        "lru-cache": "^9.1.1 || ^10.0.0",
+        "lru-cache": "^10.2.0",
         "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
       },
       "engines": {
-        "node": ">=16 || 14 >=14.17"
+        "node": ">=16 || 14 >=14.18"
       },
       "funding": {
         "url": "https://github.com/sponsors/isaacs"
       }
     },
     "node_modules/path-scurry/node_modules/lru-cache": {
-      "version": "10.2.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
-      "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
-      "dev": true,
-      "engines": {
-        "node": "14 || >=16.14"
-      }
+      "version": "10.4.3",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+      "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+      "dev": true
     },
     "node_modules/path-to-regexp": {
       "version": "0.1.7",
@@ -25713,15 +25624,6 @@
       "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
       "dev": true
     },
-    "node_modules/pathval": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
-      "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
-      "dev": true,
-      "engines": {
-        "node": "*"
-      }
-    },
     "node_modules/peek-stream": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz",
@@ -25913,17 +25815,6 @@
         "node": ">=10"
       }
     },
-    "node_modules/pkg-types": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz",
-      "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==",
-      "dev": true,
-      "dependencies": {
-        "jsonc-parser": "^3.2.0",
-        "mlly": "^1.2.0",
-        "pathe": "^1.1.0"
-      }
-    },
     "node_modules/pkg-up": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
@@ -29460,24 +29351,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/strip-literal": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.0.0.tgz",
-      "integrity": "sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==",
-      "dev": true,
-      "dependencies": {
-        "js-tokens": "^8.0.2"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      }
-    },
-    "node_modules/strip-literal/node_modules/js-tokens": {
-      "version": "8.0.3",
-      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.3.tgz",
-      "integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==",
-      "dev": true
-    },
     "node_modules/strnum": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
@@ -30151,9 +30024,15 @@
       "dev": true
     },
     "node_modules/tinybench": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.6.0.tgz",
-      "integrity": "sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==",
+      "version": "2.9.0",
+      "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
+      "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
+      "dev": true
+    },
+    "node_modules/tinyexec": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz",
+      "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==",
       "dev": true
     },
     "node_modules/tinyglobby": {
@@ -30195,19 +30074,10 @@
         "url": "https://github.com/sponsors/jonschlinkert"
       }
     },
-    "node_modules/tinypool": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.2.tgz",
-      "integrity": "sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/tinyspy": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz",
-      "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==",
+    "node_modules/tinyrainbow": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz",
+      "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==",
       "dev": true,
       "engines": {
         "node": ">=14.0.0"
@@ -30974,15 +30844,6 @@
         "win32"
       ]
     },
-    "node_modules/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==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
     "node_modules/type-fest": {
       "version": "4.15.0",
       "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.15.0.tgz",
@@ -31519,489 +31380,6 @@
         }
       }
     },
-    "node_modules/vite-node": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.4.0.tgz",
-      "integrity": "sha512-VZDAseqjrHgNd4Kh8icYHWzTKSCZMhia7GyHfhtzLW33fZlG9SwsB6CEhgyVOWkJfJ2pFLrp/Gj1FSfAiqH9Lw==",
-      "dev": true,
-      "dependencies": {
-        "cac": "^6.7.14",
-        "debug": "^4.3.4",
-        "pathe": "^1.1.1",
-        "picocolors": "^1.0.0",
-        "vite": "^5.0.0"
-      },
-      "bin": {
-        "vite-node": "vite-node.mjs"
-      },
-      "engines": {
-        "node": "^18.0.0 || >=20.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/vitest"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/aix-ppc64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
-      "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
-      "cpu": [
-        "ppc64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "aix"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/android-arm": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
-      "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/android-arm64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
-      "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/android-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
-      "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/darwin-arm64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
-      "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/darwin-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
-      "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/freebsd-arm64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
-      "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/freebsd-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
-      "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/linux-arm": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
-      "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/linux-arm64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
-      "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/linux-ia32": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
-      "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
-      "cpu": [
-        "ia32"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/linux-loong64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
-      "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
-      "cpu": [
-        "loong64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/linux-mips64el": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
-      "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
-      "cpu": [
-        "mips64el"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/linux-ppc64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
-      "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
-      "cpu": [
-        "ppc64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/linux-riscv64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
-      "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
-      "cpu": [
-        "riscv64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/linux-s390x": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
-      "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
-      "cpu": [
-        "s390x"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/linux-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
-      "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/netbsd-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
-      "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "netbsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/openbsd-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
-      "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "openbsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/sunos-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
-      "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "sunos"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/win32-arm64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
-      "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/win32-ia32": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
-      "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
-      "cpu": [
-        "ia32"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/@esbuild/win32-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
-      "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vite-node/node_modules/esbuild": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
-      "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
-      "dev": true,
-      "hasInstallScript": true,
-      "bin": {
-        "esbuild": "bin/esbuild"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "optionalDependencies": {
-        "@esbuild/aix-ppc64": "0.20.2",
-        "@esbuild/android-arm": "0.20.2",
-        "@esbuild/android-arm64": "0.20.2",
-        "@esbuild/android-x64": "0.20.2",
-        "@esbuild/darwin-arm64": "0.20.2",
-        "@esbuild/darwin-x64": "0.20.2",
-        "@esbuild/freebsd-arm64": "0.20.2",
-        "@esbuild/freebsd-x64": "0.20.2",
-        "@esbuild/linux-arm": "0.20.2",
-        "@esbuild/linux-arm64": "0.20.2",
-        "@esbuild/linux-ia32": "0.20.2",
-        "@esbuild/linux-loong64": "0.20.2",
-        "@esbuild/linux-mips64el": "0.20.2",
-        "@esbuild/linux-ppc64": "0.20.2",
-        "@esbuild/linux-riscv64": "0.20.2",
-        "@esbuild/linux-s390x": "0.20.2",
-        "@esbuild/linux-x64": "0.20.2",
-        "@esbuild/netbsd-x64": "0.20.2",
-        "@esbuild/openbsd-x64": "0.20.2",
-        "@esbuild/sunos-x64": "0.20.2",
-        "@esbuild/win32-arm64": "0.20.2",
-        "@esbuild/win32-ia32": "0.20.2",
-        "@esbuild/win32-x64": "0.20.2"
-      }
-    },
-    "node_modules/vite-node/node_modules/vite": {
-      "version": "5.2.8",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz",
-      "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==",
-      "dev": true,
-      "dependencies": {
-        "esbuild": "^0.20.1",
-        "postcss": "^8.4.38",
-        "rollup": "^4.13.0"
-      },
-      "bin": {
-        "vite": "bin/vite.js"
-      },
-      "engines": {
-        "node": "^18.0.0 || >=20.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/vitejs/vite?sponsor=1"
-      },
-      "optionalDependencies": {
-        "fsevents": "~2.3.3"
-      },
-      "peerDependencies": {
-        "@types/node": "^18.0.0 || >=20.0.0",
-        "less": "*",
-        "lightningcss": "^1.21.0",
-        "sass": "*",
-        "stylus": "*",
-        "sugarss": "*",
-        "terser": "^5.4.0"
-      },
-      "peerDependenciesMeta": {
-        "@types/node": {
-          "optional": true
-        },
-        "less": {
-          "optional": true
-        },
-        "lightningcss": {
-          "optional": true
-        },
-        "sass": {
-          "optional": true
-        },
-        "stylus": {
-          "optional": true
-        },
-        "sugarss": {
-          "optional": true
-        },
-        "terser": {
-          "optional": true
-        }
-      }
-    },
     "node_modules/vite-plugin-ngrok": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/vite-plugin-ngrok/-/vite-plugin-ngrok-1.0.0.tgz",
@@ -32031,693 +31409,6 @@
         "fsevents": "~2.3.2"
       }
     },
-    "node_modules/vitest": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.4.0.tgz",
-      "integrity": "sha512-gujzn0g7fmwf83/WzrDTnncZt2UiXP41mHuFYFrdwaLRVQ6JYQEiME2IfEjU3vcFL3VKa75XhI3lFgn+hfVsQw==",
-      "dev": true,
-      "dependencies": {
-        "@vitest/expect": "1.4.0",
-        "@vitest/runner": "1.4.0",
-        "@vitest/snapshot": "1.4.0",
-        "@vitest/spy": "1.4.0",
-        "@vitest/utils": "1.4.0",
-        "acorn-walk": "^8.3.2",
-        "chai": "^4.3.10",
-        "debug": "^4.3.4",
-        "execa": "^8.0.1",
-        "local-pkg": "^0.5.0",
-        "magic-string": "^0.30.5",
-        "pathe": "^1.1.1",
-        "picocolors": "^1.0.0",
-        "std-env": "^3.5.0",
-        "strip-literal": "^2.0.0",
-        "tinybench": "^2.5.1",
-        "tinypool": "^0.8.2",
-        "vite": "^5.0.0",
-        "vite-node": "1.4.0",
-        "why-is-node-running": "^2.2.2"
-      },
-      "bin": {
-        "vitest": "vitest.mjs"
-      },
-      "engines": {
-        "node": "^18.0.0 || >=20.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/vitest"
-      },
-      "peerDependencies": {
-        "@edge-runtime/vm": "*",
-        "@types/node": "^18.0.0 || >=20.0.0",
-        "@vitest/browser": "1.4.0",
-        "@vitest/ui": "1.4.0",
-        "happy-dom": "*",
-        "jsdom": "*"
-      },
-      "peerDependenciesMeta": {
-        "@edge-runtime/vm": {
-          "optional": true
-        },
-        "@types/node": {
-          "optional": true
-        },
-        "@vitest/browser": {
-          "optional": true
-        },
-        "@vitest/ui": {
-          "optional": true
-        },
-        "happy-dom": {
-          "optional": true
-        },
-        "jsdom": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/vitest-mock-extended": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/vitest-mock-extended/-/vitest-mock-extended-1.3.1.tgz",
-      "integrity": "sha512-OpghYjh4BDuQ/Mzs3lFMQ1QRk9D8/2O9T47MLUA5eLn7K4RWIy+MfIivYOWEyxjTENjsBnzgMihDjyNalN/K0Q==",
-      "dev": true,
-      "dependencies": {
-        "ts-essentials": "^9.3.2"
-      },
-      "peerDependencies": {
-        "typescript": "3.x || 4.x || 5.x",
-        "vitest": ">=0.31.1"
-      }
-    },
-    "node_modules/vitest-mock-extended/node_modules/ts-essentials": {
-      "version": "9.4.1",
-      "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-9.4.1.tgz",
-      "integrity": "sha512-oke0rI2EN9pzHsesdmrOrnqv1eQODmJpd/noJjwj2ZPC3Z4N2wbjrOEqnsEgmvlO2+4fBb0a794DCna2elEVIQ==",
-      "dev": true,
-      "peerDependencies": {
-        "typescript": ">=4.1.0"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/aix-ppc64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
-      "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
-      "cpu": [
-        "ppc64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "aix"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/android-arm": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
-      "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/android-arm64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
-      "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/android-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
-      "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/darwin-arm64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
-      "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/darwin-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
-      "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
-      "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/freebsd-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
-      "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/linux-arm": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
-      "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/linux-arm64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
-      "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/linux-ia32": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
-      "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
-      "cpu": [
-        "ia32"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/linux-loong64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
-      "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
-      "cpu": [
-        "loong64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/linux-mips64el": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
-      "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
-      "cpu": [
-        "mips64el"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/linux-ppc64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
-      "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
-      "cpu": [
-        "ppc64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/linux-riscv64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
-      "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
-      "cpu": [
-        "riscv64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/linux-s390x": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
-      "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
-      "cpu": [
-        "s390x"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/linux-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
-      "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/netbsd-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
-      "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "netbsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/openbsd-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
-      "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "openbsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/sunos-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
-      "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "sunos"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/win32-arm64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
-      "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/win32-ia32": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
-      "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
-      "cpu": [
-        "ia32"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/@esbuild/win32-x64": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
-      "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/vitest/node_modules/esbuild": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
-      "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
-      "dev": true,
-      "hasInstallScript": true,
-      "bin": {
-        "esbuild": "bin/esbuild"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "optionalDependencies": {
-        "@esbuild/aix-ppc64": "0.20.2",
-        "@esbuild/android-arm": "0.20.2",
-        "@esbuild/android-arm64": "0.20.2",
-        "@esbuild/android-x64": "0.20.2",
-        "@esbuild/darwin-arm64": "0.20.2",
-        "@esbuild/darwin-x64": "0.20.2",
-        "@esbuild/freebsd-arm64": "0.20.2",
-        "@esbuild/freebsd-x64": "0.20.2",
-        "@esbuild/linux-arm": "0.20.2",
-        "@esbuild/linux-arm64": "0.20.2",
-        "@esbuild/linux-ia32": "0.20.2",
-        "@esbuild/linux-loong64": "0.20.2",
-        "@esbuild/linux-mips64el": "0.20.2",
-        "@esbuild/linux-ppc64": "0.20.2",
-        "@esbuild/linux-riscv64": "0.20.2",
-        "@esbuild/linux-s390x": "0.20.2",
-        "@esbuild/linux-x64": "0.20.2",
-        "@esbuild/netbsd-x64": "0.20.2",
-        "@esbuild/openbsd-x64": "0.20.2",
-        "@esbuild/sunos-x64": "0.20.2",
-        "@esbuild/win32-arm64": "0.20.2",
-        "@esbuild/win32-ia32": "0.20.2",
-        "@esbuild/win32-x64": "0.20.2"
-      }
-    },
-    "node_modules/vitest/node_modules/execa": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
-      "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
-      "dev": true,
-      "dependencies": {
-        "cross-spawn": "^7.0.3",
-        "get-stream": "^8.0.1",
-        "human-signals": "^5.0.0",
-        "is-stream": "^3.0.0",
-        "merge-stream": "^2.0.0",
-        "npm-run-path": "^5.1.0",
-        "onetime": "^6.0.0",
-        "signal-exit": "^4.1.0",
-        "strip-final-newline": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=16.17"
-      },
-      "funding": {
-        "url": "https://github.com/sindresorhus/execa?sponsor=1"
-      }
-    },
-    "node_modules/vitest/node_modules/get-stream": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
-      "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
-      "dev": true,
-      "engines": {
-        "node": ">=16"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/vitest/node_modules/human-signals": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
-      "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=16.17.0"
-      }
-    },
-    "node_modules/vitest/node_modules/is-stream": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
-      "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
-      "dev": true,
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/vitest/node_modules/mimic-fn": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
-      "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/vitest/node_modules/npm-run-path": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
-      "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
-      "dev": true,
-      "dependencies": {
-        "path-key": "^4.0.0"
-      },
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/vitest/node_modules/onetime": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
-      "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
-      "dev": true,
-      "dependencies": {
-        "mimic-fn": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/vitest/node_modules/path-key": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
-      "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/vitest/node_modules/signal-exit": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
-      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
-      "dev": true,
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/vitest/node_modules/strip-final-newline": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
-      "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/vitest/node_modules/vite": {
-      "version": "5.2.8",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz",
-      "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==",
-      "dev": true,
-      "dependencies": {
-        "esbuild": "^0.20.1",
-        "postcss": "^8.4.38",
-        "rollup": "^4.13.0"
-      },
-      "bin": {
-        "vite": "bin/vite.js"
-      },
-      "engines": {
-        "node": "^18.0.0 || >=20.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/vitejs/vite?sponsor=1"
-      },
-      "optionalDependencies": {
-        "fsevents": "~2.3.3"
-      },
-      "peerDependencies": {
-        "@types/node": "^18.0.0 || >=20.0.0",
-        "less": "*",
-        "lightningcss": "^1.21.0",
-        "sass": "*",
-        "stylus": "*",
-        "sugarss": "*",
-        "terser": "^5.4.0"
-      },
-      "peerDependenciesMeta": {
-        "@types/node": {
-          "optional": true
-        },
-        "less": {
-          "optional": true
-        },
-        "lightningcss": {
-          "optional": true
-        },
-        "sass": {
-          "optional": true
-        },
-        "stylus": {
-          "optional": true
-        },
-        "sugarss": {
-          "optional": true
-        },
-        "terser": {
-          "optional": true
-        }
-      }
-    },
     "node_modules/w3c-xmlserializer": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
@@ -33035,9 +31726,9 @@
       }
     },
     "node_modules/why-is-node-running": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz",
-      "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
+      "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
       "dev": true,
       "dependencies": {
         "siginfo": "^2.0.0",
@@ -33627,14 +32318,14 @@
         "@radixdlt/connect-button": "*",
         "@saithodev/semantic-release-backmerge": "^3.2.1",
         "@semantic-release/exec": "^6.0.3",
+        "@vitest/coverage-v8": "^2.1.3",
         "radix-connect-common": "*",
         "semantic-release": "^23.0.0",
         "semantic-release-replace-plugin": "^1.2.7",
         "tsup": "^8.3.0",
         "typescript": "^5.4.4",
         "vite-plugin-singlefile": "^2.0.2",
-        "vitest": "^1.4.0",
-        "vitest-mock-extended": "^1.3.1"
+        "vitest": "^2.1.3"
       },
       "engines": {
         "node": ">=18"
@@ -33652,7 +32343,6 @@
       "os": [
         "aix"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33669,7 +32359,6 @@
       "os": [
         "android"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33686,7 +32375,6 @@
       "os": [
         "android"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33703,7 +32391,6 @@
       "os": [
         "android"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33720,7 +32407,6 @@
       "os": [
         "darwin"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33737,7 +32423,6 @@
       "os": [
         "darwin"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33754,7 +32439,6 @@
       "os": [
         "freebsd"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33771,7 +32455,6 @@
       "os": [
         "freebsd"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33788,7 +32471,6 @@
       "os": [
         "linux"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33805,7 +32487,6 @@
       "os": [
         "linux"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33822,7 +32503,6 @@
       "os": [
         "linux"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33839,7 +32519,6 @@
       "os": [
         "linux"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33856,7 +32535,6 @@
       "os": [
         "linux"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33873,7 +32551,6 @@
       "os": [
         "linux"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33890,7 +32567,6 @@
       "os": [
         "linux"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33907,7 +32583,6 @@
       "os": [
         "linux"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33924,7 +32599,6 @@
       "os": [
         "linux"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33941,7 +32615,6 @@
       "os": [
         "netbsd"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33958,7 +32631,6 @@
       "os": [
         "openbsd"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33975,7 +32647,6 @@
       "os": [
         "sunos"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -33992,7 +32663,6 @@
       "os": [
         "win32"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -34009,7 +32679,6 @@
       "os": [
         "win32"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -34026,7 +32695,6 @@
       "os": [
         "win32"
       ],
-      "peer": true,
       "engines": {
         "node": ">=12"
       }
@@ -34306,6 +32974,133 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "packages/dapp-toolkit/node_modules/@vitest/coverage-v8": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.3.tgz",
+      "integrity": "sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==",
+      "dev": true,
+      "dependencies": {
+        "@ampproject/remapping": "^2.3.0",
+        "@bcoe/v8-coverage": "^0.2.3",
+        "debug": "^4.3.6",
+        "istanbul-lib-coverage": "^3.2.2",
+        "istanbul-lib-report": "^3.0.1",
+        "istanbul-lib-source-maps": "^5.0.6",
+        "istanbul-reports": "^3.1.7",
+        "magic-string": "^0.30.11",
+        "magicast": "^0.3.4",
+        "std-env": "^3.7.0",
+        "test-exclude": "^7.0.1",
+        "tinyrainbow": "^1.2.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/vitest"
+      },
+      "peerDependencies": {
+        "@vitest/browser": "2.1.3",
+        "vitest": "2.1.3"
+      },
+      "peerDependenciesMeta": {
+        "@vitest/browser": {
+          "optional": true
+        }
+      }
+    },
+    "packages/dapp-toolkit/node_modules/@vitest/expect": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz",
+      "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==",
+      "dev": true,
+      "dependencies": {
+        "@vitest/spy": "2.1.3",
+        "@vitest/utils": "2.1.3",
+        "chai": "^5.1.1",
+        "tinyrainbow": "^1.2.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/vitest"
+      }
+    },
+    "packages/dapp-toolkit/node_modules/@vitest/mocker": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz",
+      "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==",
+      "dev": true,
+      "dependencies": {
+        "@vitest/spy": "2.1.3",
+        "estree-walker": "^3.0.3",
+        "magic-string": "^0.30.11"
+      },
+      "funding": {
+        "url": "https://opencollective.com/vitest"
+      },
+      "peerDependencies": {
+        "@vitest/spy": "2.1.3",
+        "msw": "^2.3.5",
+        "vite": "^5.0.0"
+      },
+      "peerDependenciesMeta": {
+        "msw": {
+          "optional": true
+        },
+        "vite": {
+          "optional": true
+        }
+      }
+    },
+    "packages/dapp-toolkit/node_modules/@vitest/runner": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz",
+      "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==",
+      "dev": true,
+      "dependencies": {
+        "@vitest/utils": "2.1.3",
+        "pathe": "^1.1.2"
+      },
+      "funding": {
+        "url": "https://opencollective.com/vitest"
+      }
+    },
+    "packages/dapp-toolkit/node_modules/@vitest/snapshot": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz",
+      "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==",
+      "dev": true,
+      "dependencies": {
+        "@vitest/pretty-format": "2.1.3",
+        "magic-string": "^0.30.11",
+        "pathe": "^1.1.2"
+      },
+      "funding": {
+        "url": "https://opencollective.com/vitest"
+      }
+    },
+    "packages/dapp-toolkit/node_modules/@vitest/spy": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz",
+      "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==",
+      "dev": true,
+      "dependencies": {
+        "tinyspy": "^3.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/vitest"
+      }
+    },
+    "packages/dapp-toolkit/node_modules/@vitest/utils": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz",
+      "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==",
+      "dev": true,
+      "dependencies": {
+        "@vitest/pretty-format": "2.1.3",
+        "loupe": "^3.1.1",
+        "tinyrainbow": "^1.2.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/vitest"
+      }
+    },
     "packages/dapp-toolkit/node_modules/aggregate-error": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz",
@@ -34322,6 +33117,15 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "packages/dapp-toolkit/node_modules/assertion-error": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+      "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "packages/dapp-toolkit/node_modules/before-after-hook": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz",
@@ -34351,6 +33155,22 @@
         "ieee754": "^1.2.1"
       }
     },
+    "packages/dapp-toolkit/node_modules/chai": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz",
+      "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==",
+      "dev": true,
+      "dependencies": {
+        "assertion-error": "^2.0.1",
+        "check-error": "^2.1.1",
+        "deep-eql": "^5.0.1",
+        "loupe": "^3.1.0",
+        "pathval": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "packages/dapp-toolkit/node_modules/chalk": {
       "version": "5.3.0",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
@@ -34363,6 +33183,15 @@
         "url": "https://github.com/chalk/chalk?sponsor=1"
       }
     },
+    "packages/dapp-toolkit/node_modules/check-error": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
+      "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 16"
+      }
+    },
     "packages/dapp-toolkit/node_modules/clean-stack": {
       "version": "5.2.0",
       "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz",
@@ -34463,6 +33292,15 @@
         }
       }
     },
+    "packages/dapp-toolkit/node_modules/deep-eql": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
+      "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "packages/dapp-toolkit/node_modules/env-ci": {
       "version": "11.0.0",
       "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.0.0.tgz",
@@ -34482,7 +33320,6 @@
       "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
       "dev": true,
       "hasInstallScript": true,
-      "peer": true,
       "bin": {
         "esbuild": "bin/esbuild"
       },
@@ -34722,6 +33559,12 @@
         "@types/trusted-types": "^2.0.2"
       }
     },
+    "packages/dapp-toolkit/node_modules/loupe": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz",
+      "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==",
+      "dev": true
+    },
     "packages/dapp-toolkit/node_modules/lru-cache": {
       "version": "10.2.0",
       "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
@@ -37680,6 +36523,15 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "packages/dapp-toolkit/node_modules/pathval": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz",
+      "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 14.16"
+      }
+    },
     "packages/dapp-toolkit/node_modules/read-pkg": {
       "version": "9.0.1",
       "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz",
@@ -37856,6 +36708,20 @@
         "node": ">=14.18"
       }
     },
+    "packages/dapp-toolkit/node_modules/test-exclude": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz",
+      "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==",
+      "dev": true,
+      "dependencies": {
+        "@istanbuljs/schema": "^0.1.2",
+        "glob": "^10.4.1",
+        "minimatch": "^9.0.4"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
     "packages/dapp-toolkit/node_modules/text-extensions": {
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz",
@@ -37868,6 +36734,24 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "packages/dapp-toolkit/node_modules/tinypool": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz",
+      "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==",
+      "dev": true,
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      }
+    },
+    "packages/dapp-toolkit/node_modules/tinyspy": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz",
+      "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=14.0.0"
+      }
+    },
     "packages/dapp-toolkit/node_modules/tslog": {
       "version": "4.8.0",
       "resolved": "https://registry.npmjs.org/tslog/-/tslog-4.8.0.tgz",
@@ -37902,7 +36786,6 @@
       "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz",
       "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==",
       "dev": true,
-      "peer": true,
       "dependencies": {
         "esbuild": "^0.21.3",
         "postcss": "^8.4.43",
@@ -37957,6 +36840,27 @@
         }
       }
     },
+    "packages/dapp-toolkit/node_modules/vite-node": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz",
+      "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==",
+      "dev": true,
+      "dependencies": {
+        "cac": "^6.7.14",
+        "debug": "^4.3.6",
+        "pathe": "^1.1.2",
+        "vite": "^5.0.0"
+      },
+      "bin": {
+        "vite-node": "vite-node.mjs"
+      },
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/vitest"
+      }
+    },
     "packages/dapp-toolkit/node_modules/vite-plugin-singlefile": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/vite-plugin-singlefile/-/vite-plugin-singlefile-2.0.2.tgz",
@@ -37973,6 +36877,70 @@
         "vite": "^5.3.1"
       }
     },
+    "packages/dapp-toolkit/node_modules/vitest": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz",
+      "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==",
+      "dev": true,
+      "dependencies": {
+        "@vitest/expect": "2.1.3",
+        "@vitest/mocker": "2.1.3",
+        "@vitest/pretty-format": "^2.1.3",
+        "@vitest/runner": "2.1.3",
+        "@vitest/snapshot": "2.1.3",
+        "@vitest/spy": "2.1.3",
+        "@vitest/utils": "2.1.3",
+        "chai": "^5.1.1",
+        "debug": "^4.3.6",
+        "magic-string": "^0.30.11",
+        "pathe": "^1.1.2",
+        "std-env": "^3.7.0",
+        "tinybench": "^2.9.0",
+        "tinyexec": "^0.3.0",
+        "tinypool": "^1.0.0",
+        "tinyrainbow": "^1.2.0",
+        "vite": "^5.0.0",
+        "vite-node": "2.1.3",
+        "why-is-node-running": "^2.3.0"
+      },
+      "bin": {
+        "vitest": "vitest.mjs"
+      },
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/vitest"
+      },
+      "peerDependencies": {
+        "@edge-runtime/vm": "*",
+        "@types/node": "^18.0.0 || >=20.0.0",
+        "@vitest/browser": "2.1.3",
+        "@vitest/ui": "2.1.3",
+        "happy-dom": "*",
+        "jsdom": "*"
+      },
+      "peerDependenciesMeta": {
+        "@edge-runtime/vm": {
+          "optional": true
+        },
+        "@types/node": {
+          "optional": true
+        },
+        "@vitest/browser": {
+          "optional": true
+        },
+        "@vitest/ui": {
+          "optional": true
+        },
+        "happy-dom": {
+          "optional": true
+        },
+        "jsdom": {
+          "optional": true
+        }
+      }
+    },
     "packages/eslint-config": {
       "name": "@repo/eslint-config",
       "version": "0.0.0",
diff --git a/packages/dapp-toolkit/package.json b/packages/dapp-toolkit/package.json
index 9285b12c..96dd1fe4 100644
--- a/packages/dapp-toolkit/package.json
+++ b/packages/dapp-toolkit/package.json
@@ -56,7 +56,7 @@
     "dev": "tsup --watch",
     "build": "tsup && npm run build:single",
     "build:single": "vite build --config vite-single-file.config.ts && cp dist/radix-dapp-toolkit.bundle.umd.cjs ../../examples/cdn",
-    "test": "vitest",
+    "test": "vitest run --coverage",
     "test:watch": "vitest --watch"
   },
   "dependencies": {
@@ -78,14 +78,14 @@
     "@radixdlt/connect-button": "*",
     "@saithodev/semantic-release-backmerge": "^3.2.1",
     "@semantic-release/exec": "^6.0.3",
+    "@vitest/coverage-v8": "^2.1.3",
     "radix-connect-common": "*",
     "semantic-release": "^23.0.0",
     "semantic-release-replace-plugin": "^1.2.7",
     "tsup": "^8.3.0",
     "typescript": "^5.4.4",
     "vite-plugin-singlefile": "^2.0.2",
-    "vitest": "^1.4.0",
-    "vitest-mock-extended": "^1.3.1"
+    "vitest": "^2.1.3"
   },
   "repository": {
     "type": "git",
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/identity/tests/ecdh-key-exchange.test.ts b/packages/dapp-toolkit/src/modules/wallet-request/identity/tests/ecdh-key-exchange.spec.ts
similarity index 100%
rename from packages/dapp-toolkit/src/modules/wallet-request/identity/tests/ecdh-key-exchange.test.ts
rename to packages/dapp-toolkit/src/modules/wallet-request/identity/tests/ecdh-key-exchange.spec.ts
diff --git a/packages/dapp-toolkit/vitest.config.ts b/packages/dapp-toolkit/vitest.config.ts
index 95c5d26e..466ada91 100644
--- a/packages/dapp-toolkit/vitest.config.ts
+++ b/packages/dapp-toolkit/vitest.config.ts
@@ -4,5 +4,11 @@ import { defineConfig } from 'vitest/config'
 export default defineConfig({
   test: {
     environment: 'jsdom',
+    coverage: {
+      provider: 'v8',
+      include: ['src/**/*.ts'],
+      reporter: ['lcov', 'text', 'html'],
+    },
+    include: ['src/**/*.spec.ts'],
   },
 })

From 38208e7d0c06d9684c9ac641dd44b4d75c2bfc5a Mon Sep 17 00:00:00 2001
From: Dawid Sowa 
Date: Tue, 22 Oct 2024 14:30:02 +0200
Subject: [PATCH 13/45] fix: remove `proofOfOwnership` from
 `unathorizedRequest`

Proof Of Ownership can only be part of authorized request
---
 .../data-request/helpers/to-wallet-request.ts   |  2 +-
 .../transformations/rdt-to-wallet.ts            |  9 +++++----
 .../transformations/wallet-to-rdt.ts            | 17 +++++++++--------
 .../modules/wallet-request/wallet-request.ts    |  4 +++-
 packages/dapp-toolkit/src/schemas/index.ts      |  2 --
 5 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/helpers/to-wallet-request.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/helpers/to-wallet-request.ts
index 4b62c66b..ea9ada8b 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/helpers/to-wallet-request.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/helpers/to-wallet-request.ts
@@ -48,7 +48,7 @@ export const toWalletRequest = ({
           oneTime,
         }
 
-      if (!oneTime) {
+      if (!oneTime || dataRequestState.proofOfOwnership) {
         const persona = walletData.persona
 
         if (walletData.persona) draft.persona = persona
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts
index f88cf299..333d2321 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts
@@ -51,7 +51,7 @@ export const TransformRdtDataRequestToWalletRequestInput = object({
 const isAuthorized = (
   input: TransformRdtDataRequestToWalletRequestInput,
 ): boolean => {
-  const { persona, accounts, personaData } = input
+  const { persona, accounts, personaData, proofOfOwnership } = input
 
   const isPersonaLogin = !!persona
   const shouldResetData = accounts?.reset || personaData?.reset
@@ -62,8 +62,9 @@ const isAuthorized = (
     shouldResetData ||
     isOngoingAccountsRequest ||
     isOngoingPersonaDataRequest ||
-    isPersonaLogin
-  )
+    isPersonaLogin ||
+    proofOfOwnership
+  ) 
 
   return isAuthorizedRequest
 }
@@ -130,7 +131,7 @@ const withProofOfOwnershipRequestItem =
       const { challenge, accountAddresses, identityAddress } =
         input.proofOfOwnership
 
-      if (challenge) {
+      if (challenge && updatedRequestItems.discriminator === 'authorizedRequest') {
         updatedRequestItems['proofOfOwnership'] = {
           challenge,
         }
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/wallet-to-rdt.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/wallet-to-rdt.ts
index 1bbfbbbe..e2369883 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/wallet-to-rdt.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/wallet-to-rdt.ts
@@ -150,6 +150,15 @@ const withProofs =
           )
           draft.proofs.push(...accountProofs)
         }
+
+        if (input.proofOfOwnership) {
+          draft.proofs.push(
+            ...convertOwnershipProofsToSignedChallenge(
+              input.proofOfOwnership.challenge,
+              input.proofOfOwnership.proofs,
+            ),
+          )
+        }
       }
       if (input.discriminator === 'unauthorizedRequest') {
         if (
@@ -168,14 +177,6 @@ const withProofs =
           draft.proofs.push(...accountProofs)
         }
       }
-      if (input.proofOfOwnership) {
-        draft.proofs.push(
-          ...convertOwnershipProofsToSignedChallenge(
-            input.proofOfOwnership.challenge,
-            input.proofOfOwnership.proofs,
-          ),
-        )
-      }
     })
 
 export const transformWalletResponseToRdtWalletData = (
diff --git a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
index b38bcf12..1977f473 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts
@@ -340,7 +340,9 @@ export const WalletRequestModule = (input: {
             !state.walletData.persona &&
             walletDataRequest.discriminator === 'authorizedRequest'
 
-          const isProofOfOwnershipRequest = !!walletDataRequest.proofOfOwnership
+          const isProofOfOwnershipRequest =
+            walletDataRequest.discriminator === 'authorizedRequest' &&
+            !!walletDataRequest.proofOfOwnership
 
           const requestType = isLoginRequest
             ? 'loginRequest'
diff --git a/packages/dapp-toolkit/src/schemas/index.ts b/packages/dapp-toolkit/src/schemas/index.ts
index e82d17f1..2a6b8237 100644
--- a/packages/dapp-toolkit/src/schemas/index.ts
+++ b/packages/dapp-toolkit/src/schemas/index.ts
@@ -153,7 +153,6 @@ export type WalletUnauthorizedRequestItems = InferOutput<
 >
 export const WalletUnauthorizedRequestItems = object({
   discriminator: literal('unauthorizedRequest'),
-  proofOfOwnership: optional(ProofOfOwnershipRequestItem),
   oneTimeAccounts: optional(AccountsRequestItem),
   oneTimePersonaData: optional(PersonaDataRequestItem),
 })
@@ -271,7 +270,6 @@ export type WalletUnauthorizedRequestResponseItems = InferOutput<
 >
 const WalletUnauthorizedRequestResponseItems = object({
   discriminator: literal('unauthorizedRequest'),
-  proofOfOwnership: optional(ProofOfOwnershipResponseItem),
   oneTimeAccounts: optional(AccountsRequestResponseItem),
   oneTimePersonaData: optional(PersonaDataRequestResponseItem),
 })

From 0a1d60709d7164667dde22f66a468cc5cb7fc71d Mon Sep 17 00:00:00 2001
From: Alex Stelea 
Date: Mon, 4 Nov 2024 15:56:06 +0000
Subject: [PATCH 14/45] code(rdt): set expiration as required value

---
 .../pre-authorization-request/subintent-builder.ts             | 3 +--
 packages/dapp-toolkit/src/schemas/index.ts                     | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts
index 150a3675..795510cb 100644
--- a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts
+++ b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts
@@ -73,7 +73,7 @@ export const SubintentRequestBuilder = () => {
    */
   const manifest = (value: string) => {
     state.transactionManifest = value
-    return api
+    return { setExpiration }
   }
 
   /**
@@ -97,7 +97,6 @@ export const SubintentRequestBuilder = () => {
   }
 
   const api = {
-    setExpiration,
     addBlobs,
     message,
     toRequestItem,
diff --git a/packages/dapp-toolkit/src/schemas/index.ts b/packages/dapp-toolkit/src/schemas/index.ts
index 85c86c4c..2e8b0c89 100644
--- a/packages/dapp-toolkit/src/schemas/index.ts
+++ b/packages/dapp-toolkit/src/schemas/index.ts
@@ -264,7 +264,7 @@ export const SubintentRequestItem = object({
   transactionManifest: string(),
   blobs: optional(array(string())),
   message: optional(string()),
-  expiration: optional(union([ExpireAtTime, ExpireAfterSignature])),
+  expiration: union([ExpireAtTime, ExpireAfterSignature]),
 })
 
 export type SubintentResponseItem = InferOutput

From a14648bd72f934b3988fdbc78c8b67c8cca4b8c5 Mon Sep 17 00:00:00 2001
From: Alex Stelea 
Date: Mon, 4 Nov 2024 16:01:32 +0000
Subject: [PATCH 15/45] ci: trigger patch on code type

---
 packages/dapp-toolkit/.releaserc | 312 ++++++++++++++++---------------
 1 file changed, 158 insertions(+), 154 deletions(-)

diff --git a/packages/dapp-toolkit/.releaserc b/packages/dapp-toolkit/.releaserc
index d0ef9b29..2ec1f5df 100644
--- a/packages/dapp-toolkit/.releaserc
+++ b/packages/dapp-toolkit/.releaserc
@@ -1,27 +1,105 @@
 {
-    "branches": [
-      "main",
-      "next",
+  "branches": [
+    "main",
+    "next",
+    {
+      "name": "develop",
+      "channel": "dev",
+      "prerelease": "dev"
+    },
+    {
+      "name": "release/([a-z0-9-.]+)",
+      "channel": "${name.replace(/^release\\//g, \"\")}",
+      "prerelease": "${name.replace(/^release\\//g, \"\")}"
+    }
+  ],
+  "plugins": [
+    [
+      "@semantic-release/commit-analyzer",
       {
-        "name": "develop",
-        "channel": "dev",
-        "prerelease": "dev"
-      },
-      {
-        "name": "release/([a-z0-9-.]+)",
-        "channel": "${name.replace(/^release\\//g, \"\")}",
-        "prerelease": "${name.replace(/^release\\//g, \"\")}"
+        "preset": "conventionalcommits",
+        "releaseRules": [
+          {
+            "type": "refactor",
+            "release": "patch"
+          },
+          {
+            "type": "major",
+            "release": "major"
+          },
+          {
+            "type": "docs",
+            "scope": "README",
+            "release": "patch"
+          },
+          {
+            "type": "test",
+            "release": false
+          },
+          {
+            "type": "style",
+            "release": "patch"
+          },
+          {
+            "type": "perf",
+            "release": "patch"
+          },
+          {
+            "type": "ci",
+            "release": false
+          },
+          {
+            "type": "build",
+            "release": false
+          },
+          {
+            "type": "chore",
+            "release": "patch"
+          },
+          {
+            "type": "code",
+            "release": "patch"
+          },
+          {
+            "type": "no-release",
+            "release": false
+          }
+        ],
+        "parserOpts": {
+          "noteKeywords": [
+            "BREAKING CHANGE",
+            "BREAKING CHANGES"
+          ]
+        }
       }
     ],
-    "plugins": [
-      [
-        "@semantic-release/commit-analyzer",
-        {
-          "preset": "conventionalcommits",
-          "releaseRules": [
+    [
+      "@semantic-release/release-notes-generator",
+      {
+        "preset": "conventionalcommits",
+        "parserOpts": {
+          "noteKeywords": [
+            "BREAKING CHANGE",
+            "BREAKING CHANGES"
+          ]
+        },
+        "writerOpts": {
+          "commitsSort": [
+            "subject",
+            "scope"
+          ]
+        },
+        "presetConfig": {
+          "types": [
             {
-              "type": "refactor",
-              "release": "patch"
+              "type": "feat",
+              "section": ":sparkles: Features",
+              "hidden": false
+            },
+            {
+              "type": "fix",
+              "section": ":bug: Fixes",
+              "hidden": false
             },
             {
               "type": "major",
@@ -29,158 +107,84 @@
             },
             {
               "type": "docs",
-              "scope": "README",
-              "release": "patch"
+              "section": ":memo: Documentation",
+              "hidden": false
             },
             {
-              "type": "test",
-              "release": false
+              "type": "style",
+              "section": ":barber: Code-style",
+              "hidden": false
             },
             {
-              "type": "style",
-              "release": "patch"
+              "type": "refactor",
+              "section": ":zap: Refactor",
+              "hidden": false
             },
             {
               "type": "perf",
-              "release": "patch"
+              "section": ":fast_forward: Performance",
+              "hidden": false
             },
             {
-              "type": "ci",
-              "release": false
+              "type": "test",
+              "section": ":white_check_mark: Tests",
+              "hidden": false
             },
             {
-              "type": "build",
-              "release": false
+              "type": "ci",
+              "section": ":repeat: CI",
+              "hidden": false
             },
             {
               "type": "chore",
-              "release": "patch"
+              "section": ":repeat: Chore",
+              "hidden": false
             },
             {
-              "type": "no-release",
-              "release": false
-            }
-          ],
-          "parserOpts": {
-            "noteKeywords": [
-              "BREAKING CHANGE",
-              "BREAKING CHANGES"
-            ]
-          }
-        }
-      ],
-      [
-        "@semantic-release/release-notes-generator",
-        {
-          "preset": "conventionalcommits",
-          "parserOpts": {
-            "noteKeywords": [
-              "BREAKING CHANGE",
-              "BREAKING CHANGES"
-            ]
-          },
-          "writerOpts": {
-            "commitsSort": [
-              "subject",
-              "scope"
-            ]
-          },
-          "presetConfig": {
-            "types": [
-              {
-                "type": "feat",
-                "section": ":sparkles: Features",
-                "hidden": false
-              },
-              {
-                "type": "fix",
-                "section": ":bug: Fixes",
-                "hidden": false
-              },
-              {
-                "type": "major",
-                "release": "major"
-              },
-              {
-                "type": "docs",
-                "section": ":memo: Documentation",
-                "hidden": false
-              },
-              {
-                "type": "style",
-                "section": ":barber: Code-style",
-                "hidden": false
-              },
-              {
-                "type": "refactor",
-                "section": ":zap: Refactor",
-                "hidden": false
-              },
-              {
-                "type": "perf",
-                "section": ":fast_forward: Performance",
-                "hidden": false
-              },
-              {
-                "type": "test",
-                "section": ":white_check_mark: Tests",
-                "hidden": false
-              },
-              {
-                "type": "ci",
-                "section": ":repeat: CI",
-                "hidden": false
-              },
-              {
-                "type": "chore",
-                "section": ":repeat: Chore",
-                "hidden": false
-              },
-              {
-                "type": "build",
-                "section": ":wrench: Build",
-                "hidden": false
-              }
-            ]
-          }
-        }
-      ],
-      [
-        "semantic-release-replace-plugin",
-        {
-          "replacements": [
-            {
-              "files": [
-                "src/version.ts"
-              ],
-              "from": "export const __VERSION__ = '2.0.0'",
-              "to": "export const __VERSION__ = '${nextRelease.version}'",
-              "countMatches": true
+              "type": "build",
+              "section": ":wrench: Build",
+              "hidden": false
             }
           ]
         }
-      ],
-      [
-        "@semantic-release/exec",
-        {
-          "prepareCmd": "rm -rf dist && npm run build"
-        }
-      ],
-      "@semantic-release/npm",
-      "@semantic-release/github",
-      [
-        "@saithodev/semantic-release-backmerge",
-        {
-          "backmergeBranches": [
-            {
-              "from": "main",
-              "to": "develop"
-            }
-          ],
-          "backmergeStrategy": "merge",
-          "clearWorkspace": true,
-          "fastForwardMode": "ff"
-        }
-      ]
+      }
+    ],
+    [
+      "semantic-release-replace-plugin",
+      {
+        "replacements": [
+          {
+            "files": [
+              "src/version.ts"
+            ],
+            "from": "export const __VERSION__ = '2.0.0'",
+            "to": "export const __VERSION__ = '${nextRelease.version}'",
+            "countMatches": true
+          }
+        ]
+      }
+    ],
+    [
+      "@semantic-release/exec",
+      {
+        "prepareCmd": "rm -rf dist && npm run build"
+      }
+    ],
+    "@semantic-release/npm",
+    "@semantic-release/github",
+    [
+      "@saithodev/semantic-release-backmerge",
+      {
+        "backmergeBranches": [
+          {
+            "from": "main",
+            "to": "develop"
+          }
+        ],
+        "backmergeStrategy": "merge",
+        "clearWorkspace": true,
+        "fastForwardMode": "ff"
+      }
     ]
-  }
\ No newline at end of file
+  ]
+}

From 49c0bfec487c350af4ea8e974aa4d31ae584f364 Mon Sep 17 00:00:00 2001
From: Alex Stelea 
Date: Thu, 7 Nov 2024 10:19:37 +0000
Subject: [PATCH 16/45] code: specify expiration option in simple dapp

---
 examples/simple-dapp/src/main.ts | 38 +++++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/examples/simple-dapp/src/main.ts b/examples/simple-dapp/src/main.ts
index 56e41af1..231c6929 100644
--- a/examples/simple-dapp/src/main.ts
+++ b/examples/simple-dapp/src/main.ts
@@ -37,6 +37,18 @@ content.innerHTML = `
   
   
+ +
+ + +
+ + +
@@ -57,6 +69,9 @@ const subintentButton = document.getElementById('subintent')! const subintentManifest = document.getElementById( 'subintentManifest', )! as HTMLTextAreaElement +const subintentExpirationValue = document.getElementById( + 'subintentExpirationValue', +)! as HTMLInputElement const requests = document.getElementById('requests')! const logs = document.getElementById('logs')! const state = document.getElementById('state')! @@ -67,6 +82,23 @@ const proofOfOwnershipRequest = document.getElementById( 'proof-of-ownership-request', )! +let subintentExpiration: 'secondsAfterSignature' | 'atTime' = + 'secondsAfterSignature' + +document.querySelectorAll('input[name="option"]').forEach((radio) => { + radio.addEventListener('change', () => { + const selectedOption = document.querySelector( + 'input[name="option"]:checked', + ) as HTMLInputElement + if (selectedOption) { + console.log(`Selected value: ${selectedOption.value}`) + subintentExpiration = selectedOption.value as + | 'secondsAfterSignature' + | 'atTime' + } + }) +}) + const logger = Logger() logger.attachTransport((logObj) => { @@ -86,10 +118,14 @@ removeCb.onclick = () => { subintentButton.onclick = async () => { console.log(subintentManifest.value) + console.log(subintentExpirationValue.value) const result = await dAppToolkit.walletApi.sendPreAuthorizationRequest( SubintentRequestBuilder() .manifest(subintentManifest.value) - .setExpiration('secondsAfterSignature', 3600), + .setExpiration( + subintentExpiration, + subintentExpirationValue.value as unknown as number, + ), ) console.log(result) From e13eadb3a7a51d78b6f51a94b0eab210c960c149 Mon Sep 17 00:00:00 2001 From: Alex Stelea Date: Thu, 17 Oct 2024 15:08:01 +0100 Subject: [PATCH 17/45] fix(rdt): deep link issue for telegram mini apps --- examples/simple-dapp/index.html | 1 + .../transport/radix-connect-relay/deep-link.module.ts | 10 ++++++++-- .../transport/radix-connect-relay/helpers/index.ts | 2 ++ .../transport/radix-connect-relay/helpers/isTma.ts | 8 ++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/index.ts create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/isTma.ts diff --git a/examples/simple-dapp/index.html b/examples/simple-dapp/index.html index faa6ed96..a6c1f65a 100644 --- a/examples/simple-dapp/index.html +++ b/examples/simple-dapp/index.html @@ -3,6 +3,7 @@ + Simple dApp diff --git a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/deep-link.module.ts b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/deep-link.module.ts index 6fba667b..57729e22 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/deep-link.module.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/deep-link.module.ts @@ -3,6 +3,7 @@ import { errAsync, okAsync } from 'neverthrow' import { Logger, isMobile } from '../../../../helpers' import Bowser from 'bowser' import { SdkError } from '../../../../error' +import { isTMA } from './helpers' export type DeepLinkModule = ReturnType export const DeepLinkModule = (input: { @@ -13,6 +14,7 @@ export const DeepLinkModule = (input: { const userAgent = Bowser.parse(window.navigator.userAgent) const { platform } = userAgent const logger = input?.logger?.getSubLogger({ name: 'DeepLinkModule' }) + const isTelegramMiniApp = isTMA(globalThis) logger?.debug({ platform, @@ -34,8 +36,12 @@ export const DeepLinkModule = (input: { data: { ...values }, }) - if (isMobile() && globalThis.location?.href) { - globalThis.location.href = outboundUrl.toString() + if (isMobile()) { + const deepLink = outboundUrl.toString() + + // Telegram Mini App does not support deep linking by changing location.href value + if (isTelegramMiniApp) globalThis.open(deepLink, '_blank') + else if (globalThis.location?.href) globalThis.location.href = deepLink return okAsync(undefined) } diff --git a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/index.ts b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/index.ts new file mode 100644 index 00000000..502b20aa --- /dev/null +++ b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/index.ts @@ -0,0 +1,2 @@ +export * from './base64url' +export * from './isTma' diff --git a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/isTma.ts b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/isTma.ts new file mode 100644 index 00000000..f2218c1e --- /dev/null +++ b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/helpers/isTma.ts @@ -0,0 +1,8 @@ +/** + * Checks if the provided object is a Telegram Mobile App (TMA) global object. + * + * @param maybeTgGlobalObject - The object to check. + * @returns `true` if the object has WebView initialization parameters, otherwise `false`. + */ +export const isTMA = (globalObject: any) => + Object.keys(globalObject?.Telegram?.WebView?.initParams || {}).length > 0 From 88932d731cebb654bfd5150b7af186d35cb1c303 Mon Sep 17 00:00:00 2001 From: Dawid Sowa Date: Fri, 18 Oct 2024 18:55:20 +0200 Subject: [PATCH 18/45] chore: add test coverage tool, bump `vitest` dependency --- package-lock.json | 2000 ++++------------- packages/dapp-toolkit/package.json | 6 +- ...ange.test.ts => ecdh-key-exchange.spec.ts} | 0 packages/dapp-toolkit/vitest.config.ts | 6 + 4 files changed, 493 insertions(+), 1519 deletions(-) rename packages/dapp-toolkit/src/modules/wallet-request/identity/tests/{ecdh-key-exchange.test.ts => ecdh-key-exchange.spec.ts} (100%) diff --git a/package-lock.json b/package-lock.json index 19f3d2bb..6ff2f2d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3630,18 +3630,18 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", - "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", "dev": true, "engines": { "node": ">=6.9.0" @@ -3700,10 +3700,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", - "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", + "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", "dev": true, + "dependencies": { + "@babel/types": "^7.25.8" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -5210,19 +5213,25 @@ } }, "node_modules/@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", + "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, "node_modules/@cdklabs/tskb": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/@cdklabs/tskb/-/tskb-0.0.3.tgz", @@ -6515,9 +6524,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "engines": { "node": ">=12" @@ -6905,9 +6914,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { @@ -12021,97 +12030,13 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, - "node_modules/@vitest/expect": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.4.0.tgz", - "integrity": "sha512-Jths0sWCJZ8BxjKe+p+eKsoqev1/T8lYcrjavEaz8auEJ4jAVY0GwW3JKmdVU4mmNPLPHixh4GNXP7GFtAiDHA==", - "dev": true, - "dependencies": { - "@vitest/spy": "1.4.0", - "@vitest/utils": "1.4.0", - "chai": "^4.3.10" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.4.0.tgz", - "integrity": "sha512-EDYVSmesqlQ4RD2VvWo3hQgTJ7ZrFQ2VSJdfiJiArkCerDAGeyF1i6dHkmySqk573jLp6d/cfqCN+7wUB5tLgg==", - "dev": true, - "dependencies": { - "@vitest/utils": "1.4.0", - "p-limit": "^5.0.0", - "pathe": "^1.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner/node_modules/p-limit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", - "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@vitest/runner/node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@vitest/snapshot": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.4.0.tgz", - "integrity": "sha512-saAFnt5pPIA5qDGxOHxJ/XxhMFKkUSBJmVt5VgDsAqPTX6JP326r5C/c9UuCMPoXNzuudTPsYDZCoJ5ilpqG2A==", - "dev": true, - "dependencies": { - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "pretty-format": "^29.7.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.4.0.tgz", - "integrity": "sha512-Ywau/Qs1DzM/8Uc+yA77CwSegizMlcgTJuYGAi0jujOteJOUf1ujunHThYo243KG9nAyWT3L9ifPYZ5+As/+6Q==", - "dev": true, - "dependencies": { - "tinyspy": "^2.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.4.0.tgz", - "integrity": "sha512-mx3Yd1/6e2Vt/PUC98DcqTirtfxUyAZ32uK82r8rZzbtBeBo+nqgnjx/LvqQdWsrvNtm14VmurNgcf4nqY5gJg==", + "node_modules/@vitest/pretty-format": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz", + "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", "dev": true, "dependencies": { - "diff-sequences": "^29.6.3", - "estree-walker": "^3.0.3", - "loupe": "^2.3.7", - "pretty-format": "^29.7.0" + "tinyrainbow": "^1.2.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -12847,15 +12772,6 @@ "util": "^0.12.5" } }, - "node_modules/assertion-error": { - "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": "*" - } - }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -15176,24 +15092,6 @@ "readable-stream": "^3.6.0" } }, - "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -15217,18 +15115,6 @@ "node": ">=10" } }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -16447,18 +16333,6 @@ "optional": true, "peer": true }, - "node_modules/deep-eql": { - "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" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -18054,15 +17928,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -18247,23 +18112,21 @@ "dev": true }, "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -18647,6 +18510,12 @@ "node": ">=12" } }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, "node_modules/html-minifier": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", @@ -19498,16 +19367,90 @@ "semver": "bin/semver.js" } }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { - "@isaacs/cliui": "^8.0.2" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=14" + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -20211,12 +20154,6 @@ "node": ">=6" } }, - "node_modules/jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "dev": true - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -20566,22 +20503,6 @@ "node": ">=6.11.5" } }, - "node_modules/local-pkg": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", - "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", - "dev": true, - "dependencies": { - "mlly": "^1.4.2", - "pkg-types": "^1.0.3" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -20793,15 +20714,6 @@ "loose-envify": "cli.js" } }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.1" - } - }, "node_modules/lower-case": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", @@ -20818,15 +20730,23 @@ } }, "node_modules/magic-string": { - "version": "0.30.8", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", - "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dev": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "engines": { - "node": ">=12" + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" } }, "node_modules/make-dir": { @@ -21191,9 +21111,9 @@ "dev": true }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -21238,9 +21158,9 @@ } }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -21295,18 +21215,6 @@ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", "dev": true }, - "node_modules/mlly": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz", - "integrity": "sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==", - "dev": true, - "dependencies": { - "acorn": "^8.11.3", - "pathe": "^1.1.2", - "pkg-types": "^1.0.3", - "ufo": "^1.3.2" - } - }, "node_modules/mnemonist": { "version": "0.39.8", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.8.tgz", @@ -25520,6 +25428,12 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "node_modules/pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -25668,29 +25582,26 @@ "dev": true }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/path-to-regexp": { "version": "0.1.7", @@ -25713,15 +25624,6 @@ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", "dev": true }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/peek-stream": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", @@ -25913,17 +25815,6 @@ "node": ">=10" } }, - "node_modules/pkg-types": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", - "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", - "dev": true, - "dependencies": { - "jsonc-parser": "^3.2.0", - "mlly": "^1.2.0", - "pathe": "^1.1.0" - } - }, "node_modules/pkg-up": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", @@ -29460,24 +29351,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-literal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.0.0.tgz", - "integrity": "sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==", - "dev": true, - "dependencies": { - "js-tokens": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/strip-literal/node_modules/js-tokens": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.3.tgz", - "integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==", - "dev": true - }, "node_modules/strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", @@ -30151,9 +30024,15 @@ "dev": true }, "node_modules/tinybench": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.6.0.tgz", - "integrity": "sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true + }, + "node_modules/tinyexec": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", "dev": true }, "node_modules/tinyglobby": { @@ -30195,19 +30074,10 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/tinypool": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.2.tgz", - "integrity": "sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", - "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", "dev": true, "engines": { "node": ">=14.0.0" @@ -30974,15 +30844,6 @@ "win32" ] }, - "node_modules/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==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/type-fest": { "version": "4.15.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.15.0.tgz", @@ -31519,489 +31380,6 @@ } } }, - "node_modules/vite-node": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.4.0.tgz", - "integrity": "sha512-VZDAseqjrHgNd4Kh8icYHWzTKSCZMhia7GyHfhtzLW33fZlG9SwsB6CEhgyVOWkJfJ2pFLrp/Gj1FSfAiqH9Lw==", - "dev": true, - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.4", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vite-node/node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" - } - }, - "node_modules/vite-node/node_modules/vite": { - "version": "5.2.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz", - "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==", - "dev": true, - "dependencies": { - "esbuild": "^0.20.1", - "postcss": "^8.4.38", - "rollup": "^4.13.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, "node_modules/vite-plugin-ngrok": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/vite-plugin-ngrok/-/vite-plugin-ngrok-1.0.0.tgz", @@ -32031,693 +31409,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/vitest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.4.0.tgz", - "integrity": "sha512-gujzn0g7fmwf83/WzrDTnncZt2UiXP41mHuFYFrdwaLRVQ6JYQEiME2IfEjU3vcFL3VKa75XhI3lFgn+hfVsQw==", - "dev": true, - "dependencies": { - "@vitest/expect": "1.4.0", - "@vitest/runner": "1.4.0", - "@vitest/snapshot": "1.4.0", - "@vitest/spy": "1.4.0", - "@vitest/utils": "1.4.0", - "acorn-walk": "^8.3.2", - "chai": "^4.3.10", - "debug": "^4.3.4", - "execa": "^8.0.1", - "local-pkg": "^0.5.0", - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "std-env": "^3.5.0", - "strip-literal": "^2.0.0", - "tinybench": "^2.5.1", - "tinypool": "^0.8.2", - "vite": "^5.0.0", - "vite-node": "1.4.0", - "why-is-node-running": "^2.2.2" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "1.4.0", - "@vitest/ui": "1.4.0", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/vitest-mock-extended": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/vitest-mock-extended/-/vitest-mock-extended-1.3.1.tgz", - "integrity": "sha512-OpghYjh4BDuQ/Mzs3lFMQ1QRk9D8/2O9T47MLUA5eLn7K4RWIy+MfIivYOWEyxjTENjsBnzgMihDjyNalN/K0Q==", - "dev": true, - "dependencies": { - "ts-essentials": "^9.3.2" - }, - "peerDependencies": { - "typescript": "3.x || 4.x || 5.x", - "vitest": ">=0.31.1" - } - }, - "node_modules/vitest-mock-extended/node_modules/ts-essentials": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-9.4.1.tgz", - "integrity": "sha512-oke0rI2EN9pzHsesdmrOrnqv1eQODmJpd/noJjwj2ZPC3Z4N2wbjrOEqnsEgmvlO2+4fBb0a794DCna2elEVIQ==", - "dev": true, - "peerDependencies": { - "typescript": ">=4.1.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/vitest/node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" - } - }, - "node_modules/vitest/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/vitest/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/vitest/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/vitest/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/vite": { - "version": "5.2.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz", - "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==", - "dev": true, - "dependencies": { - "esbuild": "^0.20.1", - "postcss": "^8.4.38", - "rollup": "^4.13.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", @@ -33035,9 +31726,9 @@ } }, "node_modules/why-is-node-running": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", - "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, "dependencies": { "siginfo": "^2.0.0", @@ -33627,14 +32318,14 @@ "@radixdlt/connect-button": "*", "@saithodev/semantic-release-backmerge": "^3.2.1", "@semantic-release/exec": "^6.0.3", + "@vitest/coverage-v8": "^2.1.3", "radix-connect-common": "*", "semantic-release": "^23.0.0", "semantic-release-replace-plugin": "^1.2.7", "tsup": "^8.3.0", "typescript": "^5.4.4", "vite-plugin-singlefile": "^2.0.2", - "vitest": "^1.4.0", - "vitest-mock-extended": "^1.3.1" + "vitest": "^2.1.3" }, "engines": { "node": ">=18" @@ -33652,7 +32343,6 @@ "os": [ "aix" ], - "peer": true, "engines": { "node": ">=12" } @@ -33669,7 +32359,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">=12" } @@ -33686,7 +32375,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">=12" } @@ -33703,7 +32391,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">=12" } @@ -33720,7 +32407,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">=12" } @@ -33737,7 +32423,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">=12" } @@ -33754,7 +32439,6 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">=12" } @@ -33771,7 +32455,6 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">=12" } @@ -33788,7 +32471,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } @@ -33805,7 +32487,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } @@ -33822,7 +32503,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } @@ -33839,7 +32519,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } @@ -33856,7 +32535,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } @@ -33873,7 +32551,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } @@ -33890,7 +32567,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } @@ -33907,7 +32583,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } @@ -33924,7 +32599,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } @@ -33941,7 +32615,6 @@ "os": [ "netbsd" ], - "peer": true, "engines": { "node": ">=12" } @@ -33958,7 +32631,6 @@ "os": [ "openbsd" ], - "peer": true, "engines": { "node": ">=12" } @@ -33975,7 +32647,6 @@ "os": [ "sunos" ], - "peer": true, "engines": { "node": ">=12" } @@ -33992,7 +32663,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=12" } @@ -34009,7 +32679,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=12" } @@ -34026,7 +32695,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=12" } @@ -34306,6 +32974,133 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "packages/dapp-toolkit/node_modules/@vitest/coverage-v8": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.3.tgz", + "integrity": "sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "@bcoe/v8-coverage": "^0.2.3", + "debug": "^4.3.6", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magic-string": "^0.30.11", + "magicast": "^0.3.4", + "std-env": "^3.7.0", + "test-exclude": "^7.0.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "2.1.3", + "vitest": "2.1.3" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "packages/dapp-toolkit/node_modules/@vitest/expect": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz", + "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "2.1.3", + "@vitest/utils": "2.1.3", + "chai": "^5.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/dapp-toolkit/node_modules/@vitest/mocker": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz", + "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "2.1.3", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.11" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/spy": "2.1.3", + "msw": "^2.3.5", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "packages/dapp-toolkit/node_modules/@vitest/runner": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz", + "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", + "dev": true, + "dependencies": { + "@vitest/utils": "2.1.3", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/dapp-toolkit/node_modules/@vitest/snapshot": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz", + "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", + "dev": true, + "dependencies": { + "@vitest/pretty-format": "2.1.3", + "magic-string": "^0.30.11", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/dapp-toolkit/node_modules/@vitest/spy": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz", + "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", + "dev": true, + "dependencies": { + "tinyspy": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/dapp-toolkit/node_modules/@vitest/utils": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz", + "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", + "dev": true, + "dependencies": { + "@vitest/pretty-format": "2.1.3", + "loupe": "^3.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "packages/dapp-toolkit/node_modules/aggregate-error": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", @@ -34322,6 +33117,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "packages/dapp-toolkit/node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "packages/dapp-toolkit/node_modules/before-after-hook": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", @@ -34351,6 +33155,22 @@ "ieee754": "^1.2.1" } }, + "packages/dapp-toolkit/node_modules/chai": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", + "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "dev": true, + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "packages/dapp-toolkit/node_modules/chalk": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", @@ -34363,6 +33183,15 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "packages/dapp-toolkit/node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "engines": { + "node": ">= 16" + } + }, "packages/dapp-toolkit/node_modules/clean-stack": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", @@ -34463,6 +33292,15 @@ } } }, + "packages/dapp-toolkit/node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "packages/dapp-toolkit/node_modules/env-ci": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.0.0.tgz", @@ -34482,7 +33320,6 @@ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, "hasInstallScript": true, - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -34722,6 +33559,12 @@ "@types/trusted-types": "^2.0.2" } }, + "packages/dapp-toolkit/node_modules/loupe": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", + "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "dev": true + }, "packages/dapp-toolkit/node_modules/lru-cache": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", @@ -37680,6 +36523,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "packages/dapp-toolkit/node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "engines": { + "node": ">= 14.16" + } + }, "packages/dapp-toolkit/node_modules/read-pkg": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", @@ -37856,6 +36708,20 @@ "node": ">=14.18" } }, + "packages/dapp-toolkit/node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" + }, + "engines": { + "node": ">=18" + } + }, "packages/dapp-toolkit/node_modules/text-extensions": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", @@ -37868,6 +36734,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "packages/dapp-toolkit/node_modules/tinypool": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", + "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "packages/dapp-toolkit/node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "packages/dapp-toolkit/node_modules/tslog": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/tslog/-/tslog-4.8.0.tgz", @@ -37902,7 +36786,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz", "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==", "dev": true, - "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -37957,6 +36840,27 @@ } } }, + "packages/dapp-toolkit/node_modules/vite-node": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz", + "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.6", + "pathe": "^1.1.2", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "packages/dapp-toolkit/node_modules/vite-plugin-singlefile": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/vite-plugin-singlefile/-/vite-plugin-singlefile-2.0.2.tgz", @@ -37973,6 +36877,70 @@ "vite": "^5.3.1" } }, + "packages/dapp-toolkit/node_modules/vitest": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz", + "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==", + "dev": true, + "dependencies": { + "@vitest/expect": "2.1.3", + "@vitest/mocker": "2.1.3", + "@vitest/pretty-format": "^2.1.3", + "@vitest/runner": "2.1.3", + "@vitest/snapshot": "2.1.3", + "@vitest/spy": "2.1.3", + "@vitest/utils": "2.1.3", + "chai": "^5.1.1", + "debug": "^4.3.6", + "magic-string": "^0.30.11", + "pathe": "^1.1.2", + "std-env": "^3.7.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.0", + "tinypool": "^1.0.0", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.1.3", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.3", + "@vitest/ui": "2.1.3", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, "packages/eslint-config": { "name": "@repo/eslint-config", "version": "0.0.0", diff --git a/packages/dapp-toolkit/package.json b/packages/dapp-toolkit/package.json index 9285b12c..96dd1fe4 100644 --- a/packages/dapp-toolkit/package.json +++ b/packages/dapp-toolkit/package.json @@ -56,7 +56,7 @@ "dev": "tsup --watch", "build": "tsup && npm run build:single", "build:single": "vite build --config vite-single-file.config.ts && cp dist/radix-dapp-toolkit.bundle.umd.cjs ../../examples/cdn", - "test": "vitest", + "test": "vitest run --coverage", "test:watch": "vitest --watch" }, "dependencies": { @@ -78,14 +78,14 @@ "@radixdlt/connect-button": "*", "@saithodev/semantic-release-backmerge": "^3.2.1", "@semantic-release/exec": "^6.0.3", + "@vitest/coverage-v8": "^2.1.3", "radix-connect-common": "*", "semantic-release": "^23.0.0", "semantic-release-replace-plugin": "^1.2.7", "tsup": "^8.3.0", "typescript": "^5.4.4", "vite-plugin-singlefile": "^2.0.2", - "vitest": "^1.4.0", - "vitest-mock-extended": "^1.3.1" + "vitest": "^2.1.3" }, "repository": { "type": "git", diff --git a/packages/dapp-toolkit/src/modules/wallet-request/identity/tests/ecdh-key-exchange.test.ts b/packages/dapp-toolkit/src/modules/wallet-request/identity/tests/ecdh-key-exchange.spec.ts similarity index 100% rename from packages/dapp-toolkit/src/modules/wallet-request/identity/tests/ecdh-key-exchange.test.ts rename to packages/dapp-toolkit/src/modules/wallet-request/identity/tests/ecdh-key-exchange.spec.ts diff --git a/packages/dapp-toolkit/vitest.config.ts b/packages/dapp-toolkit/vitest.config.ts index 95c5d26e..466ada91 100644 --- a/packages/dapp-toolkit/vitest.config.ts +++ b/packages/dapp-toolkit/vitest.config.ts @@ -4,5 +4,11 @@ import { defineConfig } from 'vitest/config' export default defineConfig({ test: { environment: 'jsdom', + coverage: { + provider: 'v8', + include: ['src/**/*.ts'], + reporter: ['lcov', 'text', 'html'], + }, + include: ['src/**/*.spec.ts'], }, }) From 691f761e56c5eaf4d5f75e4d754b4e1c9aa02877 Mon Sep 17 00:00:00 2001 From: Dawid Sowa Date: Tue, 22 Oct 2024 14:30:02 +0200 Subject: [PATCH 19/45] fix: remove `proofOfOwnership` from `unathorizedRequest` Proof Of Ownership can only be part of authorized request --- .../data-request/helpers/to-wallet-request.ts | 2 +- .../transformations/rdt-to-wallet.ts | 9 +++++---- .../transformations/wallet-to-rdt.ts | 17 +++++++++-------- .../modules/wallet-request/wallet-request.ts | 4 +++- packages/dapp-toolkit/src/schemas/index.ts | 2 -- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/helpers/to-wallet-request.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/helpers/to-wallet-request.ts index 4b62c66b..ea9ada8b 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/helpers/to-wallet-request.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/helpers/to-wallet-request.ts @@ -48,7 +48,7 @@ export const toWalletRequest = ({ oneTime, } - if (!oneTime) { + if (!oneTime || dataRequestState.proofOfOwnership) { const persona = walletData.persona if (walletData.persona) draft.persona = persona diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts index f88cf299..333d2321 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/rdt-to-wallet.ts @@ -51,7 +51,7 @@ export const TransformRdtDataRequestToWalletRequestInput = object({ const isAuthorized = ( input: TransformRdtDataRequestToWalletRequestInput, ): boolean => { - const { persona, accounts, personaData } = input + const { persona, accounts, personaData, proofOfOwnership } = input const isPersonaLogin = !!persona const shouldResetData = accounts?.reset || personaData?.reset @@ -62,8 +62,9 @@ const isAuthorized = ( shouldResetData || isOngoingAccountsRequest || isOngoingPersonaDataRequest || - isPersonaLogin - ) + isPersonaLogin || + proofOfOwnership + ) return isAuthorizedRequest } @@ -130,7 +131,7 @@ const withProofOfOwnershipRequestItem = const { challenge, accountAddresses, identityAddress } = input.proofOfOwnership - if (challenge) { + if (challenge && updatedRequestItems.discriminator === 'authorizedRequest') { updatedRequestItems['proofOfOwnership'] = { challenge, } diff --git a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/wallet-to-rdt.ts b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/wallet-to-rdt.ts index 1bbfbbbe..e2369883 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/wallet-to-rdt.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/data-request/transformations/wallet-to-rdt.ts @@ -150,6 +150,15 @@ const withProofs = ) draft.proofs.push(...accountProofs) } + + if (input.proofOfOwnership) { + draft.proofs.push( + ...convertOwnershipProofsToSignedChallenge( + input.proofOfOwnership.challenge, + input.proofOfOwnership.proofs, + ), + ) + } } if (input.discriminator === 'unauthorizedRequest') { if ( @@ -168,14 +177,6 @@ const withProofs = draft.proofs.push(...accountProofs) } } - if (input.proofOfOwnership) { - draft.proofs.push( - ...convertOwnershipProofsToSignedChallenge( - input.proofOfOwnership.challenge, - input.proofOfOwnership.proofs, - ), - ) - } }) export const transformWalletResponseToRdtWalletData = ( diff --git a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts index df5a0878..c55a220b 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts @@ -353,7 +353,9 @@ export const WalletRequestModule = (input: { !state.walletData.persona && walletDataRequest.discriminator === 'authorizedRequest' - const isProofOfOwnershipRequest = !!walletDataRequest.proofOfOwnership + const isProofOfOwnershipRequest = + walletDataRequest.discriminator === 'authorizedRequest' && + !!walletDataRequest.proofOfOwnership const requestType = isLoginRequest ? 'loginRequest' diff --git a/packages/dapp-toolkit/src/schemas/index.ts b/packages/dapp-toolkit/src/schemas/index.ts index 2e8b0c89..ef603567 100644 --- a/packages/dapp-toolkit/src/schemas/index.ts +++ b/packages/dapp-toolkit/src/schemas/index.ts @@ -153,7 +153,6 @@ export type WalletUnauthorizedRequestItems = InferOutput< > export const WalletUnauthorizedRequestItems = object({ discriminator: literal('unauthorizedRequest'), - proofOfOwnership: optional(ProofOfOwnershipRequestItem), oneTimeAccounts: optional(AccountsRequestItem), oneTimePersonaData: optional(PersonaDataRequestItem), }) @@ -309,7 +308,6 @@ export type WalletUnauthorizedRequestResponseItems = InferOutput< > const WalletUnauthorizedRequestResponseItems = object({ discriminator: literal('unauthorizedRequest'), - proofOfOwnership: optional(ProofOfOwnershipResponseItem), oneTimeAccounts: optional(AccountsRequestResponseItem), oneTimePersonaData: optional(PersonaDataRequestResponseItem), }) From 0ed3b37582d0d4498e64862147544bc8ec0ae778 Mon Sep 17 00:00:00 2001 From: Dawid Sowa Date: Tue, 22 Oct 2024 18:39:47 +0200 Subject: [PATCH 20/45] fix: adjust subintents to wallet api --- packages/dapp-toolkit/src/_types.ts | 2 - .../subintent-builder.spec.ts | 42 +++++++++++++------ .../subintent-builder.ts | 19 +++++---- .../modules/wallet-request/wallet-request.ts | 4 +- packages/dapp-toolkit/src/schemas/index.ts | 28 ++++++++----- 5 files changed, 61 insertions(+), 34 deletions(-) diff --git a/packages/dapp-toolkit/src/_types.ts b/packages/dapp-toolkit/src/_types.ts index bc4f670d..9c2dba77 100644 --- a/packages/dapp-toolkit/src/_types.ts +++ b/packages/dapp-toolkit/src/_types.ts @@ -4,8 +4,6 @@ import type { Observable } from 'rxjs' import type { RadixButtonStatus, RadixButtonTheme } from 'radix-connect-common' import { CallbackFns, - ExpireAfterSignature, - ExpireAtTime, Persona, PersonaDataName, WalletInteraction, diff --git a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.spec.ts b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.spec.ts index b36f85b9..6c719dc3 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.spec.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.spec.ts @@ -13,26 +13,44 @@ describe('SubintentRequestBuilder', () => { expect(tx).toEqual({ discriminator: 'subintent', version: 1, - transactionManifestVersion: 1, - transactionManifest: '...', + manifestVersion: 2, + subintentManifest: '...', expiration: { - discriminator: 'expireAfterSignature', - value: 60, + discriminator: 'expireAfterDelay', + expireAfterSeconds: 60, }, blobs: ['deadbeef', 'beefdead'], message: 'hello', }) }) + it('should build a subintent request with expiration at time', () => { + const tx = SubintentRequestBuilder() + .manifest('...') + .setExpiration('atTime', 1970) + .toRequestItem() + + expect(tx).toEqual({ + discriminator: 'subintent', + version: 1, + manifestVersion: 2, + subintentManifest: '...', + expiration: { + discriminator: 'expireAtTime', + unixTimestampSeconds: 1970, + }, + }) + }) + it('should build a subintent request using raw object', () => { const tx = SubintentRequestBuilder() .rawConfig({ version: 1, - transactionManifestVersion: 1, - transactionManifest: '...', + manifestVersion: 2, + subintentManifest: '...', expiration: { - discriminator: 'expireAfterSignature', - value: 60, + discriminator: 'expireAfterDelay', + expireAfterSeconds: 60, }, blobs: ['deadbeef', 'beefdead'], message: 'hello', @@ -42,11 +60,11 @@ describe('SubintentRequestBuilder', () => { expect(tx).toEqual({ discriminator: 'subintent', version: 1, - transactionManifestVersion: 1, - transactionManifest: '...', + manifestVersion: 2, + subintentManifest: '...', expiration: { - discriminator: 'expireAfterSignature', - value: 60, + discriminator: 'expireAfterDelay', + expireAfterSeconds: 60, }, blobs: ['deadbeef', 'beefdead'], message: 'hello', diff --git a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts index 795510cb..26d1fa17 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts @@ -21,7 +21,7 @@ export const SubintentRequestBuilder = () => { let state: Partial = { discriminator: 'subintent', version: 1, - transactionManifestVersion: 1, + manifestVersion: 2, } /** @@ -35,11 +35,16 @@ export const SubintentRequestBuilder = () => { type: 'atTime' | 'secondsAfterSignature', value: number, ) => { - state.expiration = { - discriminator: - type === 'atTime' ? 'expireAtTime' : 'expireAfterSignature', - value, - } + state.expiration = + type === 'atTime' + ? { + discriminator: 'expireAtTime', + unixTimestampSeconds: value, + } + : { + discriminator: 'expireAfterDelay', + expireAfterSeconds: value, + } return api } @@ -72,7 +77,7 @@ export const SubintentRequestBuilder = () => { * @returns The API object for method chaining. */ const manifest = (value: string) => { - state.transactionManifest = value + state.subintentManifest = value return { setExpiration } } diff --git a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts index c55a220b..54ecc3db 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts @@ -307,14 +307,14 @@ export const WalletRequestModule = (input: { > => { const walletInteraction = walletRequestSdk.createWalletInteraction({ discriminator: 'preAuthorizationRequest', - subintent: value.toRequestItem(), + request: value.toRequestItem(), }) return addNewRequest('preAuthorizationRequest', walletInteraction, false) .andThen(() => sendRequestAndAwaitResponse(walletInteraction)) .map((requestItem) => ({ signedPartialTransaction: - requestItem.walletResponse.signedPartialTransaction, + requestItem.walletResponse.response.signedPartialTransaction, })) } diff --git a/packages/dapp-toolkit/src/schemas/index.ts b/packages/dapp-toolkit/src/schemas/index.ts index ef603567..1685f4d9 100644 --- a/packages/dapp-toolkit/src/schemas/index.ts +++ b/packages/dapp-toolkit/src/schemas/index.ts @@ -246,24 +246,30 @@ export const CancelRequest = object({ export type ExpireAtTime = InferOutput export const ExpireAtTime = object({ discriminator: literal('expireAtTime'), - value: number(), + unixTimestampSeconds: number(), }) -export type ExpireAfterSignature = InferOutput -export const ExpireAfterSignature = object({ - discriminator: literal('expireAfterSignature'), - value: number(), +export type ExpireAfterDelay = InferOutput +export const ExpireAfterDelay = object({ + discriminator: literal('expireAfterDelay'), + expireAfterSeconds: number(), }) export type SubintentRequestItem = InferOutput export const SubintentRequestItem = object({ discriminator: literal('subintent'), + /** + * Version of the message interface + */ version: number(), - transactionManifestVersion: number(), - transactionManifest: string(), + /** + * Version of the Transaction Manifest + */ + manifestVersion: number(), + subintentManifest: string(), blobs: optional(array(string())), message: optional(string()), - expiration: union([ExpireAtTime, ExpireAfterSignature]), + expiration: union([ExpireAtTime, ExpireAfterDelay]), }) export type SubintentResponseItem = InferOutput @@ -277,7 +283,7 @@ export type WalletPreAuthorizationItems = InferOutput< > export const WalletPreAuthorizationItems = object({ discriminator: literal('preAuthorizationRequest'), - subintent: optional(SubintentRequestItem), + request: optional(SubintentRequestItem), }) export type WalletInteractionItems = InferOutput @@ -334,8 +340,8 @@ export type WalletPreAuthorizationResponseItems = InferOutput< typeof WalletPreAuthorizationResponseItems > export const WalletPreAuthorizationResponseItems = object({ - discriminator: literal('preAuthorizationRequest'), - subintent: optional(SubintentResponseItem), + discriminator: literal('preAuthorizationResponse'), + response: optional(SubintentResponseItem), }) export const AuthLoginRequestResponseItem = union([ From a971f48804b5edde3a5beabc4ff7f84c7198a114 Mon Sep 17 00:00:00 2001 From: Dawid Sowa Date: Fri, 25 Oct 2024 11:19:52 +0200 Subject: [PATCH 21/45] fix: rename `setExpiration` parameter --- examples/simple-dapp/src/main.ts | 7 ++----- .../pre-authorization-request/subintent-builder.spec.ts | 2 +- .../pre-authorization-request/subintent-builder.ts | 9 +++------ 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/examples/simple-dapp/src/main.ts b/examples/simple-dapp/src/main.ts index 231c6929..6ea29f66 100644 --- a/examples/simple-dapp/src/main.ts +++ b/examples/simple-dapp/src/main.ts @@ -82,8 +82,7 @@ const proofOfOwnershipRequest = document.getElementById( 'proof-of-ownership-request', )! -let subintentExpiration: 'secondsAfterSignature' | 'atTime' = - 'secondsAfterSignature' +let subintentExpiration: 'afterDelay' | 'atTime' = 'afterDelay' document.querySelectorAll('input[name="option"]').forEach((radio) => { radio.addEventListener('change', () => { @@ -92,9 +91,7 @@ document.querySelectorAll('input[name="option"]').forEach((radio) => { ) as HTMLInputElement if (selectedOption) { console.log(`Selected value: ${selectedOption.value}`) - subintentExpiration = selectedOption.value as - | 'secondsAfterSignature' - | 'atTime' + subintentExpiration = selectedOption.value as 'afterDelay' | 'atTime' } }) }) diff --git a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.spec.ts b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.spec.ts index 6c719dc3..f28b1709 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.spec.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.spec.ts @@ -5,7 +5,7 @@ describe('SubintentRequestBuilder', () => { it('should build a subintent request', () => { const tx = SubintentRequestBuilder() .manifest('...') - .setExpiration('secondsAfterSignature', 60) + .setExpiration('afterDelay', 60) .addBlobs('deadbeef', 'beefdead') .message('hello') .toRequestItem() diff --git a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts index 26d1fa17..280a80bb 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/pre-authorization-request/subintent-builder.ts @@ -27,14 +27,11 @@ export const SubintentRequestBuilder = () => { /** * Sets the expiration for a request. * - * @param type - The type of expiration. Can be 'atTime' for a specific time or 'secondsAfterSignature' for a duration after the signature. - * @param value - The value associated with the expiration type. For 'atTime', this is a timestamp. For 'secondsAfterSignature', this is the number of seconds. + * @param type - The type of expiration. Can be 'atTime' for a specific time or 'afterDelay' for a duration after the signature. + * @param value - The value associated with the expiration type. For 'atTime', this is a timestamp. For 'afterDelay', this is the number of seconds. * @returns The API object for chaining. */ - const setExpiration = ( - type: 'atTime' | 'secondsAfterSignature', - value: number, - ) => { + const setExpiration = (type: 'atTime' | 'afterDelay', value: number) => { state.expiration = type === 'atTime' ? { From d831bad5b83c8ec518d5cd58025755511dbb68cf Mon Sep 17 00:00:00 2001 From: Alex Stelea Date: Thu, 7 Nov 2024 12:51:20 +0000 Subject: [PATCH 22/45] code: update simple dapp --- examples/simple-dapp/src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/simple-dapp/src/main.ts b/examples/simple-dapp/src/main.ts index 6ea29f66..c88491bd 100644 --- a/examples/simple-dapp/src/main.ts +++ b/examples/simple-dapp/src/main.ts @@ -121,7 +121,7 @@ subintentButton.onclick = async () => { .manifest(subintentManifest.value) .setExpiration( subintentExpiration, - subintentExpirationValue.value as unknown as number, + parseInt(subintentExpirationValue.value as string), ), ) From db3fbf2e86bf32e2ded18b22d19d989f92e35d85 Mon Sep 17 00:00:00 2001 From: Alex Stelea Date: Mon, 11 Nov 2024 18:48:10 +0000 Subject: [PATCH 23/45] code(rdt): update single file bundle extension --- .gitignore | 2 +- examples/cdn/index.html | 4 ++-- packages/dapp-toolkit/package.json | 2 +- packages/dapp-toolkit/vite-single-file.config.ts | 8 ++++++++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 6ad61a66..555c82cd 100644 --- a/.gitignore +++ b/.gitignore @@ -43,7 +43,7 @@ yarn-error.log* .envrc -examples/cdn/radix-dapp-toolkit.bundle.umd.cjs +examples/cdn/radix-dapp-toolkit.bundle.umd.js # Editor directories and files .vscode/* diff --git a/examples/cdn/index.html b/examples/cdn/index.html index e671f9a8..2530058d 100644 --- a/examples/cdn/index.html +++ b/examples/cdn/index.html @@ -15,7 +15,7 @@
- + diff --git a/packages/dapp-toolkit/package.json b/packages/dapp-toolkit/package.json index 96dd1fe4..bc53e3f3 100644 --- a/packages/dapp-toolkit/package.json +++ b/packages/dapp-toolkit/package.json @@ -55,7 +55,7 @@ "scripts": { "dev": "tsup --watch", "build": "tsup && npm run build:single", - "build:single": "vite build --config vite-single-file.config.ts && cp dist/radix-dapp-toolkit.bundle.umd.cjs ../../examples/cdn", + "build:single": "vite build --config vite-single-file.config.ts && cp dist/radix-dapp-toolkit.bundle.umd.js ../../examples/cdn", "test": "vitest run --coverage", "test:watch": "vitest --watch" }, diff --git a/packages/dapp-toolkit/vite-single-file.config.ts b/packages/dapp-toolkit/vite-single-file.config.ts index 2bc7f56f..482efd99 100644 --- a/packages/dapp-toolkit/vite-single-file.config.ts +++ b/packages/dapp-toolkit/vite-single-file.config.ts @@ -3,12 +3,20 @@ import { viteSingleFile } from 'vite-plugin-singlefile' export default defineConfig({ plugins: [viteSingleFile()], + build: { emptyOutDir: false, + lib: { entry: 'src/single-file.js', name: 'RDT', fileName: 'radix-dapp-toolkit.bundle', + formats: ['umd'], + }, + rollupOptions: { + output: { + entryFileNames: `radix-dapp-toolkit.bundle.umd.js`, + }, }, }, define: { 'process.env.NODE_ENV': '"production"' }, From fedb7f70eb01030c014798ed9a35d2825a819b7a Mon Sep 17 00:00:00 2001 From: Dawid Sowa Date: Wed, 13 Nov 2024 13:35:51 +0100 Subject: [PATCH 24/45] fix: add preauth request resolver --- examples/simple-dapp/src/main.ts | 55 ++++++++++++++++++- .../request-resolver/resolvers/index.ts | 1 + .../resolvers/pre-authorization-response.ts | 45 +++++++++++++++ .../modules/wallet-request/wallet-request.ts | 9 ++- 4 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 packages/dapp-toolkit/src/modules/wallet-request/request-resolver/resolvers/pre-authorization-response.ts diff --git a/examples/simple-dapp/src/main.ts b/examples/simple-dapp/src/main.ts index c88491bd..401fcaa8 100644 --- a/examples/simple-dapp/src/main.ts +++ b/examples/simple-dapp/src/main.ts @@ -36,7 +36,58 @@ content.innerHTML = `
- +