@luxexchange/api 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.depcheckrc +17 -0
- package/.eslintrc.js +30 -0
- package/README.md +5 -0
- package/package.json +74 -0
- package/project.json +94 -0
- package/scripts/fixGraphQLApiTypes.mts +91 -0
- package/scripts/modifyTradingApiTypes.mts +232 -0
- package/src/client.ts +66 -0
- package/src/clients/auctions/createAuctionServiceClient.ts +44 -0
- package/src/clients/base/SharedQueryClient.ts +25 -0
- package/src/clients/base/auth.ts +43 -0
- package/src/clients/base/createFetchClient.ts +133 -0
- package/src/clients/base/errors.ts +32 -0
- package/src/clients/base/types.ts +26 -0
- package/src/clients/base/urls.test.ts +297 -0
- package/src/clients/base/urls.ts +85 -0
- package/src/clients/base/utils.test.ts +131 -0
- package/src/clients/base/utils.ts +54 -0
- package/src/clients/blockaid/createBlockaidApiClient.ts +185 -0
- package/src/clients/blockaid/types.ts +495 -0
- package/src/clients/content/types.ts +22 -0
- package/src/clients/conversionTracking/api-ConversionProxyService_connectquery.ts +20 -0
- package/src/clients/conversionTracking/api_connect.ts +24 -0
- package/src/clients/conversionTracking/api_pb.ts +184 -0
- package/src/clients/conversionTracking/index.ts +4 -0
- package/src/clients/data/createDataServiceApiClient.ts +101 -0
- package/src/clients/dataApi/createDataApiServiceClient.ts +29 -0
- package/src/clients/dataApi/getGetPortfolioQueryOptions.test.ts +122 -0
- package/src/clients/dataApi/getGetPortfolioQueryOptions.ts +76 -0
- package/src/clients/embeddedWallet/createEmbeddedWalletApiClient.ts +325 -0
- package/src/clients/for/createForApiClient.ts +187 -0
- package/src/clients/for/types.ts +39 -0
- package/src/clients/for/utils.ts +13 -0
- package/src/clients/graphql/__generated__/operations.ts +605 -0
- package/src/clients/graphql/__generated__/react-hooks.ts +4245 -0
- package/src/clients/graphql/__generated__/resolvers.ts +1469 -0
- package/src/clients/graphql/__generated__/schema-types.ts +2099 -0
- package/src/clients/graphql/codegen.config.ts +50 -0
- package/src/clients/graphql/fragments.ts +96 -0
- package/src/clients/graphql/generated.ts +5 -0
- package/src/clients/graphql/queries.graphql +1028 -0
- package/src/clients/graphql/queries.ts +19 -0
- package/src/clients/graphql/schema.graphql +1585 -0
- package/src/clients/graphql/types.ts +9 -0
- package/src/clients/graphql/utils.ts +21 -0
- package/src/clients/graphql/web/LuxPrices.graphql +18 -0
- package/src/clients/graphql/web/RecentTokenTransfers.graphql +93 -0
- package/src/clients/graphql/web/SimpleToken.graphql +12 -0
- package/src/clients/graphql/web/TokenSpotPrice.graphql +19 -0
- package/src/clients/graphql/web/activity.graphql +272 -0
- package/src/clients/graphql/web/allV3Ticks.graphql +11 -0
- package/src/clients/graphql/web/allV4Ticks.graphql +11 -0
- package/src/clients/graphql/web/feeTierDistribution.graphql +7 -0
- package/src/clients/graphql/web/landing.graphql +38 -0
- package/src/clients/graphql/web/latestSubgraphBlock.graphql +3 -0
- package/src/clients/graphql/web/nft/CollectionSearch.graphql +34 -0
- package/src/clients/graphql/web/nft/NftBalance.graphql +109 -0
- package/src/clients/graphql/web/pool.graphql +199 -0
- package/src/clients/graphql/web/poolTransactions.graphql +84 -0
- package/src/clients/graphql/web/portfolios.graphql +68 -0
- package/src/clients/graphql/web/token.graphql +97 -0
- package/src/clients/graphql/web/tokenCharts.graphql +85 -0
- package/src/clients/graphql/web/tokenTransactions.graphql +25 -0
- package/src/clients/graphql/web/topPools.graphql +78 -0
- package/src/clients/graphql/web/transactions.graphql +56 -0
- package/src/clients/jupiter/createJupiterApiClient.ts +42 -0
- package/src/clients/jupiter/types.ts +92 -0
- package/src/clients/jupiter/utils.ts +27 -0
- package/src/clients/liquidity/createAuctionMutationClient.ts +41 -0
- package/src/clients/liquidity/createLiquidityServiceClient.ts +56 -0
- package/src/clients/lux/createLuxApiClient.ts +100 -0
- package/src/clients/notifications/createNotificationsApiClient.ts +72 -0
- package/src/clients/notifications/types.ts +102 -0
- package/src/clients/trading/__generated__/core/ApiError.ts +25 -0
- package/src/clients/trading/__generated__/core/ApiRequestOptions.ts +17 -0
- package/src/clients/trading/__generated__/core/ApiResult.ts +11 -0
- package/src/clients/trading/__generated__/core/CancelablePromise.ts +131 -0
- package/src/clients/trading/__generated__/core/OpenAPI.ts +32 -0
- package/src/clients/trading/__generated__/core/request.ts +322 -0
- package/src/clients/trading/__generated__/index.ts +221 -0
- package/src/clients/trading/__generated__/models/Address.ts +5 -0
- package/src/clients/trading/__generated__/models/AggregatedOutput.ts +20 -0
- package/src/clients/trading/__generated__/models/ApprovalRequest.ts +25 -0
- package/src/clients/trading/__generated__/models/ApprovalResponse.ts +18 -0
- package/src/clients/trading/__generated__/models/AutoSlippage.ts +14 -0
- package/src/clients/trading/__generated__/models/BridgeQuote.ts +55 -0
- package/src/clients/trading/__generated__/models/ChainDelegationMap.ts +9 -0
- package/src/clients/trading/__generated__/models/ChainId.ts +29 -0
- package/src/clients/trading/__generated__/models/ChainedQuote.ts +63 -0
- package/src/clients/trading/__generated__/models/CheckApprovalLPRequest.ts +35 -0
- package/src/clients/trading/__generated__/models/CheckApprovalLPResponse.ts +29 -0
- package/src/clients/trading/__generated__/models/ClaimLPFeesRequest.ts +20 -0
- package/src/clients/trading/__generated__/models/ClaimLPFeesResponse.ts +13 -0
- package/src/clients/trading/__generated__/models/ClaimLPRewardsRequest.ts +19 -0
- package/src/clients/trading/__generated__/models/ClaimLPRewardsResponse.ts +13 -0
- package/src/clients/trading/__generated__/models/ClassicGasUseEstimateUSD.ts +8 -0
- package/src/clients/trading/__generated__/models/ClassicInput.ts +11 -0
- package/src/clients/trading/__generated__/models/ClassicOutput.ts +13 -0
- package/src/clients/trading/__generated__/models/ClassicQuote.ts +69 -0
- package/src/clients/trading/__generated__/models/ClientContext.ts +18 -0
- package/src/clients/trading/__generated__/models/CosignerData.ts +21 -0
- package/src/clients/trading/__generated__/models/CreateLPPositionRequest.ts +40 -0
- package/src/clients/trading/__generated__/models/CreateLPPositionResponse.ts +21 -0
- package/src/clients/trading/__generated__/models/CreatePlanRequest.ts +23 -0
- package/src/clients/trading/__generated__/models/CreateSendRequest.ts +22 -0
- package/src/clients/trading/__generated__/models/CreateSendResponse.ts +18 -0
- package/src/clients/trading/__generated__/models/CreateSwap5792Request.ts +17 -0
- package/src/clients/trading/__generated__/models/CreateSwap5792Response.ts +17 -0
- package/src/clients/trading/__generated__/models/CreateSwap7702Request.ts +21 -0
- package/src/clients/trading/__generated__/models/CreateSwap7702Response.ts +13 -0
- package/src/clients/trading/__generated__/models/CreateSwapRequest.ts +42 -0
- package/src/clients/trading/__generated__/models/CreateSwapResponse.ts +16 -0
- package/src/clients/trading/__generated__/models/Curve.ts +9 -0
- package/src/clients/trading/__generated__/models/DEXOrder.ts +35 -0
- package/src/clients/trading/__generated__/models/DecreaseLPPositionRequest.ts +33 -0
- package/src/clients/trading/__generated__/models/DecreaseLPPositionResponse.ts +19 -0
- package/src/clients/trading/__generated__/models/DelegationDetails.ts +19 -0
- package/src/clients/trading/__generated__/models/Distributor.ts +10 -0
- package/src/clients/trading/__generated__/models/DutchInput.ts +13 -0
- package/src/clients/trading/__generated__/models/DutchInputV3.ts +15 -0
- package/src/clients/trading/__generated__/models/DutchOrderInfo.ts +41 -0
- package/src/clients/trading/__generated__/models/DutchOrderInfoV2.ts +27 -0
- package/src/clients/trading/__generated__/models/DutchOrderInfoV3.ts +28 -0
- package/src/clients/trading/__generated__/models/DutchOutput.ts +15 -0
- package/src/clients/trading/__generated__/models/DutchOutputV3.ts +18 -0
- package/src/clients/trading/__generated__/models/DutchQuote.ts +27 -0
- package/src/clients/trading/__generated__/models/DutchQuoteV2.ts +28 -0
- package/src/clients/trading/__generated__/models/DutchQuoteV3.ts +30 -0
- package/src/clients/trading/__generated__/models/Encode7702ResponseBody.ts +11 -0
- package/src/clients/trading/__generated__/models/Err400.ts +9 -0
- package/src/clients/trading/__generated__/models/Err401.ts +9 -0
- package/src/clients/trading/__generated__/models/Err404.ts +17 -0
- package/src/clients/trading/__generated__/models/Err422.ts +9 -0
- package/src/clients/trading/__generated__/models/Err429.ts +9 -0
- package/src/clients/trading/__generated__/models/Err500.ts +9 -0
- package/src/clients/trading/__generated__/models/Err504.ts +9 -0
- package/src/clients/trading/__generated__/models/GasStrategy.ts +46 -0
- package/src/clients/trading/__generated__/models/GetOrdersResponse.ts +12 -0
- package/src/clients/trading/__generated__/models/GetSwappableTokensResponse.ts +29 -0
- package/src/clients/trading/__generated__/models/GetSwapsResponse.ts +18 -0
- package/src/clients/trading/__generated__/models/HooksOptions.ts +12 -0
- package/src/clients/trading/__generated__/models/IncreaseLPPositionRequest.ts +39 -0
- package/src/clients/trading/__generated__/models/IncreaseLPPositionResponse.ts +21 -0
- package/src/clients/trading/__generated__/models/IndependentToken.ts +8 -0
- package/src/clients/trading/__generated__/models/IndicativeQuoteRequest.ts +18 -0
- package/src/clients/trading/__generated__/models/IndicativeQuoteResponse.ts +14 -0
- package/src/clients/trading/__generated__/models/IndicativeQuoteToken.ts +13 -0
- package/src/clients/trading/__generated__/models/LimitOrderQuoteRequest.ts +22 -0
- package/src/clients/trading/__generated__/models/LimitOrderQuoteResponse.ts +19 -0
- package/src/clients/trading/__generated__/models/MigrateLPPositionRequest.ts +41 -0
- package/src/clients/trading/__generated__/models/MigrateLPPositionResponse.ts +13 -0
- package/src/clients/trading/__generated__/models/NullablePermit.ts +13 -0
- package/src/clients/trading/__generated__/models/OrderIds.ts +5 -0
- package/src/clients/trading/__generated__/models/OrderInput.ts +13 -0
- package/src/clients/trading/__generated__/models/OrderOutput.ts +16 -0
- package/src/clients/trading/__generated__/models/OrderRequest.ts +17 -0
- package/src/clients/trading/__generated__/models/OrderResponse.ts +13 -0
- package/src/clients/trading/__generated__/models/OrderStatus.ts +23 -0
- package/src/clients/trading/__generated__/models/OrderType.ts +11 -0
- package/src/clients/trading/__generated__/models/OrderTypeQuery.ts +12 -0
- package/src/clients/trading/__generated__/models/Permit.ts +13 -0
- package/src/clients/trading/__generated__/models/PermitAmount.ts +11 -0
- package/src/clients/trading/__generated__/models/PlanResponse.ts +75 -0
- package/src/clients/trading/__generated__/models/PlanStatus.ts +14 -0
- package/src/clients/trading/__generated__/models/PlanStep.ts +59 -0
- package/src/clients/trading/__generated__/models/PlanStepMethod.ts +12 -0
- package/src/clients/trading/__generated__/models/PlanStepPayloadType.ts +12 -0
- package/src/clients/trading/__generated__/models/PlanStepProof.ts +20 -0
- package/src/clients/trading/__generated__/models/PlanStepStatus.ts +14 -0
- package/src/clients/trading/__generated__/models/PlanStepType.ts +23 -0
- package/src/clients/trading/__generated__/models/Pool.ts +15 -0
- package/src/clients/trading/__generated__/models/PoolInfoRequest.ts +20 -0
- package/src/clients/trading/__generated__/models/PoolInfoResponse.ts +16 -0
- package/src/clients/trading/__generated__/models/PoolInformation.ts +44 -0
- package/src/clients/trading/__generated__/models/PoolParameters.ts +19 -0
- package/src/clients/trading/__generated__/models/PoolReferenceByProtocol.ts +12 -0
- package/src/clients/trading/__generated__/models/Position.ts +11 -0
- package/src/clients/trading/__generated__/models/PriorityInput.ts +12 -0
- package/src/clients/trading/__generated__/models/PriorityOrderInfo.ts +29 -0
- package/src/clients/trading/__generated__/models/PriorityOutput.ts +17 -0
- package/src/clients/trading/__generated__/models/PriorityQuote.ts +31 -0
- package/src/clients/trading/__generated__/models/ProtocolItems.ts +15 -0
- package/src/clients/trading/__generated__/models/Protocols.ts +9 -0
- package/src/clients/trading/__generated__/models/Quote.ts +14 -0
- package/src/clients/trading/__generated__/models/QuoteRequest.ts +41 -0
- package/src/clients/trading/__generated__/models/QuoteResponse.ts +19 -0
- package/src/clients/trading/__generated__/models/RequestId.ts +8 -0
- package/src/clients/trading/__generated__/models/Routing.ts +20 -0
- package/src/clients/trading/__generated__/models/RoutingPreference.ts +16 -0
- package/src/clients/trading/__generated__/models/SafetyLevel.ts +10 -0
- package/src/clients/trading/__generated__/models/ScopeData.ts +28 -0
- package/src/clients/trading/__generated__/models/SettledAmount.ts +14 -0
- package/src/clients/trading/__generated__/models/SortKey.ts +7 -0
- package/src/clients/trading/__generated__/models/SpreadOptimization.ts +11 -0
- package/src/clients/trading/__generated__/models/StepUpdate.ts +25 -0
- package/src/clients/trading/__generated__/models/SwapSafetyMode.ts +10 -0
- package/src/clients/trading/__generated__/models/SwapStatus.ts +11 -0
- package/src/clients/trading/__generated__/models/TokenInRoute.ts +20 -0
- package/src/clients/trading/__generated__/models/TokenProject.ts +13 -0
- package/src/clients/trading/__generated__/models/TokenProjectLogo.ts +8 -0
- package/src/clients/trading/__generated__/models/TradeType.ts +11 -0
- package/src/clients/trading/__generated__/models/TransactionFailureReason.ts +11 -0
- package/src/clients/trading/__generated__/models/TransactionHash.ts +8 -0
- package/src/clients/trading/__generated__/models/TransactionRequest.ts +29 -0
- package/src/clients/trading/__generated__/models/TransactionRequest5792.ts +25 -0
- package/src/clients/trading/__generated__/models/TruncatedPlanStep.ts +21 -0
- package/src/clients/trading/__generated__/models/UniversalRouterVersion.ts +8 -0
- package/src/clients/trading/__generated__/models/UpdatePlanRequest.ts +12 -0
- package/src/clients/trading/__generated__/models/Urgency.ts +12 -0
- package/src/clients/trading/__generated__/models/V2PoolInRoute.ts +19 -0
- package/src/clients/trading/__generated__/models/V2Reserve.ts +16 -0
- package/src/clients/trading/__generated__/models/V3PoolInRoute.ts +24 -0
- package/src/clients/trading/__generated__/models/V4PoolInRoute.ts +30 -0
- package/src/clients/trading/__generated__/models/WalletCheckDelegationRequestBody.ts +17 -0
- package/src/clients/trading/__generated__/models/WalletCheckDelegationResponseBody.ts +14 -0
- package/src/clients/trading/__generated__/models/WalletEncode7702RequestBody.ts +21 -0
- package/src/clients/trading/__generated__/models/WalletExecutionContext.ts +17 -0
- package/src/clients/trading/__generated__/models/WalletInfo.ts +22 -0
- package/src/clients/trading/__generated__/models/WalletProperties.ts +12 -0
- package/src/clients/trading/__generated__/models/WrapUnwrapQuote.ts +31 -0
- package/src/clients/trading/__generated__/models/additionalValidationContract.ts +9 -0
- package/src/clients/trading/__generated__/models/additionalValidationData.ts +9 -0
- package/src/clients/trading/__generated__/models/bps.ts +8 -0
- package/src/clients/trading/__generated__/models/bpsFee.ts +8 -0
- package/src/clients/trading/__generated__/models/bridgeTokenInChainIdParam.ts +6 -0
- package/src/clients/trading/__generated__/models/chainIdParam.ts +6 -0
- package/src/clients/trading/__generated__/models/claimerWalletAddress.ts +8 -0
- package/src/clients/trading/__generated__/models/contractAddress.ts +8 -0
- package/src/clients/trading/__generated__/models/cosignerAddress.ts +8 -0
- package/src/clients/trading/__generated__/models/cursorParam.ts +5 -0
- package/src/clients/trading/__generated__/models/deadline.ts +8 -0
- package/src/clients/trading/__generated__/models/encodedOrder.ts +8 -0
- package/src/clients/trading/__generated__/models/endAmount.ts +8 -0
- package/src/clients/trading/__generated__/models/erc20EthEnabledHeader.ts +8 -0
- package/src/clients/trading/__generated__/models/fillerParam.ts +9 -0
- package/src/clients/trading/__generated__/models/gasFee.ts +8 -0
- package/src/clients/trading/__generated__/models/gasFeeInCurrency.ts +8 -0
- package/src/clients/trading/__generated__/models/gasFeeUSD.ts +8 -0
- package/src/clients/trading/__generated__/models/gasLimit.ts +8 -0
- package/src/clients/trading/__generated__/models/gasPrice.ts +8 -0
- package/src/clients/trading/__generated__/models/generatePermitAsTransaction.ts +8 -0
- package/src/clients/trading/__generated__/models/includeGasInfo.ts +8 -0
- package/src/clients/trading/__generated__/models/inputToken.ts +8 -0
- package/src/clients/trading/__generated__/models/isSpam.ts +8 -0
- package/src/clients/trading/__generated__/models/limitParam.ts +5 -0
- package/src/clients/trading/__generated__/models/liquidity.ts +8 -0
- package/src/clients/trading/__generated__/models/lpPoolFee.ts +8 -0
- package/src/clients/trading/__generated__/models/lpTickCurrent.ts +8 -0
- package/src/clients/trading/__generated__/models/maxFeePerGas.ts +8 -0
- package/src/clients/trading/__generated__/models/maxPriorityFeePerGas.ts +8 -0
- package/src/clients/trading/__generated__/models/minAmount.ts +8 -0
- package/src/clients/trading/__generated__/models/nonce.ts +8 -0
- package/src/clients/trading/__generated__/models/orderId.ts +8 -0
- package/src/clients/trading/__generated__/models/orderIdParam.ts +6 -0
- package/src/clients/trading/__generated__/models/orderIdsParam.ts +9 -0
- package/src/clients/trading/__generated__/models/orderStatusParam.ts +9 -0
- package/src/clients/trading/__generated__/models/orderTypeParam.ts +9 -0
- package/src/clients/trading/__generated__/models/outputToken.ts +8 -0
- package/src/clients/trading/__generated__/models/poolFee.ts +8 -0
- package/src/clients/trading/__generated__/models/portionAmount.ts +8 -0
- package/src/clients/trading/__generated__/models/portionAmountReceiverAddress.ts +8 -0
- package/src/clients/trading/__generated__/models/portionBips.ts +8 -0
- package/src/clients/trading/__generated__/models/quoteId.ts +8 -0
- package/src/clients/trading/__generated__/models/receiverWalletAddress.ts +8 -0
- package/src/clients/trading/__generated__/models/senderWalletAddress.ts +8 -0
- package/src/clients/trading/__generated__/models/slippageTolerance.ts +14 -0
- package/src/clients/trading/__generated__/models/sortKeyParam.ts +9 -0
- package/src/clients/trading/__generated__/models/sortParam.ts +8 -0
- package/src/clients/trading/__generated__/models/sqrtRatioX96.ts +8 -0
- package/src/clients/trading/__generated__/models/startAmount.ts +8 -0
- package/src/clients/trading/__generated__/models/swapperParam.ts +9 -0
- package/src/clients/trading/__generated__/models/tickCurrent.ts +8 -0
- package/src/clients/trading/__generated__/models/tickSpacing.ts +8 -0
- package/src/clients/trading/__generated__/models/tokenAmount.ts +8 -0
- package/src/clients/trading/__generated__/models/tokenInParam.ts +6 -0
- package/src/clients/trading/__generated__/models/tokenSymbol.ts +8 -0
- package/src/clients/trading/__generated__/models/transactionHashesParam.ts +9 -0
- package/src/clients/trading/__generated__/models/universalRouterVersionHeader.ts +9 -0
- package/src/clients/trading/__generated__/services/ApprovalService.ts +39 -0
- package/src/clients/trading/__generated__/services/DefaultService.ts +46 -0
- package/src/clients/trading/__generated__/services/IndicativeQuoteService.ts +39 -0
- package/src/clients/trading/__generated__/services/LimitOrderQuoteService.ts +37 -0
- package/src/clients/trading/__generated__/services/LiquidityService.ts +239 -0
- package/src/clients/trading/__generated__/services/OrderService.ts +131 -0
- package/src/clients/trading/__generated__/services/PlanService.ts +76 -0
- package/src/clients/trading/__generated__/services/QuoteService.ts +58 -0
- package/src/clients/trading/__generated__/services/SendService.ts +37 -0
- package/src/clients/trading/__generated__/services/SwapService.ts +161 -0
- package/src/clients/trading/__generated__/services/SwappableTokensService.ts +42 -0
- package/src/clients/trading/__generated__/services/WalletCheckDelegationService.ts +37 -0
- package/src/clients/trading/__generated__/services/WalletEncode7702Service.ts +37 -0
- package/src/clients/trading/api.json +1 -0
- package/src/clients/trading/createTradingApiClient.ts +328 -0
- package/src/clients/trading/tradeTypes.ts +51 -0
- package/src/clients/trading/types.ts +72 -0
- package/src/clients/unitags/createUnitagsApiClient.test.ts +438 -0
- package/src/clients/unitags/createUnitagsApiClient.ts +214 -0
- package/src/clients/unitags/types.ts +122 -0
- package/src/components/ApiInit.test.tsx +364 -0
- package/src/components/ApiInit.tsx +71 -0
- package/src/connectRpc/base.ts +33 -0
- package/src/connectRpc/utils.ts +136 -0
- package/src/getEntryGatewayUrl.ts +46 -0
- package/src/getWebSocketUrl.ts +28 -0
- package/src/global.d.ts +2 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/shared/types.ts +10 -0
- package/src/hooks/shared/useQueryWithImmediateGarbageCollection.ts +90 -0
- package/src/hooks/use-token-list.ts +52 -0
- package/src/hooks/use-token-price.ts +82 -0
- package/src/hooks/useIsSessionInitialized.ts +17 -0
- package/src/index.ts +318 -0
- package/src/provideDeviceIdService.ts +25 -0
- package/src/provideLuxIdentifierService.ts +25 -0
- package/src/provideSessionService.native.ts +46 -0
- package/src/provideSessionService.ts +13 -0
- package/src/provideSessionService.web.ts +87 -0
- package/src/provideSessionStorage.ts +21 -0
- package/src/session/createSessionTransport.test.ts +79 -0
- package/src/session/createSessionTransport.ts +107 -0
- package/src/session/createWithSessionRetry.ts +33 -0
- package/src/session/index.ts +12 -0
- package/src/storage/createExtensionStorageDriver.ts +29 -0
- package/src/storage/createNativeStorageDriver.ts +19 -0
- package/src/storage/createWebStorageDriver.ts +17 -0
- package/src/storage/getStorageDriver.native.ts +6 -0
- package/src/storage/getStorageDriver.ts +8 -0
- package/src/storage/getStorageDriver.web.ts +11 -0
- package/src/storage/types.ts +9 -0
- package/src/transport.ts +85 -0
- package/stubs/privy-service-connect.d.ts +3 -0
- package/stubs/privy-service-pb.d.ts +60 -0
- package/tsconfig.json +37 -0
- package/tsconfig.lint.json +8 -0
- package/tsconfig.spec.json +8 -0
- package/vitest.config.ts +14 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Internal types
|
|
2
|
+
|
|
3
|
+
export type UnitagClaim = {
|
|
4
|
+
address?: string
|
|
5
|
+
username: string
|
|
6
|
+
avatarUri?: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type UnitagClaimSource = 'onboarding' | 'home' | 'settings'
|
|
10
|
+
|
|
11
|
+
export type UnitagClaimContext = {
|
|
12
|
+
source: UnitagClaimSource
|
|
13
|
+
hasENSAddress: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// API types
|
|
17
|
+
|
|
18
|
+
export type UnitagUsernameRequest = {
|
|
19
|
+
username: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type UnitagUsernameResponse = {
|
|
23
|
+
available: boolean
|
|
24
|
+
requiresEnsMatch: boolean
|
|
25
|
+
metadata?: ProfileMetadata
|
|
26
|
+
username?: string
|
|
27
|
+
address?: {
|
|
28
|
+
address: Address
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type UnitagAddressRequest = {
|
|
33
|
+
address: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type UnitagAddressResponse = {
|
|
37
|
+
username?: string
|
|
38
|
+
address?: Address
|
|
39
|
+
metadata?: ProfileMetadata
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type UnitagAddressesRequest = {
|
|
43
|
+
addresses: Address[]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type UnitagAddressesResponse = {
|
|
47
|
+
usernames: {
|
|
48
|
+
[address: Address]: UnitagAddressResponse
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type UnitagResponse = {
|
|
53
|
+
success: boolean
|
|
54
|
+
errorCode?: UnitagErrorCodes
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type UnitagClaimEligibilityResponse = {
|
|
58
|
+
canClaim: boolean
|
|
59
|
+
errorCode?: UnitagErrorCodes
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type ProfileMetadata = {
|
|
63
|
+
avatar?: string
|
|
64
|
+
description?: string
|
|
65
|
+
twitter?: string
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type UnitagClaimUsernameRequestBody = {
|
|
69
|
+
username: string
|
|
70
|
+
deviceId: string
|
|
71
|
+
metadata?: ProfileMetadata
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export type UnitagClaimEligibilityRequest = {
|
|
75
|
+
address?: Address
|
|
76
|
+
deviceId: string
|
|
77
|
+
isUsernameChange?: boolean
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type UnitagUpdateMetadataRequestBody = {
|
|
81
|
+
metadata: ProfileMetadata
|
|
82
|
+
clearAvatar?: boolean
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export type UnitagUpdateMetadataResponse = {
|
|
86
|
+
success: boolean
|
|
87
|
+
metadata?: ProfileMetadata
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export type UnitagGetAvatarUploadUrlResponse = {
|
|
91
|
+
success: boolean
|
|
92
|
+
avatarUrl?: string
|
|
93
|
+
preSignedUrl?: string
|
|
94
|
+
s3UploadFields?: Record<string, string>
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export type UnitagDeleteUsernameRequestBody = {
|
|
98
|
+
username: string
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export type UnitagAvatarUploadCredentials = {
|
|
102
|
+
preSignedUrl?: string
|
|
103
|
+
s3UploadFields?: Record<string, string>
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export type UnitagChangeUsernameRequestBody = {
|
|
107
|
+
username: string
|
|
108
|
+
deviceId: string
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Copied enum from unitags backend code -- needs to be up-to-date
|
|
112
|
+
export enum UnitagErrorCodes {
|
|
113
|
+
UnitagNotAvailable = 'unitags-1',
|
|
114
|
+
RequiresENSMatch = 'unitags-2',
|
|
115
|
+
IPLimitReached = 'unitags-3',
|
|
116
|
+
AddressLimitReached = 'unitags-4',
|
|
117
|
+
DeviceLimitReached = 'unitags-5',
|
|
118
|
+
DeviceActiveLimitReached = 'unitags-6',
|
|
119
|
+
AddressActiveLimitReached = 'unitags-7',
|
|
120
|
+
NoUnitagForAddress = 'unitags-8',
|
|
121
|
+
UnitagNotActive = 'unitags-9',
|
|
122
|
+
}
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
2
|
+
import { render, waitFor } from '@testing-library/react'
|
|
3
|
+
import { ApiInit } from '@luxfi/api/src/components/ApiInit'
|
|
4
|
+
import {
|
|
5
|
+
ChallengeType,
|
|
6
|
+
createChallengeSolverService,
|
|
7
|
+
createDeviceIdService,
|
|
8
|
+
createNoopPerformanceTracker,
|
|
9
|
+
createSessionInitializationService,
|
|
10
|
+
createSessionRepository,
|
|
11
|
+
createSessionService,
|
|
12
|
+
createSessionStorage,
|
|
13
|
+
createLuxIdentifierService,
|
|
14
|
+
type DeviceIdService,
|
|
15
|
+
type SessionInitializationService,
|
|
16
|
+
type SessionService,
|
|
17
|
+
type SessionStorage,
|
|
18
|
+
type LuxIdentifierService,
|
|
19
|
+
} from '@luxfi/sessions'
|
|
20
|
+
import React from 'react'
|
|
21
|
+
import { sleep } from '@luxfi/utilities/src/time/timing'
|
|
22
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
23
|
+
|
|
24
|
+
// Mock platform detection - we're testing as extension by default
|
|
25
|
+
vi.mock('@luxfi/utilities/src/platform', () => ({
|
|
26
|
+
isWeb: false,
|
|
27
|
+
isExtension: true,
|
|
28
|
+
isInterface: false,
|
|
29
|
+
}))
|
|
30
|
+
|
|
31
|
+
describe('ApiInit Integration', () => {
|
|
32
|
+
// Services and mocked boundaries
|
|
33
|
+
let queryClient: QueryClient
|
|
34
|
+
let mockStorage: Map<string, any>
|
|
35
|
+
let mockApiClient: {
|
|
36
|
+
initSession: ReturnType<typeof vi.fn>
|
|
37
|
+
challenge: ReturnType<typeof vi.fn>
|
|
38
|
+
verify: ReturnType<typeof vi.fn>
|
|
39
|
+
}
|
|
40
|
+
let sessionStorage: SessionStorage
|
|
41
|
+
let deviceIdService: DeviceIdService
|
|
42
|
+
let luxIdentifierService: LuxIdentifierService
|
|
43
|
+
let sessionService: SessionService
|
|
44
|
+
let initService: SessionInitializationService
|
|
45
|
+
let isSessionServiceEnabled: boolean
|
|
46
|
+
|
|
47
|
+
beforeEach(() => {
|
|
48
|
+
vi.clearAllMocks()
|
|
49
|
+
// Default to enabled
|
|
50
|
+
isSessionServiceEnabled = true
|
|
51
|
+
|
|
52
|
+
// Mock only the boundaries (storage and network)
|
|
53
|
+
mockStorage = new Map()
|
|
54
|
+
mockApiClient = {
|
|
55
|
+
initSession: vi.fn().mockResolvedValue({
|
|
56
|
+
sessionId: 'test-session-123',
|
|
57
|
+
needChallenge: false,
|
|
58
|
+
extra: {},
|
|
59
|
+
}),
|
|
60
|
+
challenge: vi.fn().mockResolvedValue({
|
|
61
|
+
challengeId: 'challenge-456',
|
|
62
|
+
challengeType: ChallengeType.TURNSTILE,
|
|
63
|
+
extra: { sitekey: 'mock-sitekey' },
|
|
64
|
+
challengeData: { case: undefined },
|
|
65
|
+
}),
|
|
66
|
+
verify: vi.fn().mockResolvedValue({
|
|
67
|
+
retry: false,
|
|
68
|
+
}),
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Create REAL service instances with mocked boundaries
|
|
72
|
+
sessionStorage = createSessionStorage({
|
|
73
|
+
getSessionId: async () => mockStorage.get('sessionId') || null,
|
|
74
|
+
setSessionId: async (id) => {
|
|
75
|
+
mockStorage.set('sessionId', id)
|
|
76
|
+
},
|
|
77
|
+
clearSessionId: async () => {
|
|
78
|
+
mockStorage.delete('sessionId')
|
|
79
|
+
},
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
deviceIdService = createDeviceIdService({
|
|
83
|
+
getDeviceId: async () => mockStorage.get('deviceId') || '',
|
|
84
|
+
setDeviceId: async (id) => {
|
|
85
|
+
mockStorage.set('deviceId', id)
|
|
86
|
+
},
|
|
87
|
+
removeDeviceId: async () => {
|
|
88
|
+
mockStorage.delete('deviceId')
|
|
89
|
+
},
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
luxIdentifierService = createLuxIdentifierService({
|
|
93
|
+
getLuxIdentifier: async () => mockStorage.get('luxIdentifier') || null,
|
|
94
|
+
setLuxIdentifier: async (identifier) => {
|
|
95
|
+
mockStorage.set('luxIdentifier', identifier)
|
|
96
|
+
},
|
|
97
|
+
removeLuxIdentifier: async () => {
|
|
98
|
+
mockStorage.delete('luxIdentifier')
|
|
99
|
+
},
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
const sessionRepository = createSessionRepository({
|
|
103
|
+
client: mockApiClient as any,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
sessionService = createSessionService({
|
|
107
|
+
sessionStorage,
|
|
108
|
+
deviceIdService,
|
|
109
|
+
luxIdentifierService,
|
|
110
|
+
sessionRepository,
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
const challengeSolverService = createChallengeSolverService()
|
|
114
|
+
// Add a mock solver for Turnstile
|
|
115
|
+
challengeSolverService.getSolver = vi.fn().mockReturnValue({
|
|
116
|
+
solve: vi.fn().mockResolvedValue('mock-solution'),
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
initService = createSessionInitializationService({
|
|
120
|
+
getSessionService: () => sessionService,
|
|
121
|
+
challengeSolverService,
|
|
122
|
+
performanceTracker: createNoopPerformanceTracker(),
|
|
123
|
+
getIsSessionUpgradeAutoEnabled: () => true,
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
// Fresh query client for each test
|
|
127
|
+
queryClient = new QueryClient({
|
|
128
|
+
defaultOptions: {
|
|
129
|
+
queries: {
|
|
130
|
+
retry: false,
|
|
131
|
+
gcTime: 0,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
afterEach(() => {
|
|
138
|
+
vi.clearAllMocks()
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it('initializes session and makes it available for API requests', async () => {
|
|
142
|
+
// Act: Render the component
|
|
143
|
+
render(
|
|
144
|
+
<QueryClientProvider client={queryClient}>
|
|
145
|
+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
|
|
146
|
+
</QueryClientProvider>,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
// Assert: Session was initialized
|
|
150
|
+
await waitFor(() => {
|
|
151
|
+
expect(mockApiClient.initSession).toHaveBeenCalled()
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
// Wait a bit for async storage operations to complete
|
|
155
|
+
await sleep(50)
|
|
156
|
+
|
|
157
|
+
// Assert: Session is now stored and retrievable
|
|
158
|
+
const storedSession = await sessionStorage.get()
|
|
159
|
+
expect(storedSession?.sessionId).toBe('test-session-123')
|
|
160
|
+
|
|
161
|
+
// Verify storage was actually set
|
|
162
|
+
expect(mockStorage.get('sessionId')).toBe('test-session-123')
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
it('completes challenge flow when required by server', async () => {
|
|
166
|
+
// Setup: Server requires challenge
|
|
167
|
+
mockApiClient.initSession.mockResolvedValue({
|
|
168
|
+
sessionId: 'challenge-session',
|
|
169
|
+
needChallenge: true,
|
|
170
|
+
extra: {},
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
// Act
|
|
174
|
+
render(
|
|
175
|
+
<QueryClientProvider client={queryClient}>
|
|
176
|
+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
|
|
177
|
+
</QueryClientProvider>,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
// Assert: Full flow completes
|
|
181
|
+
await waitFor(() => {
|
|
182
|
+
expect(mockApiClient.initSession).toHaveBeenCalled()
|
|
183
|
+
expect(mockApiClient.challenge).toHaveBeenCalled()
|
|
184
|
+
expect(mockApiClient.verify).toHaveBeenCalled()
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
// Assert: Session is stored after challenge
|
|
188
|
+
const storedSession = await sessionStorage.get()
|
|
189
|
+
expect(storedSession?.sessionId).toBe('challenge-session')
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
it('always calls initSession - backend handles session reuse', async () => {
|
|
193
|
+
// Setup: Pre-populate storage with existing session
|
|
194
|
+
await sessionStorage.set({ sessionId: 'existing-session' })
|
|
195
|
+
|
|
196
|
+
// Mock backend to return the same session ID (simulating session reuse)
|
|
197
|
+
mockApiClient.initSession.mockResolvedValue({
|
|
198
|
+
sessionId: 'existing-session',
|
|
199
|
+
needChallenge: false,
|
|
200
|
+
extra: {},
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
// Act
|
|
204
|
+
render(
|
|
205
|
+
<QueryClientProvider client={queryClient}>
|
|
206
|
+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
|
|
207
|
+
</QueryClientProvider>,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
// Wait for initialization
|
|
211
|
+
await waitFor(() => {
|
|
212
|
+
expect(mockApiClient.initSession).toHaveBeenCalled()
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
// Assert: initSession IS called (backend decides to reuse based on X-Session-ID header)
|
|
216
|
+
expect(mockApiClient.initSession).toHaveBeenCalledTimes(1)
|
|
217
|
+
|
|
218
|
+
// Session in storage should match what backend returned
|
|
219
|
+
const storedSession = await sessionStorage.get()
|
|
220
|
+
expect(storedSession?.sessionId).toBe('existing-session')
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
it('retries initialization on transient failures', async () => {
|
|
224
|
+
// Use fake timers to speed up retry delays
|
|
225
|
+
vi.useFakeTimers()
|
|
226
|
+
|
|
227
|
+
let attemptCount = 0
|
|
228
|
+
|
|
229
|
+
// Mock the initialize method of the initService directly
|
|
230
|
+
// This will properly trigger React Query's retry logic
|
|
231
|
+
initService.initialize = vi.fn().mockImplementation(async () => {
|
|
232
|
+
attemptCount++
|
|
233
|
+
if (attemptCount < 3) {
|
|
234
|
+
throw new Error('Network error')
|
|
235
|
+
}
|
|
236
|
+
// Mock successful initialization after retries
|
|
237
|
+
await sessionStorage.set({ sessionId: 'retry-success' })
|
|
238
|
+
return { sessionId: 'retry-success', needChallenge: false, extra: {} }
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
// Use query client with no default retries - component controls retry
|
|
242
|
+
const retryClient = new QueryClient({
|
|
243
|
+
defaultOptions: {
|
|
244
|
+
queries: {
|
|
245
|
+
retry: false, // Let component control retries
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
// Act
|
|
251
|
+
render(
|
|
252
|
+
<QueryClientProvider client={retryClient}>
|
|
253
|
+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
|
|
254
|
+
</QueryClientProvider>,
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
// Fast-forward through the retry delays
|
|
258
|
+
await vi.waitFor(
|
|
259
|
+
async () => {
|
|
260
|
+
// Advance timers to trigger retries
|
|
261
|
+
await vi.advanceTimersByTimeAsync(1000) // First retry after 1000ms
|
|
262
|
+
await vi.advanceTimersByTimeAsync(2000) // Second retry after 2000ms
|
|
263
|
+
expect(initService.initialize).toHaveBeenCalledTimes(3)
|
|
264
|
+
},
|
|
265
|
+
{ timeout: 500 }, // Much faster with fake timers
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
const storedSession = await sessionStorage.get()
|
|
269
|
+
expect(storedSession?.sessionId).toBe('retry-success')
|
|
270
|
+
|
|
271
|
+
// Restore real timers
|
|
272
|
+
vi.useRealTimers()
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
it('prevents duplicate initialization on re-renders', async () => {
|
|
276
|
+
const { rerender } = render(
|
|
277
|
+
<QueryClientProvider client={queryClient}>
|
|
278
|
+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
|
|
279
|
+
</QueryClientProvider>,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
await waitFor(() => {
|
|
283
|
+
expect(mockApiClient.initSession).toHaveBeenCalledTimes(1)
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
// Re-render multiple times
|
|
287
|
+
rerender(
|
|
288
|
+
<QueryClientProvider client={queryClient}>
|
|
289
|
+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
|
|
290
|
+
</QueryClientProvider>,
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
rerender(
|
|
294
|
+
<QueryClientProvider client={queryClient}>
|
|
295
|
+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
|
|
296
|
+
</QueryClientProvider>,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
// Wait to ensure no additional calls
|
|
300
|
+
await sleep(100)
|
|
301
|
+
|
|
302
|
+
// Assert: Still only initialized once due to React Query caching
|
|
303
|
+
expect(mockApiClient.initSession).toHaveBeenCalledTimes(1)
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
it('should not initialize session when feature flag is disabled', async () => {
|
|
307
|
+
// Set feature flag as disabled
|
|
308
|
+
isSessionServiceEnabled = false
|
|
309
|
+
|
|
310
|
+
render(
|
|
311
|
+
<QueryClientProvider client={queryClient}>
|
|
312
|
+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
|
|
313
|
+
</QueryClientProvider>,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
// Wait to ensure no calls are made
|
|
317
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
318
|
+
|
|
319
|
+
// Assert: No session initialization should occur
|
|
320
|
+
expect(mockApiClient.initSession).not.toHaveBeenCalled()
|
|
321
|
+
expect(mockApiClient.challenge).not.toHaveBeenCalled()
|
|
322
|
+
expect(mockApiClient.verify).not.toHaveBeenCalled()
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
it('should wait for feature flag to be enabled before initializing session', async () => {
|
|
326
|
+
// Start with feature flag disabled (simulating Statsig loading)
|
|
327
|
+
isSessionServiceEnabled = false
|
|
328
|
+
|
|
329
|
+
const { rerender } = render(
|
|
330
|
+
<QueryClientProvider client={queryClient}>
|
|
331
|
+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
|
|
332
|
+
</QueryClientProvider>,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
// Assert that initialization does not happen while flag is disabled
|
|
336
|
+
// Use a try/catch with waitFor to verify the call never happens
|
|
337
|
+
await expect(
|
|
338
|
+
waitFor(
|
|
339
|
+
() => {
|
|
340
|
+
expect(mockApiClient.initSession).toHaveBeenCalled()
|
|
341
|
+
},
|
|
342
|
+
{ timeout: 100 },
|
|
343
|
+
),
|
|
344
|
+
).rejects.toThrow()
|
|
345
|
+
|
|
346
|
+
// Verify it still hasn't been called
|
|
347
|
+
expect(mockApiClient.initSession).not.toHaveBeenCalled()
|
|
348
|
+
|
|
349
|
+
// Now simulate feature flag becoming enabled (Statsig loaded)
|
|
350
|
+
isSessionServiceEnabled = true
|
|
351
|
+
|
|
352
|
+
// Trigger a re-render
|
|
353
|
+
rerender(
|
|
354
|
+
<QueryClientProvider client={queryClient}>
|
|
355
|
+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
|
|
356
|
+
</QueryClientProvider>,
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
// Now session initialization should occur
|
|
360
|
+
await waitFor(() => {
|
|
361
|
+
expect(mockApiClient.initSession).toHaveBeenCalled()
|
|
362
|
+
})
|
|
363
|
+
})
|
|
364
|
+
})
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { queryOptions, useQuery } from '@tanstack/react-query'
|
|
2
|
+
import { SharedQueryClient } from '@luxexchange/api/src/clients/base/SharedQueryClient'
|
|
3
|
+
import type { SessionInitializationService, SessionInitResult } from '@luxexchange/sessions'
|
|
4
|
+
import { SessionError } from '@luxexchange/sessions'
|
|
5
|
+
import { useState } from 'react'
|
|
6
|
+
import type { Logger } from '@luxfi/utilities/src/logger/logger'
|
|
7
|
+
import { ReactQueryCacheKey } from '@luxfi/utilities/src/reactQuery/cache'
|
|
8
|
+
|
|
9
|
+
interface ApiInitProps {
|
|
10
|
+
getSessionInitService: () => SessionInitializationService
|
|
11
|
+
isSessionServiceEnabled: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Query key for session initialization.
|
|
16
|
+
* Shared between ApiInit (which triggers the query) and InitializationStatusProvider (which observes it).
|
|
17
|
+
*/
|
|
18
|
+
export const SESSION_INIT_QUERY_KEY = [ReactQueryCacheKey.Session, 'initialization'] as const
|
|
19
|
+
|
|
20
|
+
function createInitServiceQuery(ctx: {
|
|
21
|
+
getSessionInitService: () => SessionInitializationService
|
|
22
|
+
getLogger?: () => Logger
|
|
23
|
+
}): ReturnType<typeof queryOptions<SessionInitResult>> {
|
|
24
|
+
return queryOptions<SessionInitResult>({
|
|
25
|
+
queryKey: SESSION_INIT_QUERY_KEY,
|
|
26
|
+
queryFn: async (): Promise<SessionInitResult> => {
|
|
27
|
+
const service = ctx.getSessionInitService()
|
|
28
|
+
return service.initialize()
|
|
29
|
+
},
|
|
30
|
+
retry: (failureCount, error) => {
|
|
31
|
+
const logger = ctx.getLogger?.()
|
|
32
|
+
// Don't retry any session-related errors - these are terminal errors
|
|
33
|
+
if (error instanceof SessionError) {
|
|
34
|
+
logger?.error(error, {
|
|
35
|
+
tags: {
|
|
36
|
+
file: 'ApiInit.tsx',
|
|
37
|
+
function: 'createInitServiceQuery',
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
return false
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
logger?.warn('ApiInit.tsx', 'createInitServiceQuery', 'retry', failureCount, error)
|
|
44
|
+
// For other errors (network issues, etc.), retry up to 3 times
|
|
45
|
+
return failureCount < 3
|
|
46
|
+
},
|
|
47
|
+
retryDelay: (attemptIndex: number) => Math.min(1000 * 2 ** attemptIndex, 30000), // Exponential backoff
|
|
48
|
+
refetchOnMount: false,
|
|
49
|
+
refetchOnWindowFocus: false,
|
|
50
|
+
refetchOnReconnect: false,
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function ApiInit({ getSessionInitService, isSessionServiceEnabled }: ApiInitProps): null {
|
|
55
|
+
const [query] = useState(() => createInitServiceQuery({ getSessionInitService }))
|
|
56
|
+
|
|
57
|
+
useQuery({
|
|
58
|
+
...query,
|
|
59
|
+
enabled: isSessionServiceEnabled,
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
return null
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Reinitializes the session by invalidating the session initialization query. Resolves once the query has re-run. */
|
|
66
|
+
export async function reinitializeSession(): Promise<void> {
|
|
67
|
+
await SharedQueryClient.invalidateQueries({ queryKey: SESSION_INIT_QUERY_KEY })
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { ApiInit }
|
|
71
|
+
export type { ApiInitProps }
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type StreamResponse, type Transport, type UnaryResponse } from '@connectrpc/connect'
|
|
2
|
+
import { type ConnectTransportOptions, createConnectTransport } from '@connectrpc/connect-web'
|
|
3
|
+
|
|
4
|
+
// The string arg to pass to the BE for chainId to get data for all networks
|
|
5
|
+
export const ALL_NETWORKS_ARG = 'ALL_NETWORKS'
|
|
6
|
+
|
|
7
|
+
export interface ConnectRpcContext {
|
|
8
|
+
baseUrl: string
|
|
9
|
+
additionalHeaders?: HeadersInit
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const createConnectTransportWithDefaults = (
|
|
13
|
+
context: ConnectRpcContext,
|
|
14
|
+
transportOptions: Partial<ConnectTransportOptions> = {},
|
|
15
|
+
): Transport =>
|
|
16
|
+
createConnectTransport({
|
|
17
|
+
baseUrl: context.baseUrl,
|
|
18
|
+
interceptors: context.additionalHeaders
|
|
19
|
+
? [
|
|
20
|
+
(next) =>
|
|
21
|
+
(request): Promise<UnaryResponse | StreamResponse> => {
|
|
22
|
+
if (context.additionalHeaders) {
|
|
23
|
+
const headers = new Headers(context.additionalHeaders)
|
|
24
|
+
headers.forEach((value, key) => {
|
|
25
|
+
request.header.set(key, value)
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
return next(request)
|
|
29
|
+
},
|
|
30
|
+
]
|
|
31
|
+
: [],
|
|
32
|
+
...transportOptions,
|
|
33
|
+
})
|