diff --git a/apps/hyperdrive-trading/.env.sample b/apps/hyperdrive-trading/.env.sample index 378d6a118..0b62be5ed 100644 --- a/apps/hyperdrive-trading/.env.sample +++ b/apps/hyperdrive-trading/.env.sample @@ -59,3 +59,9 @@ VITE_ADDRESS_SCREEN_URL= # Used to screen VPN, proxy, and Tor Exit Node IP addresses. VITE_VPN_SCREEN_URL= ################################################## + +################################################## +# Rewards +VITE_REWARDS_BASE_URL=https://rewards.hyperdrive.money/swagger + +################################################## diff --git a/apps/hyperdrive-trading/package.json b/apps/hyperdrive-trading/package.json index fd51e4314..8868b690c 100644 --- a/apps/hyperdrive-trading/package.json +++ b/apps/hyperdrive-trading/package.json @@ -25,7 +25,8 @@ "test:watch": "vitest --reporter=verbose", "typecheck": "tsc --project tsconfig.json --noEmit", "gen:version": "bash ./scripts/generate-version.sh", - "gen:walletconnect": "bash ./scripts/generate-walletconnect.sh" + "gen:walletconnect": "bash ./scripts/generate-walletconnect.sh", + "gen:rewards-swagger": "bash ./scripts/generate-rewards-swagger.sh" }, "dependencies": { "@delvtech/drift": "^0.0.1-beta.11", @@ -41,7 +42,7 @@ "@tanstack/react-query": "^4.29.12", "@tanstack/react-router": "^1.87.7", "@tanstack/router-devtools": "^1.87.7", - "@tanstack/react-table": "^8.10.3", + "@tanstack/react-table": "^8.20.5", "@tanstack/query-core": "^4.36.1", "@types/d3-format": "^3.0.4", "@types/lodash.sortby": "^4.7.9", @@ -77,6 +78,7 @@ }, "devDependencies": { "@hyperdrive/eslint-config": "*", + "swagger-typescript-api": "^13.0.23", "@hyperdrive/prettier-config": "*", "@hyperdrive/tsconfig": "*", "@tanstack/eslint-plugin-query": "^5.28.11", diff --git a/apps/hyperdrive-trading/scripts/generate-rewards-swagger.sh b/apps/hyperdrive-trading/scripts/generate-rewards-swagger.sh new file mode 100644 index 000000000..108051c08 --- /dev/null +++ b/apps/hyperdrive-trading/scripts/generate-rewards-swagger.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Define the URL and output file path +URL="https://rewards.hyperdrive.money/swagger.json" +OUTPUT_DIR="src/rewards/generated" +SWAGGER_FILE="$OUTPUT_DIR/rewards-swagger.json" +TYPES_FILE="RewardsClient.ts" +CUSTOM_CONFIG="src/rewards/config.js" + +# Create the directory if it doesn't exist +mkdir -p "$(dirname "$SWAGGER_FILE")" + +# Download the file +curl -o "$SWAGGER_FILE" "$URL" + +# Check if the download was successful +if [ $? -eq 0 ]; then + echo "File downloaded successfully and saved to $SWAGGER_FILE" +else + echo "Failed to download the file from $URL" + exit 1 +fi + +npx swagger-typescript-api \ + -p $SWAGGER_FILE \ + -o $OUTPUT_DIR \ + -n $TYPES_FILE \ + --api-class-name RewardsApi \ + --custom-config $CUSTOM_CONFIG \ + --unwrap-response-data + diff --git a/apps/hyperdrive-trading/src/rewards/config.js b/apps/hyperdrive-trading/src/rewards/config.js new file mode 100644 index 000000000..1dfd44a5c --- /dev/null +++ b/apps/hyperdrive-trading/src/rewards/config.js @@ -0,0 +1,26 @@ +// swagger-typescript-api config file + +module.exports = { + codeGenConstructs: (constructs) => { + return { + ...constructs, + TypeField: ({ key, value, readonly, optional }) => { + let fieldValue = value; + // Convert vanilla string to the appropriate address type + if (key.endsWith("Address")) { + fieldValue = "`0x${string}`"; + } + + if (key.endsWith("Proof")) { + fieldValue = "`0x${string}`[]"; + } + + return [readonly && "readonly ", key, optional && "?", ": ", fieldValue] + .filter(Boolean) + .join(""); + }, + }; + }, + // TODO: Convert fields ending with "-Amount" from string to bigint. This will + // require post-processing in the api client +}; diff --git a/apps/hyperdrive-trading/src/rewards/generated/RewardsClient.ts b/apps/hyperdrive-trading/src/rewards/generated/RewardsClient.ts new file mode 100644 index 000000000..619818f0a --- /dev/null +++ b/apps/hyperdrive-trading/src/rewards/generated/RewardsClient.ts @@ -0,0 +1,318 @@ +/* eslint-disable */ +/* tslint:disable */ +/* + * --------------------------------------------------------------- + * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ## + * ## ## + * ## AUTHOR: acacode ## + * ## SOURCE: https://github.com/acacode/swagger-typescript-api ## + * --------------------------------------------------------------- + */ + +export interface RewardsResponse { + /** + * The user's blockchain address. + * @example "0x1234567890abcdef1234567890abcdef12345678" + */ + userAddress: `0x${string}`; + rewards: Rewards; +} + +export type Rewards = { + /** @example 1 */ + chainId: number; + /** + * Address of the claim contract. + * @example "0x0000000000000000000000000000000000000000" + */ + claimContractAddress: `0x${string}`; + /** + * Amount of tokens claimable. + * @example "1000000000000000000" + */ + claimable: string; + /** + * Token address of the reward. + * @example "0xBAa5CC21fd487B8Fcc2F632f3F4E8D37262a0842" + */ + rewardTokenAddress: `0x${string}`; + /** @example ["0xProof1","0xProof2","0xProof3"] */ + merkleProof: `0x${string}`[]; + /** + * Timestamp of the last merkle proof update. + * @example 123892327 + */ + merkleProofLastUpdated: number; +}[]; + +export type QueryParamsType = Record; +export type ResponseFormat = keyof Omit; + +export interface FullRequestParams extends Omit { + /** set parameter to `true` for call `securityWorker` for this request */ + secure?: boolean; + /** request path */ + path: string; + /** content type of request body */ + type?: ContentType; + /** query params */ + query?: QueryParamsType; + /** format of response (i.e. response.json() -> format: "json") */ + format?: ResponseFormat; + /** request body */ + body?: unknown; + /** base url */ + baseUrl?: string; + /** request cancellation token */ + cancelToken?: CancelToken; +} + +export type RequestParams = Omit< + FullRequestParams, + "body" | "method" | "query" | "path" +>; + +export interface ApiConfig { + baseUrl?: string; + baseApiParams?: Omit; + securityWorker?: ( + securityData: SecurityDataType | null, + ) => Promise | RequestParams | void; + customFetch?: typeof fetch; +} + +export interface HttpResponse + extends Response { + data: D; + error: E; +} + +type CancelToken = Symbol | string | number; + +export enum ContentType { + Json = "application/json", + FormData = "multipart/form-data", + UrlEncoded = "application/x-www-form-urlencoded", + Text = "text/plain", +} + +export class HttpClient { + public baseUrl: string = "https://rewards.hyperdrive.money"; + private securityData: SecurityDataType | null = null; + private securityWorker?: ApiConfig["securityWorker"]; + private abortControllers = new Map(); + private customFetch = (...fetchParams: Parameters) => + fetch(...fetchParams); + + private baseApiParams: RequestParams = { + credentials: "same-origin", + headers: {}, + redirect: "follow", + referrerPolicy: "no-referrer", + }; + + constructor(apiConfig: ApiConfig = {}) { + Object.assign(this, apiConfig); + } + + public setSecurityData = (data: SecurityDataType | null) => { + this.securityData = data; + }; + + protected encodeQueryParam(key: string, value: any) { + const encodedKey = encodeURIComponent(key); + return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`; + } + + protected addQueryParam(query: QueryParamsType, key: string) { + return this.encodeQueryParam(key, query[key]); + } + + protected addArrayQueryParam(query: QueryParamsType, key: string) { + const value = query[key]; + return value.map((v: any) => this.encodeQueryParam(key, v)).join("&"); + } + + protected toQueryString(rawQuery?: QueryParamsType): string { + const query = rawQuery || {}; + const keys = Object.keys(query).filter( + (key) => "undefined" !== typeof query[key], + ); + return keys + .map((key) => + Array.isArray(query[key]) + ? this.addArrayQueryParam(query, key) + : this.addQueryParam(query, key), + ) + .join("&"); + } + + protected addQueryParams(rawQuery?: QueryParamsType): string { + const queryString = this.toQueryString(rawQuery); + return queryString ? `?${queryString}` : ""; + } + + private contentFormatters: Record any> = { + [ContentType.Json]: (input: any) => + input !== null && (typeof input === "object" || typeof input === "string") + ? JSON.stringify(input) + : input, + [ContentType.Text]: (input: any) => + input !== null && typeof input !== "string" + ? JSON.stringify(input) + : input, + [ContentType.FormData]: (input: any) => + Object.keys(input || {}).reduce((formData, key) => { + const property = input[key]; + formData.append( + key, + property instanceof Blob + ? property + : typeof property === "object" && property !== null + ? JSON.stringify(property) + : `${property}`, + ); + return formData; + }, new FormData()), + [ContentType.UrlEncoded]: (input: any) => this.toQueryString(input), + }; + + protected mergeRequestParams( + params1: RequestParams, + params2?: RequestParams, + ): RequestParams { + return { + ...this.baseApiParams, + ...params1, + ...(params2 || {}), + headers: { + ...(this.baseApiParams.headers || {}), + ...(params1.headers || {}), + ...((params2 && params2.headers) || {}), + }, + }; + } + + protected createAbortSignal = ( + cancelToken: CancelToken, + ): AbortSignal | undefined => { + if (this.abortControllers.has(cancelToken)) { + const abortController = this.abortControllers.get(cancelToken); + if (abortController) { + return abortController.signal; + } + return void 0; + } + + const abortController = new AbortController(); + this.abortControllers.set(cancelToken, abortController); + return abortController.signal; + }; + + public abortRequest = (cancelToken: CancelToken) => { + const abortController = this.abortControllers.get(cancelToken); + + if (abortController) { + abortController.abort(); + this.abortControllers.delete(cancelToken); + } + }; + + public request = async ({ + body, + secure, + path, + type, + query, + format, + baseUrl, + cancelToken, + ...params + }: FullRequestParams): Promise => { + const secureParams = + ((typeof secure === "boolean" ? secure : this.baseApiParams.secure) && + this.securityWorker && + (await this.securityWorker(this.securityData))) || + {}; + const requestParams = this.mergeRequestParams(params, secureParams); + const queryString = query && this.toQueryString(query); + const payloadFormatter = this.contentFormatters[type || ContentType.Json]; + const responseFormat = format || requestParams.format; + + return this.customFetch( + `${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, + { + ...requestParams, + headers: { + ...(requestParams.headers || {}), + ...(type && type !== ContentType.FormData + ? { "Content-Type": type } + : {}), + }, + signal: + (cancelToken + ? this.createAbortSignal(cancelToken) + : requestParams.signal) || null, + body: + typeof body === "undefined" || body === null + ? null + : payloadFormatter(body), + }, + ).then(async (response) => { + const r = response.clone() as HttpResponse; + r.data = null as unknown as T; + r.error = null as unknown as E; + + const data = !responseFormat + ? r + : await response[responseFormat]() + .then((data) => { + if (r.ok) { + r.data = data; + } else { + r.error = data; + } + return r; + }) + .catch((e) => { + r.error = e; + return r; + }); + + if (cancelToken) { + this.abortControllers.delete(cancelToken); + } + + if (!response.ok) throw data; + return data.data; + }); + }; +} + +/** + * @title Hyperdrive Rewards API + * @version 1.0.0 + * @baseUrl https://rewards.hyperdrive.money + * + * API documentation for Hyperdrive Rewards + */ +export class RewardsApi< + SecurityDataType extends unknown, +> extends HttpClient { + get = { + /** + * @description Returns the rewards associated with a specific address. + * + * @name RewardsDetail + * @summary Get rewards for an address. + * @request GET:/get/rewards/{address} + */ + rewardsDetail: (address: string, params: RequestParams = {}) => + this.request({ + path: `/get/rewards/${address}`, + method: "GET", + format: "json", + ...params, + }), + }; +} diff --git a/apps/hyperdrive-trading/src/rewards/generated/rewards-swagger.json b/apps/hyperdrive-trading/src/rewards/generated/rewards-swagger.json new file mode 100644 index 000000000..431a6178e --- /dev/null +++ b/apps/hyperdrive-trading/src/rewards/generated/rewards-swagger.json @@ -0,0 +1,97 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Hyperdrive Rewards API", + "version": "1.0.0", + "description": "API documentation for Hyperdrive Rewards" + }, + "servers": [{ "url": "https://rewards.hyperdrive.money" }], + "components": { + "schemas": { + "RewardsResponse": { + "type": "object", + "properties": { + "userAddress": { + "type": "string", + "description": "The user's blockchain address.", + "example": "0x1234567890abcdef1234567890abcdef12345678" + }, + "rewards": { "$ref": "#/components/schemas/Rewards" } + }, + "required": ["userAddress", "rewards"] + }, + "Rewards": { + "type": "array", + "items": { + "type": "object", + "properties": { + "chainId": { "type": "integer", "example": 1 }, + "claimContractAddress": { + "type": "string", + "description": "Address of the claim contract.", + "example": "0x0000000000000000000000000000000000000000" + }, + "claimable": { + "type": "string", + "description": "Amount of tokens claimable.", + "example": "1000000000000000000" + }, + "rewardTokenAddress": { + "type": "string", + "description": "Token address of the reward.", + "example": "0xBAa5CC21fd487B8Fcc2F632f3F4E8D37262a0842" + }, + "merkleProof": { + "type": "array", + "items": { "type": "string" }, + "nullable": true, + "example": ["0xProof1", "0xProof2", "0xProof3"] + }, + "merkleProofLastUpdated": { + "type": "integer", + "description": "Timestamp of the last merkle proof update.", + "example": 123892327 + } + }, + "required": [ + "chainId", + "claimContractAddress", + "claimable", + "rewardTokenAddress", + "merkleProof", + "merkleProofLastUpdated" + ] + } + } + } + }, + "paths": { + "/get/rewards/{address}": { + "get": { + "summary": "Get rewards for an address.", + "description": "Returns the rewards associated with a specific address.", + "parameters": [ + { + "in": "path", + "name": "address", + "required": true, + "schema": { "type": "string" }, + "description": "The address to retrieve rewards for." + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/RewardsResponse" } + } + } + }, + "400": { "description": "Bad request" } + } + } + } + }, + "tags": [] +} diff --git a/apps/hyperdrive-trading/src/ui/portfolio/rewards/RewardsContainer.tsx b/apps/hyperdrive-trading/src/ui/portfolio/rewards/RewardsContainer.tsx index 2fec0f1cd..8d5df776c 100644 --- a/apps/hyperdrive-trading/src/ui/portfolio/rewards/RewardsContainer.tsx +++ b/apps/hyperdrive-trading/src/ui/portfolio/rewards/RewardsContainer.tsx @@ -63,7 +63,9 @@ export function RewardsContainer(): ReactElement { ); } - const rewardsByChain = groupBy(rewards, (reward) => reward.chainId); + const rewardsByChain = rewards + ? groupBy(rewards, (reward) => reward.chainId) + : []; return ( diff --git a/apps/hyperdrive-trading/src/ui/portfolio/rewards/RewardsTableDesktop.tsx b/apps/hyperdrive-trading/src/ui/portfolio/rewards/RewardsTableDesktop.tsx index 7fdb097e6..ebaf1ae3f 100644 --- a/apps/hyperdrive-trading/src/ui/portfolio/rewards/RewardsTableDesktop.tsx +++ b/apps/hyperdrive-trading/src/ui/portfolio/rewards/RewardsTableDesktop.tsx @@ -10,9 +10,9 @@ import { } from "@tanstack/react-table"; import classNames from "classnames"; import { ReactElement } from "react"; +import { Rewards } from "src/rewards/generated/RewardsClient"; import { Pagination } from "src/ui/base/components/Pagination"; import { formatBalance } from "src/ui/base/formatting/formatBalance"; -import { Reward } from "src/ui/portfolio/rewards/useRewardsData"; import { Address } from "viem"; export function RewardsTableDesktop({ @@ -20,7 +20,7 @@ export function RewardsTableDesktop({ rewards, }: { account: Address; - rewards: Reward[] | undefined; + rewards: Rewards; }): ReactElement { const tableInstance = useReactTable({ columns: getColumns(), @@ -130,6 +130,8 @@ export function RewardsTableDesktop({ ); } +// TODO: Remove this type once the swagger is defined properly +type Reward = NonNullable; const columnHelper = createColumnHelper(); function getColumns() { @@ -141,7 +143,7 @@ function getColumns() { const token = getToken({ appConfig, chainId: row.original.chainId, - tokenAddress: row.original.rewardToken, + tokenAddress: row.original.rewardTokenAddress, })!; return (
@@ -158,13 +160,13 @@ function getColumns() { const token = getToken({ appConfig, chainId: row.original.chainId, - tokenAddress: row.original.rewardToken, + tokenAddress: row.original.rewardTokenAddress, })!; return (
{formatBalance({ - balance: row.original.claimable || 0n, + balance: BigInt(row.original.claimable) || 0n, decimals: token.decimals, places: token.places, })}{" "} diff --git a/apps/hyperdrive-trading/src/ui/portfolio/rewards/useRewardsData.ts b/apps/hyperdrive-trading/src/ui/portfolio/rewards/useRewardsData.ts index 3d6403a26..ebab9a627 100644 --- a/apps/hyperdrive-trading/src/ui/portfolio/rewards/useRewardsData.ts +++ b/apps/hyperdrive-trading/src/ui/portfolio/rewards/useRewardsData.ts @@ -1,63 +1,14 @@ -import { parseFixed } from "@delvtech/fixed-point-wasm"; -import { appConfig } from "@delvtech/hyperdrive-appconfig"; import { useQuery } from "@tanstack/react-query"; import { makeQueryKey } from "src/base/makeQueryKey"; -import { Address, zeroAddress } from "viem"; -import { base } from "viem/chains"; - -interface RewardsResponse { - userAddress: Address; - rewards: Reward[]; -} - -export interface Reward { - chainId: number; - claimContract: Address; - claimable: bigint; - rewardToken: Address; - merkleProof: string[] | null; - merkleProofLastUpdated: number; -} - -function getDummyRewardsResponse(account: Address) { - const dummyRewardsResponse: RewardsResponse = { - userAddress: account, - rewards: [ - { - // rewards for this user that they can claim - chainId: base.id, - claimContract: zeroAddress, - claimable: parseFixed("1000000").bigint, - rewardToken: appConfig.tokens.find( - (token) => token.chainId === 8453 && token.symbol === "MORPHO", - )!.address, - merkleProof: ["0xProof", "0xProof", "0xProof"], - merkleProofLastUpdated: 123892327, - }, - { - // rewards are accumulating, but the merkle root hasn't been added - // to the claimContract yet - chainId: base.id, - claimContract: zeroAddress, - claimable: parseFixed("0").bigint, - rewardToken: appConfig.tokens.find( - (token) => token.chainId === 8453 && token.symbol === "USDC", - )!.address, - merkleProof: null, - merkleProofLastUpdated: 123892327, - }, - ], - }; - - return dummyRewardsResponse; -} +import { Rewards, RewardsApi } from "src/rewards/generated/RewardsClient"; +import { Address } from "viem"; export function usePortfolioRewardsData({ account, }: { account: Address | undefined; }): { - rewards: Reward[] | undefined; + rewards: Rewards | undefined; rewardsStatus: "error" | "success" | "loading"; } { const queryEnabled = !!account; @@ -65,9 +16,11 @@ export function usePortfolioRewardsData({ queryKey: makeQueryKey("rewards", { account }), queryFn: queryEnabled ? async () => { - // TODO: Fetch rewards from server - const rewardsResponse = getDummyRewardsResponse(account); - return rewardsResponse.rewards; + const rewardsApi = new RewardsApi({ + baseUrl: import.meta.env.VITE_REWARDS_BASE_URL, + }); + const response = await rewardsApi.get.rewardsDetail(account); + return response.rewards; } : undefined, enabled: queryEnabled, diff --git a/turbo.json b/turbo.json index 5f75d376e..43ccc64a2 100644 --- a/turbo.json +++ b/turbo.json @@ -31,7 +31,8 @@ "VITE_ROLLBAR_ENV", "VITE_SEPOLIA_RPC_URL", "VITE_VPN_SCREEN_URL", - "VITE_WALLET_CONNECT_PROJECT_ID" + "VITE_WALLET_CONNECT_PROJECT_ID", + "VITE_REWARDS_BASE_URL" ], "outputs": ["dist/**", ".next/**"] }, diff --git a/yarn.lock b/yarn.lock index dede515a7..e934d8d7b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2978,6 +2978,11 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" +"@exodus/schemasafe@^1.0.0-rc.2": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@exodus/schemasafe/-/schemasafe-1.3.0.tgz#731656abe21e8e769a7f70a4d833e6312fe59b7f" + integrity sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw== + "@floating-ui/core@^1.6.0": version "1.6.5" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.5.tgz#102335cac0d22035b04d70ca5ff092d2d1a26f2b" @@ -4612,12 +4617,12 @@ "@tanstack/store" "0.6.0" use-sync-external-store "^1.2.2" -"@tanstack/react-table@^8.10.3": - version "8.15.0" - resolved "https://registry.yarnpkg.com/@tanstack/react-table/-/react-table-8.15.0.tgz#668ceb9f396d33409165d5b9bee7734b657061c6" - integrity sha512-8K4RSROUtXUtfiezV6Ehl8z99axFrkQnxXi0vjWBJv3Tsm5x4EyrgXI7d2tOOMoANykKZLB6S1sGZGemoMRt7Q== +"@tanstack/react-table@^8.20.5": + version "8.20.5" + resolved "https://registry.yarnpkg.com/@tanstack/react-table/-/react-table-8.20.5.tgz#19987d101e1ea25ef5406dce4352cab3932449d8" + integrity sha512-WEHopKw3znbUZ61s9i0+i9g8drmDo6asTWbrQh8Us63DAk/M0FkmIqERew6P71HI75ksZ2Pxyuf4vvKh9rAkiA== dependencies: - "@tanstack/table-core" "8.14.0" + "@tanstack/table-core" "8.20.5" "@tanstack/react-virtual@^3.8.1": version "3.10.7" @@ -4680,10 +4685,10 @@ resolved "https://registry.yarnpkg.com/@tanstack/store/-/store-0.6.0.tgz#f73d711c6e53f2f91c0f0af0771583095d449f67" integrity sha512-+m2OBglsjXcLmmKOX6/9v8BDOCtyxhMmZLsRUDswOOSdIIR9mvv6i0XNKsmTh3AlYU8c1mRcodC8/Vyf+69VlQ== -"@tanstack/table-core@8.14.0": - version "8.14.0" - resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.14.0.tgz#4c9fe8b74949bb0ffe4ac8b1937beaff1f3a19de" - integrity sha512-wDhpKJahGHWhmRt4RxtV3pES63CoeadljGWS/xeS9OJr1HBl2NB+OO44ht3sxDH5j5TRDAbQzC0NvSlsUfn7lQ== +"@tanstack/table-core@8.20.5": + version "8.20.5" + resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.20.5.tgz#3974f0b090bed11243d4107283824167a395cf1d" + integrity sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg== "@tanstack/virtual-core@3.10.7": version "3.10.7" @@ -5272,6 +5277,11 @@ resolved "https://registry.yarnpkg.com/@types/stylis/-/stylis-4.2.0.tgz#199a3f473f0c3a6f6e4e1b17cdbc967f274bdc6b" integrity sha512-n4sx2bqL0mW1tvDf/loQ+aMX7GQD3lc3fkCMC55VFNDu/vBOabO+LTIeXKM14xK0ppk5TUGcWRjiSpIlUpghKw== +"@types/swagger-schema-official@^2.0.25": + version "2.0.25" + resolved "https://registry.yarnpkg.com/@types/swagger-schema-official/-/swagger-schema-official-2.0.25.tgz#c8073914004d0a9c5412aeaf458d96e34c504840" + integrity sha512-T92Xav+Gf/Ik1uPW581nA+JftmjWPgskw/WBf4TJzxRG/SJ+DfNnNE+WuZ4mrXuzflQMqMkm1LSYjzYW7MB1Cg== + "@types/trusted-types@^2.0.2": version "2.0.7" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" @@ -7123,6 +7133,11 @@ call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bin get-intrinsic "^1.2.4" set-function-length "^1.2.1" +call-me-maybe@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" + integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -7762,6 +7777,16 @@ cosmiconfig@^8.3.5: parse-json "^5.2.0" path-type "^4.0.0" +cosmiconfig@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d" + integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== + dependencies: + env-paths "^2.2.1" + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + crc-32@^1.2.0: version "1.2.2" resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" @@ -8745,6 +8770,11 @@ entities@^4.2.0, entities@^4.4.0: resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== +env-paths@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -8880,6 +8910,11 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es6-promise@^3.2.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" + integrity sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg== + esbuild@^0.19.2, esbuild@~0.19.10: version "0.19.12" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.12.tgz#dc82ee5dc79e82f5a5c3b4323a2a641827db3e04" @@ -9666,7 +9701,7 @@ fast-redact@^3.0.0: resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== -fast-safe-stringify@^2.0.6, fast-safe-stringify@^2.1.1: +fast-safe-stringify@^2.0.6, fast-safe-stringify@^2.0.7, fast-safe-stringify@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== @@ -10750,6 +10785,11 @@ http-shutdown@^1.2.2: resolved "https://registry.yarnpkg.com/http-shutdown/-/http-shutdown-1.2.2.tgz#41bc78fc767637c4c95179bc492f312c0ae64c5f" integrity sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw== +http2-client@^1.2.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/http2-client/-/http2-client-1.3.5.tgz#20c9dc909e3cc98284dd20af2432c524086df181" + integrity sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA== + http2-wrapper@^2.1.10: version "2.2.1" resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.1.tgz#310968153dcdedb160d8b72114363ef5fce1f64a" @@ -13208,6 +13248,13 @@ node-emoji@^2.1.0: emojilib "^2.4.0" skin-tone "^2.0.0" +node-fetch-h2@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz#c6188325f9bd3d834020bf0f2d6dc17ced2241ac" + integrity sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg== + dependencies: + http2-client "^1.2.5" + node-fetch-native@^1.6.1, node-fetch-native@^1.6.2, node-fetch-native@^1.6.3: version "1.6.4" resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.4.tgz#679fc8fd8111266d47d7e72c379f1bed9acff06e" @@ -13230,6 +13277,13 @@ node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.0.tgz#3fee9c1731df4581a3f9ead74664369ff00d26dd" integrity sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og== +node-readfiles@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/node-readfiles/-/node-readfiles-0.2.0.tgz#dbbd4af12134e2e635c245ef93ffcf6f60673a5d" + integrity sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA== + dependencies: + es6-promise "^3.2.1" + node-releases@^2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" @@ -13337,6 +13391,52 @@ number-to-bn@1.7.0: bn.js "4.11.6" strip-hex-prefix "1.0.0" +oas-kit-common@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/oas-kit-common/-/oas-kit-common-1.0.8.tgz#6d8cacf6e9097967a4c7ea8bcbcbd77018e1f535" + integrity sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ== + dependencies: + fast-safe-stringify "^2.0.7" + +oas-linter@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/oas-linter/-/oas-linter-3.2.2.tgz#ab6a33736313490659035ca6802dc4b35d48aa1e" + integrity sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ== + dependencies: + "@exodus/schemasafe" "^1.0.0-rc.2" + should "^13.2.1" + yaml "^1.10.0" + +oas-resolver@^2.5.6: + version "2.5.6" + resolved "https://registry.yarnpkg.com/oas-resolver/-/oas-resolver-2.5.6.tgz#10430569cb7daca56115c915e611ebc5515c561b" + integrity sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ== + dependencies: + node-fetch-h2 "^2.3.0" + oas-kit-common "^1.0.8" + reftools "^1.1.9" + yaml "^1.10.0" + yargs "^17.0.1" + +oas-schema-walker@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz#74c3cd47b70ff8e0b19adada14455b5d3ac38a22" + integrity sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ== + +oas-validator@^5.0.8: + version "5.0.8" + resolved "https://registry.yarnpkg.com/oas-validator/-/oas-validator-5.0.8.tgz#387e90df7cafa2d3ffc83b5fb976052b87e73c28" + integrity sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw== + dependencies: + call-me-maybe "^1.0.1" + oas-kit-common "^1.0.8" + oas-linter "^3.2.2" + oas-resolver "^2.5.6" + oas-schema-walker "^1.1.5" + reftools "^1.1.9" + should "^13.2.1" + yaml "^1.10.0" + obj-multiplex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/obj-multiplex/-/obj-multiplex-1.0.0.tgz#2f2ae6bfd4ae11befe742ea9ea5b36636eabffc1" @@ -14387,7 +14487,7 @@ prettier@3.2.5: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== -prettier@3.3.3: +prettier@3.3.3, prettier@~3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== @@ -15059,6 +15159,11 @@ reflect.getprototypeof@^1.0.4: globalthis "^1.0.3" which-builtin-type "^1.1.3" +reftools@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/reftools/-/reftools-1.1.9.tgz#e16e19f662ccd4648605312c06d34e5da3a2b77e" + integrity sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w== + regenerate-unicode-properties@^10.1.0: version "10.1.1" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" @@ -15884,6 +15989,50 @@ shiki@^0.14.7: vscode-oniguruma "^1.7.0" vscode-textmate "^8.0.0" +should-equal@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3" + integrity sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA== + dependencies: + should-type "^1.4.0" + +should-format@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/should-format/-/should-format-3.0.3.tgz#9bfc8f74fa39205c53d38c34d717303e277124f1" + integrity sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q== + dependencies: + should-type "^1.3.0" + should-type-adaptors "^1.0.1" + +should-type-adaptors@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz#401e7f33b5533033944d5cd8bf2b65027792e27a" + integrity sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA== + dependencies: + should-type "^1.3.0" + should-util "^1.0.0" + +should-type@^1.3.0, should-type@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/should-type/-/should-type-1.4.0.tgz#0756d8ce846dfd09843a6947719dfa0d4cff5cf3" + integrity sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ== + +should-util@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/should-util/-/should-util-1.0.1.tgz#fb0d71338f532a3a149213639e2d32cbea8bcb28" + integrity sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g== + +should@^13.2.1: + version "13.2.3" + resolved "https://registry.yarnpkg.com/should/-/should-13.2.3.tgz#96d8e5acf3e97b49d89b51feaa5ae8d07ef58f10" + integrity sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ== + dependencies: + should-equal "^2.0.0" + should-format "^3.0.3" + should-type "^1.4.0" + should-type-adaptors "^1.0.1" + should-util "^1.0.0" + side-channel@^1.0.4, side-channel@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" @@ -16532,6 +16681,46 @@ svgo@^2.7.0, svgo@^2.8.0: picocolors "^1.0.0" stable "^0.1.8" +swagger-schema-official@2.0.0-bab6bed: + version "2.0.0-bab6bed" + resolved "https://registry.yarnpkg.com/swagger-schema-official/-/swagger-schema-official-2.0.0-bab6bed.tgz#70070468d6d2977ca5237b2e519ca7d06a2ea3fd" + integrity sha512-rCC0NWGKr/IJhtRuPq/t37qvZHI/mH4I4sxflVM+qgVe5Z2uOCivzWaVbuioJaB61kvm5UvB7b49E+oBY0M8jA== + +swagger-typescript-api@^13.0.23: + version "13.0.23" + resolved "https://registry.yarnpkg.com/swagger-typescript-api/-/swagger-typescript-api-13.0.23.tgz#411d421a64877c5f168260329fefda6d7bf4629f" + integrity sha512-HhoIepxlFEU7Ol42Gh8/tvwhSxdkHcweX2tRkNhbZYBiEA+rK3C6N85MnwoeQR5XbidE3Kz8mLOqIerVGgR9uw== + dependencies: + "@types/swagger-schema-official" "^2.0.25" + consola "^3.2.3" + cosmiconfig "^9.0.0" + didyoumean "^1.2.2" + eta "^2.2.0" + js-yaml "^4.1.0" + lodash "^4.17.21" + nanoid "^3.3.7" + prettier "~3.3.3" + swagger-schema-official "2.0.0-bab6bed" + swagger2openapi "^7.0.8" + typescript "~5.5.4" + +swagger2openapi@^7.0.8: + version "7.0.8" + resolved "https://registry.yarnpkg.com/swagger2openapi/-/swagger2openapi-7.0.8.tgz#12c88d5de776cb1cbba758994930f40ad0afac59" + integrity sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g== + dependencies: + call-me-maybe "^1.0.1" + node-fetch "^2.6.1" + node-fetch-h2 "^2.3.0" + node-readfiles "^0.2.0" + oas-kit-common "^1.0.8" + oas-resolver "^2.5.6" + oas-schema-walker "^1.1.5" + oas-validator "^5.0.8" + reftools "^1.1.9" + yaml "^1.10.0" + yargs "^17.0.1" + system-architecture@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/system-architecture/-/system-architecture-0.1.0.tgz#71012b3ac141427d97c67c56bc7921af6bff122d" @@ -17149,7 +17338,7 @@ typedoc@^0.25.7: minimatch "^9.0.3" shiki "^0.14.7" -typescript@^5.0.2, typescript@^5.3.3, typescript@^5.4.4, typescript@^5.4.5, typescript@^5.5.4, typescript@~5.2.2: +typescript@^5.0.2, typescript@^5.3.3, typescript@^5.4.4, typescript@^5.4.5, typescript@^5.5.4, typescript@~5.2.2, typescript@~5.5.4: version "5.5.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== @@ -18225,7 +18414,7 @@ yargs@^15.1.0, yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^17.5.1, yargs@^17.7.1: +yargs@^17.0.1, yargs@^17.5.1, yargs@^17.7.1: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==