From bd1936c4188ca842d2b2b092cde314aae762b453 Mon Sep 17 00:00:00 2001 From: yakuramori <62520712+yury-dubinin@users.noreply.github.com> Date: Tue, 10 Sep 2024 19:45:06 +0200 Subject: [PATCH] Publish Stage (#3831) * Mattupham/fe 1067 portfolio v3 update 0 change values to be green and up (#3823) * add threshold updates * Clean up logs * [Limit Orders]: SQS Active Order Query (#3828) * fix: increased cache time and refetch interval for active orders * fix: even longer cache * fix: WIP batch query implementation * fix: longer delay between batches * fix: batch size/timing * fix: vercel max duration * fix: wired in sqs query for active orders * fix: build * fix: filled orders styling * fix: remove claimable orders test data * fix: further reduced queries * feat: moved orders query to passthrough * fix: moved active orders to local router * fix: altered orders cache to be more responsive * chore: post typing fixes for active orders sqs query * fix: reverted unnecessary changes * feat: removed pool restriction on orderbooks * Clean up formatter (#3829) * Clean up formatter * Remove log * update no price data * add pr notification yaml (#3830) Co-authored-by: Michael Millington <> * fix lint issue (#3832) * Handle PricePretty and Lint issue * add search from query param for earn (#3836) * Update search from query param * Do not log subsequent chart interaction events / Handle last event tracking (#3834) * Handle last event tracking * Clean up * Clean up types * Update event properties * Add types for event options * Fix lint * Update MATIC -> POL (#3835) * Update MATIC -> POL * Update tests * feat: feature flag for sqs active orders (#3837) * [Limit Orders]: Fix date display for order history (#3833) * fix: date display for order history * fix: undid feature flag changes * fix: typing issue * [Limit Orders]: Price to Tick Crash Handler (#3838) * fix: price to tick error handling * feat: added swap source to swap amplitude events --------- Co-authored-by: Matt Upham <30577966+mattupham@users.noreply.github.com> * Update IBC overrides to use POL (#3839) --------- Co-authored-by: Matt Upham <30577966+mattupham@users.noreply.github.com> Co-authored-by: Connor Barr Co-authored-by: Max Millington --- .github/workflows/pr-notification.yml | 20 ++ .../bridge/src/__tests__/mock-asset-lists.ts | 6 +- packages/bridge/src/squid/__tests__/mocks.ts | 2 +- .../__tests__/squid-bridge-provider.spec.ts | 2 +- .../src/queries/__tests__/mock-asset-lists.ts | 8 +- .../complex/orderbooks/active-orders.ts | 47 +++- .../complex/orderbooks/historical-orders.ts | 11 +- .../src/queries/complex/orderbooks/pools.ts | 18 +- .../queries/complex/orderbooks/tick-state.ts | 4 +- .../server/src/queries/osmosis/orderbooks.ts | 2 +- .../server/src/queries/sidecar/orderbooks.ts | 40 ++++ packages/stores/src/tests/mock-data.ts | 8 +- .../src/__tests_e2e__/mock-asset-lists.ts | 8 +- packages/trpc/src/orderbook-router.ts | 49 ++++- packages/web/components/assets/price.tsx | 12 +- .../complex/orders-history/index.tsx | 22 +- .../complex/orders-history/order-modal.tsx | 11 +- .../complex/portfolio/allocation.tsx | 5 +- .../complex/portfolio/historical-chart.tsx | 11 +- .../earn/filters/filter-context.tsx | 17 +- packages/web/components/swap-tool/alt.tsx | 1 + .../recent-activity-transaction-row.tsx | 9 +- .../transaction-details-content.tsx | 6 +- .../transactions/transaction-row.tsx | 9 +- .../transactions/transaction-utils.tsx | 26 --- packages/web/config/analytics-events.ts | 16 ++ packages/web/config/ibc-overrides.ts | 2 +- packages/web/config/mock-asset-lists.ts | 6 +- .../web/hooks/limit-orders/use-orderbook.ts | 203 +++++++++++++++--- .../web/hooks/limit-orders/use-place-limit.ts | 34 +-- packages/web/hooks/use-amplitude-analytics.ts | 26 ++- packages/web/hooks/use-feature-flags.ts | 5 +- packages/web/localizations/de.json | 1 - packages/web/localizations/en.json | 1 - packages/web/localizations/es.json | 1 - packages/web/localizations/fa.json | 1 - packages/web/localizations/fr.json | 1 - packages/web/localizations/gu.json | 1 - packages/web/localizations/hi.json | 1 - packages/web/localizations/ja.json | 1 - packages/web/localizations/ko.json | 1 - packages/web/localizations/pl.json | 1 - packages/web/localizations/pt-br.json | 1 - packages/web/localizations/ro.json | 1 - packages/web/localizations/ru.json | 1 - packages/web/localizations/tr.json | 1 - packages/web/localizations/zh-cn.json | 1 - packages/web/localizations/zh-hk.json | 1 - packages/web/localizations/zh-tw.json | 1 - packages/web/pages/earn/index.tsx | 6 +- packages/web/server/api/local-router.ts | 2 + packages/web/stores/index.tsx | 3 +- 52 files changed, 493 insertions(+), 181 deletions(-) create mode 100644 .github/workflows/pr-notification.yml diff --git a/.github/workflows/pr-notification.yml b/.github/workflows/pr-notification.yml new file mode 100644 index 0000000000..0f2defc7b3 --- /dev/null +++ b/.github/workflows/pr-notification.yml @@ -0,0 +1,20 @@ +name: PR Notification +on: + pull_request: + types: [opened, reopened] + branches: + - master +jobs: + slack-notification: + runs-on: ubuntu-latest + steps: + - name: Slack Notification + uses: 8398a7/action-slack@v3 + with: + status: ${{ job.status }} + text: New PR opened to master branch + author_name: GitHub Action + fields: repo,message,commit,author,action,eventName,ref,workflow + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_ANNOUNCEMENT_WEBHOOK_URL }} diff --git a/packages/bridge/src/__tests__/mock-asset-lists.ts b/packages/bridge/src/__tests__/mock-asset-lists.ts index 3ed9bcabd9..8a49a8f243 100644 --- a/packages/bridge/src/__tests__/mock-asset-lists.ts +++ b/packages/bridge/src/__tests__/mock-asset-lists.ts @@ -1445,7 +1445,7 @@ export const MockAssetLists: AssetList[] = [ sourceDenom: "wmatic-wei", coinMinimalDenom: "ibc/AB589511ED0DD5FA56171A39978AFBF1371DB986EC1C3526CE138A16377E39BB", - symbol: "MATIC", + symbol: "POL", decimals: 18, logoURIs: { png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/matic-purple.png", @@ -1506,7 +1506,7 @@ export const MockAssetLists: AssetList[] = [ chainType: "evm", chainId: 137, address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - symbol: "MATIC", + symbol: "POL", decimals: 18, logoURIs: { png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/matic-purple.png", @@ -1514,7 +1514,7 @@ export const MockAssetLists: AssetList[] = [ }, }, ], - variantGroupKey: "MATIC", + variantGroupKey: "POL", name: "Polygon", isAlloyed: false, verified: true, diff --git a/packages/bridge/src/squid/__tests__/mocks.ts b/packages/bridge/src/squid/__tests__/mocks.ts index 3e1aed09a8..cfc1669d99 100644 --- a/packages/bridge/src/squid/__tests__/mocks.ts +++ b/packages/bridge/src/squid/__tests__/mocks.ts @@ -1977,7 +1977,7 @@ export const MockChains = [ chainId: 137, nativeCurrency: { name: "Polygon", - symbol: "MATIC", + symbol: "POL", decimals: 18, icon: "https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/polygon.svg", }, diff --git a/packages/bridge/src/squid/__tests__/squid-bridge-provider.spec.ts b/packages/bridge/src/squid/__tests__/squid-bridge-provider.spec.ts index 263077e9e2..72ca5fce07 100644 --- a/packages/bridge/src/squid/__tests__/squid-bridge-provider.spec.ts +++ b/packages/bridge/src/squid/__tests__/squid-bridge-provider.spec.ts @@ -527,7 +527,7 @@ describe("SquidBridgeProvider", () => { chainId: 137, nativeCurrency: { name: "Polygon", - symbol: "MATIC", + symbol: "POL", decimals: 18, icon: "https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/polygon.svg", }, diff --git a/packages/server/src/queries/__tests__/mock-asset-lists.ts b/packages/server/src/queries/__tests__/mock-asset-lists.ts index f97db77c1b..b5aa0c3f52 100644 --- a/packages/server/src/queries/__tests__/mock-asset-lists.ts +++ b/packages/server/src/queries/__tests__/mock-asset-lists.ts @@ -1447,7 +1447,7 @@ export const AssetLists: AssetList[] = [ sourceDenom: "wmatic-wei", coinMinimalDenom: "ibc/AB589511ED0DD5FA56171A39978AFBF1371DB986EC1C3526CE138A16377E39BB", - symbol: "MATIC", + symbol: "POL", decimals: 18, logoURIs: { png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/matic-purple.png", @@ -1508,7 +1508,7 @@ export const AssetLists: AssetList[] = [ chainType: "evm", chainId: 137, address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - symbol: "MATIC", + symbol: "POL", decimals: 18, logoURIs: { png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/matic-purple.png", @@ -1516,14 +1516,14 @@ export const AssetLists: AssetList[] = [ }, }, ], - variantGroupKey: "MATIC", + variantGroupKey: "POL", name: "Polygon", isAlloyed: false, verified: true, unstable: false, disabled: false, preview: false, - relative_image_url: "/tokens/generated/matic.png", + relative_image_url: "/tokens/generated/pol.png", }, { chainName: "axelar", diff --git a/packages/server/src/queries/complex/orderbooks/active-orders.ts b/packages/server/src/queries/complex/orderbooks/active-orders.ts index ad0223a962..6b1fa9d618 100644 --- a/packages/server/src/queries/complex/orderbooks/active-orders.ts +++ b/packages/server/src/queries/complex/orderbooks/active-orders.ts @@ -1,6 +1,6 @@ import { Dec, Int } from "@keplr-wallet/unit"; import { tickToPrice } from "@osmosis-labs/math"; -import { Chain } from "@osmosis-labs/types"; +import { AssetList, Chain } from "@osmosis-labs/types"; import { getAssetFromAssetList } from "@osmosis-labs/utils"; import cachified, { CacheEntry } from "cachified"; import dayjs from "dayjs"; @@ -8,6 +8,7 @@ import { LRUCache } from "lru-cache"; import { DEFAULT_LRU_OPTIONS } from "../../../utils/cache"; import { LimitOrder, queryOrderbookActiveOrders } from "../../osmosis"; +import { queryActiveOrdersSQS } from "../../sidecar/orderbooks"; import { getOrderbookTickState, getOrderbookTickUnrealizedCancels, @@ -16,6 +17,46 @@ import type { MappedLimitOrder, OrderStatus } from "./types"; const activeOrdersCache = new LRUCache(DEFAULT_LRU_OPTIONS); +export function getOrderbookActiveOrdersSQS({ + userOsmoAddress, + assetList, +}: { + userOsmoAddress: string; + assetList: AssetList[]; +}) { + return cachified({ + cache: activeOrdersCache, + key: `orderbookActiveOrders-sqs-${userOsmoAddress}`, + ttl: 5000, // 5 seconds + getFreshValue: () => + queryActiveOrdersSQS({ + userOsmoAddress, + }).then(async ({ orders }) => { + const mappedOrders: MappedLimitOrder[] = orders.map((o) => { + return { + ...o, + price: new Dec(o.price), + quantity: parseInt(o.quantity), + placed_quantity: parseInt(o.placed_quantity), + percentClaimed: new Dec(o.percentClaimed), + totalFilled: parseInt(o.totalFilled), + percentFilled: new Dec(o.percentFilled), + quoteAsset: getAssetFromAssetList({ + coinMinimalDenom: o.quote_asset.symbol, + assetLists: assetList, + }), + baseAsset: getAssetFromAssetList({ + coinMinimalDenom: o.base_asset.symbol, + assetLists: assetList, + }), + output: new Dec(o.output), + }; + }); + return mappedOrders; + }), + }); +} + export function getOrderbookActiveOrders({ orderbookAddress, userOsmoAddress, @@ -32,7 +73,7 @@ export function getOrderbookActiveOrders({ return cachified({ cache: activeOrdersCache, key: `orderbookActiveOrders-${orderbookAddress}-${userOsmoAddress}`, - ttl: 2000, // 2 seconds + ttl: 10000, // 10 seconds getFreshValue: () => queryOrderbookActiveOrders({ orderbookAddress, @@ -152,7 +193,7 @@ async function getTickInfoAndTransformOrders( output, quoteAsset, baseAsset, - placed_at: dayjs(parseInt(o.placed_at) / 1_000).unix(), + placed_at: dayjs(o.placed_at / 1000).unix(), }; }); } diff --git a/packages/server/src/queries/complex/orderbooks/historical-orders.ts b/packages/server/src/queries/complex/orderbooks/historical-orders.ts index a59086b236..c66b66bce9 100644 --- a/packages/server/src/queries/complex/orderbooks/historical-orders.ts +++ b/packages/server/src/queries/complex/orderbooks/historical-orders.ts @@ -139,12 +139,11 @@ async function mapHistoricalToMapped( order_direction: o.order_direction, order_id: parseInt(o.order_id), owner: userAddress, - placed_at: - dayjs( - o.place_timestamp && o.place_timestamp.length > 0 - ? o.place_timestamp - : 0 - ).unix() * 1000, + placed_at: dayjs( + o.place_timestamp && o.place_timestamp.length > 0 + ? o.place_timestamp + : 0 + ).unix(), placed_quantity: parseInt(o.quantity), placedQuantityMin, quantityMin, diff --git a/packages/server/src/queries/complex/orderbooks/pools.ts b/packages/server/src/queries/complex/orderbooks/pools.ts index bbbd36a388..3119270d51 100644 --- a/packages/server/src/queries/complex/orderbooks/pools.ts +++ b/packages/server/src/queries/complex/orderbooks/pools.ts @@ -22,16 +22,14 @@ export function getOrderbookPools() { ttl: 1000 * 60 * 60, // 1 hour getFreshValue: () => queryCanonicalOrderbooks().then(async (data) => { - return data - .filter((o) => o.pool_id < 2065) - .map((orderbook) => { - return { - baseDenom: orderbook.base, - quoteDenom: orderbook.quote, - contractAddress: orderbook.contract_address, - poolId: orderbook.pool_id.toString(), - }; - }) as Orderbook[]; + return data.map((orderbook) => { + return { + baseDenom: orderbook.base, + quoteDenom: orderbook.quote, + contractAddress: orderbook.contract_address, + poolId: orderbook.pool_id.toString(), + }; + }) as Orderbook[]; }), }); } diff --git a/packages/server/src/queries/complex/orderbooks/tick-state.ts b/packages/server/src/queries/complex/orderbooks/tick-state.ts index 96116fe415..d1994235ea 100644 --- a/packages/server/src/queries/complex/orderbooks/tick-state.ts +++ b/packages/server/src/queries/complex/orderbooks/tick-state.ts @@ -24,7 +24,7 @@ export function getOrderbookTickState({ key: `orderbookTickInfo-${orderbookAddress}-${tickIds .sort((a, b) => a - b) .join(",")}`, - ttl: 1000 * 6, // 6 seconds + ttl: 1000 * 10, // 6 seconds getFreshValue: () => queryOrderbookTicks({ orderbookAddress, chainList, tickIds }).then( ({ data }) => data.ticks @@ -46,7 +46,7 @@ export function getOrderbookTickUnrealizedCancels({ key: `orderbookTickUnrealizedCancels-${orderbookAddress}-${tickIds .sort((a, b) => a - b) .join(",")}`, - ttl: 1000 * 6, // 6 seconds + ttl: 1000 * 10, // 10 seconds getFreshValue: () => queryOrderbookTickUnrealizedCancelsById({ orderbookAddress, diff --git a/packages/server/src/queries/osmosis/orderbooks.ts b/packages/server/src/queries/osmosis/orderbooks.ts index 7d4b6752ab..9914f1e690 100644 --- a/packages/server/src/queries/osmosis/orderbooks.ts +++ b/packages/server/src/queries/osmosis/orderbooks.ts @@ -29,7 +29,7 @@ export interface LimitOrder { etas: string; claim_bounty?: string; placed_quantity: string; - placed_at: string; + placed_at: number; } interface OrderbookActiveOrdersResponse { diff --git a/packages/server/src/queries/sidecar/orderbooks.ts b/packages/server/src/queries/sidecar/orderbooks.ts index e9fa8af8ac..bae6c68c56 100644 --- a/packages/server/src/queries/sidecar/orderbooks.ts +++ b/packages/server/src/queries/sidecar/orderbooks.ts @@ -9,7 +9,47 @@ export type CanonicalOrderbooksResponse = { contract_address: string; }[]; +export interface SQSActiveOrder { + tick_id: number; + order_id: number; + order_direction: "bid" | "ask"; + owner: string; + quantity: string; + etas: string; + placed_quantity: string; + placed_at: number; + price: string; + percentClaimed: string; + totalFilled: string; + percentFilled: string; + orderbookAddress: string; + status: "open" | "partiallyFilled"; + output: string; + quote_asset: { + symbol: string; + }; + base_asset: { + symbol: string; + }; +} + +export type ActiveOrdersResponse = { + orders: SQSActiveOrder[]; +}; + export async function queryCanonicalOrderbooks() { const url = new URL("/pools/canonical-orderbooks", SIDECAR_BASE_URL); return await apiClient(url.toString()); } + +export async function queryActiveOrdersSQS({ + userOsmoAddress, +}: { + userOsmoAddress: string; +}) { + const url = new URL( + `/passthrough/active-orders?userOsmoAddress=${userOsmoAddress}`, + SIDECAR_BASE_URL + ); + return await apiClient(url.toString()); +} diff --git a/packages/stores/src/tests/mock-data.ts b/packages/stores/src/tests/mock-data.ts index 88acb835f4..676db0a6f7 100644 --- a/packages/stores/src/tests/mock-data.ts +++ b/packages/stores/src/tests/mock-data.ts @@ -2401,7 +2401,7 @@ export const MockAssetList: AssetList[] = [ sourceDenom: "wmatic-wei", coinMinimalDenom: "ibc/AB589511ED0DD5FA56171A39978AFBF1371DB986EC1C3526CE138A16377E39BB", - symbol: "MATIC", + symbol: "POL", decimals: 18, logoURIs: { png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/matic-purple.png", @@ -2462,7 +2462,7 @@ export const MockAssetList: AssetList[] = [ chainType: "evm", chainId: 137, address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - symbol: "MATIC", + symbol: "POL", decimals: 18, logoURIs: { png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/matic-purple.png", @@ -2470,14 +2470,14 @@ export const MockAssetList: AssetList[] = [ }, }, ], - variantGroupKey: "MATIC", + variantGroupKey: "POL", name: "Polygon", isAlloyed: false, verified: true, unstable: false, disabled: false, preview: false, - relative_image_url: "/tokens/generated/matic.png", + relative_image_url: "/tokens/generated/pol.png", }, { chainName: "axelar", diff --git a/packages/trpc/src/__tests_e2e__/mock-asset-lists.ts b/packages/trpc/src/__tests_e2e__/mock-asset-lists.ts index f97db77c1b..b5aa0c3f52 100644 --- a/packages/trpc/src/__tests_e2e__/mock-asset-lists.ts +++ b/packages/trpc/src/__tests_e2e__/mock-asset-lists.ts @@ -1447,7 +1447,7 @@ export const AssetLists: AssetList[] = [ sourceDenom: "wmatic-wei", coinMinimalDenom: "ibc/AB589511ED0DD5FA56171A39978AFBF1371DB986EC1C3526CE138A16377E39BB", - symbol: "MATIC", + symbol: "POL", decimals: 18, logoURIs: { png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/matic-purple.png", @@ -1508,7 +1508,7 @@ export const AssetLists: AssetList[] = [ chainType: "evm", chainId: 137, address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - symbol: "MATIC", + symbol: "POL", decimals: 18, logoURIs: { png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/matic-purple.png", @@ -1516,14 +1516,14 @@ export const AssetLists: AssetList[] = [ }, }, ], - variantGroupKey: "MATIC", + variantGroupKey: "POL", name: "Polygon", isAlloyed: false, verified: true, unstable: false, disabled: false, preview: false, - relative_image_url: "/tokens/generated/matic.png", + relative_image_url: "/tokens/generated/pol.png", }, { chainName: "axelar", diff --git a/packages/trpc/src/orderbook-router.ts b/packages/trpc/src/orderbook-router.ts index b113d94886..52c9efffe9 100644 --- a/packages/trpc/src/orderbook-router.ts +++ b/packages/trpc/src/orderbook-router.ts @@ -3,6 +3,7 @@ import { tickToPrice } from "@osmosis-labs/math"; import { CursorPaginationSchema, getOrderbookActiveOrders, + getOrderbookActiveOrdersSQS, getOrderbookHistoricalOrders, getOrderbookMakerFee, getOrderbookPools, @@ -12,12 +13,17 @@ import { OrderStatus, } from "@osmosis-labs/server"; import { getAssetFromAssetList } from "@osmosis-labs/utils"; +import { z } from "zod"; import { createTRPCRouter, publicProcedure } from "./api"; import { OsmoAddressSchema, UserOsmoAddressSchema } from "./parameter-types"; const GetInfiniteLimitOrdersInputSchema = CursorPaginationSchema.merge( UserOsmoAddressSchema.required() +).merge( + z.object({ + filter: z.enum(["open", "filled", "historical"]).optional(), + }) ); const orderStatusOrder: Record = { @@ -106,7 +112,48 @@ export const orderbookRouter = createTRPCRouter({ return allOrders.sort(defaultSortOrders); }, cacheKey: `all-active-orders-${input.userOsmoAddress}`, - ttl: 2000, + ttl: 15000, + cursor: input.cursor, + limit: input.limit, + }); + }), + getAllOrdersSQS: publicProcedure + .input(GetInfiniteLimitOrdersInputSchema) + .query(async ({ input, ctx }) => { + return maybeCachePaginatedItems({ + getFreshItems: async () => { + const { userOsmoAddress, filter } = input; + + const shouldFetchActive = + !filter || filter === "open" || filter === "filled"; + const shouldFetchHistorical = !filter || filter === "historical"; + const promises: Promise[] = []; + if (shouldFetchActive) { + promises.push( + getOrderbookActiveOrdersSQS({ + userOsmoAddress, + assetList: ctx.assetLists, + }) + ); + } + if (shouldFetchHistorical) { + promises.push( + getOrderbookHistoricalOrders({ + userOsmoAddress, + assetLists: ctx.assetLists, + chainList: ctx.chainList, + }) + ); + } + const orders = await Promise.all(promises); + const allOrders = orders.flat().sort(defaultSortOrders); + if (filter === "filled") { + return allOrders.filter((o) => o.status === "filled"); + } + return allOrders; + }, + cacheKey: `all-active-orders-sqs-${input.userOsmoAddress}`, + ttl: 10000, cursor: input.cursor, limit: input.limit, }); diff --git a/packages/web/components/assets/price.tsx b/packages/web/components/assets/price.tsx index 762ce67be5..4158141ceb 100644 --- a/packages/web/components/assets/price.tsx +++ b/packages/web/components/assets/price.tsx @@ -12,8 +12,8 @@ import { api } from "~/utils/trpc"; import { Sparkline } from "../chart/sparkline"; import { CustomClasses } from "../types"; -// 0.01% -const THRESHOLD = 0.0001; +// 0.1% +const THRESHOLD = 0.001; /** Colored price change text with up/down arrow. */ export const PriceChange: FunctionComponent< @@ -23,8 +23,8 @@ export const PriceChange: FunctionComponent< value?: PricePretty; } & CustomClasses > = ({ priceChange, overrideTextClasses = "body1", className, value }) => { - const isBullish = priceChange.toDec().gt(new Dec(THRESHOLD)); - const isBearish = priceChange.toDec().lt(new Dec(-THRESHOLD)); + const isBullish = priceChange.toDec().gte(new Dec(THRESHOLD)); + const isBearish = priceChange.toDec().lte(new Dec(-THRESHOLD)); const isFlat = !isBullish && !isBearish; // remove negative symbol since we're using arrows @@ -34,7 +34,7 @@ export const PriceChange: FunctionComponent< } const priceChangeDisplay = priceChange - .maxDecimals(2) + .maxDecimals(1) .inequalitySymbol(false) .toString(); @@ -71,7 +71,7 @@ export const PriceChange: FunctionComponent< > {value !== undefined ? value.toString() + " " : null} - {isFlat ? "0.00%" : formattedPriceChangeDisplay} + {isFlat ? "0.0%" : formattedPriceChangeDisplay} ); diff --git a/packages/web/components/complex/orders-history/index.tsx b/packages/web/components/complex/orders-history/index.tsx index 02a53e6c41..f699df1871 100644 --- a/packages/web/components/complex/orders-history/index.tsx +++ b/packages/web/components/complex/orders-history/index.tsx @@ -84,9 +84,8 @@ export const OrderHistory = observer(() => { } = useOrderbookAllActiveOrders({ userAddress: wallet?.address ?? "", pageSize: 20, - refetchInterval: 15000, + refetchInterval: featureFlags.sqsActiveOrders ? 10000 : 30000, }); - const groupedOrders = useMemo(() => groupOrdersByStatus(orders), [orders]); const groups = useMemo( () => @@ -116,15 +115,16 @@ export const OrderHistory = observer(() => { scrollMargin: listRef.current?.offsetTop ?? 0, paddingStart: 45, }); + const filledOrdersInDisplay = useMemo(() => { + return orders.filter((o) => o.status === "filled"); + }, [orders]); - const filledOrders = orders.filter((o) => o.status === "filled"); - const filledOrdersCount = filledOrders.length; - - const { claimAllOrders } = useOrderbookClaimableOrders({ - userAddress: wallet?.address ?? "", - disabled: isLoading || orders.length === 0 || isRefetching, - orders: filledOrders, - }); + const { claimAllOrders, count: filledOrdersCount } = + useOrderbookClaimableOrders({ + userAddress: wallet?.address ?? "", + disabled: isLoading || filledOrdersInDisplay.length === 0 || isRefetching, + refetchInterval: featureFlags.sqsActiveOrders ? 10000 : 30000, + }); const claimOrders = useCallback(async () => { try { @@ -433,7 +433,7 @@ const TableOrderRow = memo( baseAsset?.rawAsset.logoURIs.png ?? ""; - const placedAt = dayjs(placed_at); + const placedAt = dayjs.unix(placed_at); const formattedTime = placedAt.format("h:mm A"); const formattedDate = placedAt.format("MMM D"); diff --git a/packages/web/components/complex/orders-history/order-modal.tsx b/packages/web/components/complex/orders-history/order-modal.tsx index d077ef616a..d6a19e9bc7 100644 --- a/packages/web/components/complex/orders-history/order-modal.tsx +++ b/packages/web/components/complex/orders-history/order-modal.tsx @@ -69,11 +69,14 @@ const OrderDetails = observer( : order.baseAsset; }, [order]); - const formattedMonth = dayjs(order?.placed_at).format("MMMM").slice(0, 3); + const formattedMonth = dayjs + .unix(order?.placed_at ?? 0) + .format("MMMM") + .slice(0, 3); - const formattedDateDayYearHourMinute = dayjs(order?.placed_at).format( - "DD, YYYY, HH:mm" - ); + const formattedDateDayYearHourMinute = dayjs + .unix(order?.placed_at ?? 0) + .format("DD, YYYY, HH:mm"); const formattedDate = `${formattedMonth} ${formattedDateDayYearHourMinute}`; diff --git a/packages/web/components/complex/portfolio/allocation.tsx b/packages/web/components/complex/portfolio/allocation.tsx index b9ee982292..c46714a1b9 100644 --- a/packages/web/components/complex/portfolio/allocation.tsx +++ b/packages/web/components/complex/portfolio/allocation.tsx @@ -6,7 +6,6 @@ import { FunctionComponent, useEffect, useState } from "react"; import { Icon } from "~/components/assets"; import { AllocationTabs } from "~/components/complex/portfolio/allocation-tabs"; import { AllocationOptions } from "~/components/complex/portfolio/types"; -import { displayFiatPrice } from "~/components/transactions/transaction-utils"; import { EventName } from "~/config"; import { Breakpoint, @@ -15,6 +14,7 @@ import { useTranslation, useWindowSize, } from "~/hooks"; +import { formatFiatPrice } from "~/utils/formatter"; const COLORS: Record = { all: [ @@ -133,6 +133,7 @@ export const Allocation: FunctionComponent<{ {selectedList.map(({ key, percentage, fiatValue }, index) => { const colorClass = COLORS[selectedOption][index % COLORS[selectedOption].length]; + return (
@@ -147,7 +148,7 @@ export const Allocation: FunctionComponent<{ {percentage.maxDecimals(0).toString()}
-
{displayFiatPrice(fiatValue, "", t)}
+
{formatFiatPrice(fiatValue)}
); })} diff --git a/packages/web/components/complex/portfolio/historical-chart.tsx b/packages/web/components/complex/portfolio/historical-chart.tsx index e393b71a9c..97182301ca 100644 --- a/packages/web/components/complex/portfolio/historical-chart.tsx +++ b/packages/web/components/complex/portfolio/historical-chart.tsx @@ -37,7 +37,7 @@ export const PortfolioHistoricalChart = ({ setIsChartMinimized, }: PortfolioHistoricalChartProps) => { const { t } = useTranslation(); - const { logEvent } = useAmplitudeAnalytics(); + const { logEvent, getLastEvent } = useAmplitudeAnalytics(); return (
@@ -54,7 +54,14 @@ export const PortfolioHistoricalChart = ({ onPointerHover={(value, time) => { setShowDate(true); setDataPoint({ value, time }); - logEvent([EventName.Portfolio.chartInteraction]); + + const lastEvent = getLastEvent(); + // Avoid logging subsequent chartInteraction events to prevent Amplitude overload + if ( + lastEvent?.eventName !== EventName.Portfolio.chartInteraction + ) { + logEvent([EventName.Portfolio.chartInteraction]); + } }} onPointerOut={resetDataPoint} /> diff --git a/packages/web/components/earn/filters/filter-context.tsx b/packages/web/components/earn/filters/filter-context.tsx index 48d490e985..5fcdc351af 100644 --- a/packages/web/components/earn/filters/filter-context.tsx +++ b/packages/web/components/earn/filters/filter-context.tsx @@ -1,4 +1,11 @@ -import { createContext, PropsWithChildren, useCallback, useState } from "react"; +import { useRouter } from "next/router"; +import { + createContext, + PropsWithChildren, + useCallback, + useEffect, + useState, +} from "react"; import { ListOption, @@ -47,6 +54,14 @@ export const FilterProvider = ({ defaultFilters, }: PropsWithChildren<{ defaultFilters: Filters }>) => { const [filters, setFilters] = useState(defaultFilters); + const router = useRouter(); + const { search } = router.query; + + useEffect(() => { + if (typeof search === "string" && search !== "") { + setFilters((prev) => ({ ...prev, search })); + } + }, [search]); const setFilter = useCallback( (key, value) => { diff --git a/packages/web/components/swap-tool/alt.tsx b/packages/web/components/swap-tool/alt.tsx index 1688b1dcfb..f3107e3e45 100644 --- a/packages/web/components/swap-tool/alt.tsx +++ b/packages/web/components/swap-tool/alt.tsx @@ -229,6 +229,7 @@ export const AltSwapTool: FunctionComponent = observer( feeValueUsd: Number(swapState.totalFee?.toString() ?? "0"), page, quoteTimeMilliseconds: swapState.quote?.timeMs, + swapSource: "swap" as "swap" | "market", }; logEvent([EventName.Swap.swapStarted, baseEvent]); setIsSendingTx(true); diff --git a/packages/web/components/transactions/recent-activity/recent-activity-transaction-row.tsx b/packages/web/components/transactions/recent-activity/recent-activity-transaction-row.tsx index 588131eb60..40da967148 100644 --- a/packages/web/components/transactions/recent-activity/recent-activity-transaction-row.tsx +++ b/packages/web/components/transactions/recent-activity/recent-activity-transaction-row.tsx @@ -2,9 +2,7 @@ import { FunctionComponent } from "react"; import { FallbackImg, Icon } from "~/components/assets"; import { TransactionRow } from "~/components/transactions/transaction-row"; -import { displayFiatPrice } from "~/components/transactions/transaction-utils"; -import { useTranslation } from "~/hooks"; - +import { formatFiatPrice } from "~/utils/formatter"; export type TransactionStatus = "pending" | "success" | "failed"; export const RecentActivityRow: FunctionComponent<{ @@ -26,13 +24,12 @@ export const SwapRow: FunctionComponent = ({ title, tokenConversion, }) => { - const { t } = useTranslation(); - const leftComponent = tokenConversion ? (

{title[status]}

- {displayFiatPrice(tokenConversion.tokenIn?.value, "", t)}{" "} + {tokenConversion.tokenIn?.value && + formatFiatPrice(tokenConversion.tokenIn?.value)}{" "} {tokenConversion.tokenIn.amount.denom}{" "} {" "} {tokenConversion.tokenOut.amount.denom} diff --git a/packages/web/components/transactions/transaction-details/transaction-details-content.tsx b/packages/web/components/transactions/transaction-details/transaction-details-content.tsx index 9b10058ba8..f0b189bc87 100644 --- a/packages/web/components/transactions/transaction-details/transaction-details-content.tsx +++ b/packages/web/components/transactions/transaction-details/transaction-details-content.tsx @@ -8,7 +8,6 @@ import { Icon } from "~/components/assets"; import { FallbackImg } from "~/components/assets"; import { CopyIconButton } from "~/components/buttons/copy-icon-button"; import { IconButton } from "~/components/buttons/icon-button"; -import { displayFiatPrice } from "~/components/transactions/transaction-utils"; import { Button } from "~/components/ui/button"; import { EventName } from "~/config"; import { @@ -18,6 +17,7 @@ import { } from "~/hooks"; import { theme } from "~/tailwind.config"; import { formatPretty } from "~/utils/formatter"; +import { formatFiatPrice } from "~/utils/formatter"; export const TransactionDetailsContent = ({ onRequestClose, @@ -142,7 +142,7 @@ export const TransactionDetailsContent = ({ {formatPretty(tokenIn.token, { maxDecimals: 6 }).split(" ")[0]}
- {displayFiatPrice(tokenIn?.usd, "", t)} + {formatFiatPrice(tokenIn?.usd)}
@@ -179,7 +179,7 @@ export const TransactionDetailsContent = ({ {formatPretty(tokenOut.token, { maxDecimals: 6 }).split(" ")[0]}
- {displayFiatPrice(tokenOut?.usd, "", t)} + {formatFiatPrice(tokenOut?.usd)}
diff --git a/packages/web/components/transactions/transaction-row.tsx b/packages/web/components/transactions/transaction-row.tsx index 0a64f5cdf2..d6ee4c8678 100644 --- a/packages/web/components/transactions/transaction-row.tsx +++ b/packages/web/components/transactions/transaction-row.tsx @@ -3,10 +3,8 @@ import classNames from "classnames"; import { FunctionComponent } from "react"; import { FallbackImg, Icon } from "~/components/assets"; -import { displayFiatPrice } from "~/components/transactions/transaction-utils"; -import { useTranslation } from "~/hooks"; import { theme } from "~/tailwind.config"; -import { formatPretty } from "~/utils/formatter"; +import { formatFiatPrice, formatPretty } from "~/utils/formatter"; import { Spinner } from "../loaders"; @@ -133,7 +131,6 @@ const TokenConversion: FunctionComponent< TransactionRow["tokenConversion"] > > = ({ status, tokenIn, tokenOut, effect }) => { - const { t } = useTranslation(); return (
@@ -150,7 +147,7 @@ const TokenConversion: FunctionComponent<
)}
- {displayFiatPrice(tokenIn?.value, "-", t)} + {tokenIn.value && `- ${formatFiatPrice(tokenIn.value)}`}
)}
- {displayFiatPrice(tokenOut?.value, "+", t)} + {tokenOut.value && `+ ${formatFiatPrice(tokenOut.value)}`}
diff --git a/packages/web/components/transactions/transaction-utils.tsx b/packages/web/components/transactions/transaction-utils.tsx index 929ab8a4c0..74cb5f64ac 100644 --- a/packages/web/components/transactions/transaction-utils.tsx +++ b/packages/web/components/transactions/transaction-utils.tsx @@ -1,5 +1,3 @@ -import { PricePretty } from "@keplr-wallet/unit"; -import { Dec } from "@keplr-wallet/unit"; import { FormattedTransaction } from "@osmosis-labs/server"; import dayjs from "dayjs"; import isToday from "dayjs/plugin/isToday"; @@ -7,8 +5,6 @@ import isYesterday from "dayjs/plugin/isYesterday"; import relativeTime from "dayjs/plugin/relativeTime"; import { useTranslation } from "hooks"; -import { MultiLanguageT } from "~/hooks"; - dayjs.extend(relativeTime); dayjs.extend(isToday); dayjs.extend(isYesterday); @@ -47,25 +43,3 @@ export const useFormatDate = () => { return formatDate; }; - -export const displayFiatPrice = ( - value: PricePretty | undefined, - prefix: "-" | "+" | "", - t: MultiLanguageT -): string => { - if (value === undefined) return t("transactions.noPriceData"); - - const decValue = value.toDec(); - const symbol = value.symbol; - - if (decValue.lt(new Dec(0.01))) { - return `${prefix} <${symbol}0.01`; - } - - // Convert displayValue to a fixed 2-decimal place string - const formattedDisplayValue = `${prefix} ${symbol}${Number( - decValue.toString() - ).toFixed(2)}`; - - return formattedDisplayValue; -}; diff --git a/packages/web/config/analytics-events.ts b/packages/web/config/analytics-events.ts index 5a9e00d04c..ba6b1f92a1 100644 --- a/packages/web/config/analytics-events.ts +++ b/packages/web/config/analytics-events.ts @@ -2,6 +2,8 @@ * Logged to Amplitude at https://analytics.amplitude.com/osmosis-zone/ */ +import { AllocationOptions } from "~/components/complex/portfolio/types"; + // Should be in sync with: https://docs.google.com/spreadsheets/d/18w8VwJmmRdb_E-XkE1UjkqhLxCyhqVVhWlzDgTtbRWo/edit?usp=sharing // For maintainability - all event logs should be in high level component @@ -70,6 +72,20 @@ export type EventProperties = { isRecommendedVariant: boolean; walletName: string; transferDirection: "deposit" | "withdraw"; + swapSource: "market" | "swap"; + coinDenom: string; + appName: string; + isFeatured: boolean; + isBanner: boolean; + position: number; + allocationType: AllocationOptions; + section: string; + tokenIn: string; + tokenOut: string; + option: string; + numberOfValidators: number; + validatorNames: string[]; + squadSize: number; }; export type UserProperties = { diff --git a/packages/web/config/ibc-overrides.ts b/packages/web/config/ibc-overrides.ts index 66aae53323..2789465a1e 100644 --- a/packages/web/config/ibc-overrides.ts +++ b/packages/web/config/ibc-overrides.ts @@ -59,7 +59,7 @@ const MainnetIBCAdditionalData: Partial< withdrawUrlOverride: "https://app.picasso.network/?from=OSMOSIS&to=POLKADOT", }, - MATIC: { + POL: { sourceChainNameOverride: "Polygon", }, SHIB: { diff --git a/packages/web/config/mock-asset-lists.ts b/packages/web/config/mock-asset-lists.ts index 341f28d909..d78bf70457 100644 --- a/packages/web/config/mock-asset-lists.ts +++ b/packages/web/config/mock-asset-lists.ts @@ -1445,7 +1445,7 @@ export const AssetLists: AssetList[] = [ sourceDenom: "wmatic-wei", coinMinimalDenom: "ibc/AB589511ED0DD5FA56171A39978AFBF1371DB986EC1C3526CE138A16377E39BB", - symbol: "MATIC", + symbol: "POL", decimals: 18, logoURIs: { png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/matic-purple.png", @@ -1506,7 +1506,7 @@ export const AssetLists: AssetList[] = [ chainType: "evm", chainId: 137, address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - symbol: "MATIC", + symbol: "POL", decimals: 18, logoURIs: { png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/matic-purple.png", @@ -1514,7 +1514,7 @@ export const AssetLists: AssetList[] = [ }, }, ], - variantGroupKey: "MATIC", + variantGroupKey: "POL", name: "Polygon", isAlloyed: false, verified: true, diff --git a/packages/web/hooks/limit-orders/use-orderbook.ts b/packages/web/hooks/limit-orders/use-orderbook.ts index 2cdfee8ade..7242882149 100644 --- a/packages/web/hooks/limit-orders/use-orderbook.ts +++ b/packages/web/hooks/limit-orders/use-orderbook.ts @@ -10,6 +10,7 @@ import { getAssetFromAssetList } from "@osmosis-labs/utils"; import { useCallback, useMemo } from "react"; import { AssetLists } from "~/config/generated/asset-lists"; +import { useFeatureFlags } from "~/hooks/use-feature-flags"; import { useSwapAsset } from "~/hooks/use-swap"; import { useStore } from "~/stores"; import { api } from "~/utils/trpc"; @@ -262,26 +263,63 @@ const useMakerFee = ({ orderbookAddress }: { orderbookAddress: string }) => { export type DisplayableLimitOrder = MappedLimitOrder; -export const useOrderbookAllActiveOrders = ({ +/** + * Queries for all active orders for a given user. + * Swaps between using SQS passthrough and a direct node query based on feature flag. + */ +const useOrdersQuery = ({ userAddress, pageSize = 10, - refetchInterval = 2000, + refetchInterval = 5000, }: { userAddress: string; pageSize?: number; refetchInterval?: number; }) => { + const { sqsActiveOrders } = useFeatureFlags(); const { orderbooks } = useOrderbooks(); const addresses = orderbooks.map(({ contractAddress }) => contractAddress); const { - data: orders, - isLoading, - fetchNextPage, - isFetching, - isFetchingNextPage, - hasNextPage, - refetch, - isRefetching, + data: sqsOrders, + isLoading: isSQSOrdersLoading, + fetchNextPage: fetchSQSOrdersNextPage, + isFetching: isSQSOrdersFetching, + isFetchingNextPage: isSQSOrdersFetchingNextPage, + hasNextPage: hasSQSOrdersNextPage, + refetch: refetchSQSOrders, + isRefetching: isSQSOrdersRefetching, + } = api.local.orderbooks.getAllOrdersSQS.useInfiniteQuery( + { + userOsmoAddress: userAddress, + limit: pageSize, + }, + { + getNextPageParam: (lastPage) => lastPage.nextCursor, + initialCursor: 0, + refetchInterval, + cacheTime: refetchInterval, + staleTime: refetchInterval, + enabled: !!userAddress && addresses.length > 0 && sqsActiveOrders, + refetchOnMount: true, + keepPreviousData: false, + trpc: { + abortOnUnmount: true, + context: { + skipBatch: true, + }, + }, + } + ); + + const { + data: nodeOrders, + isLoading: isNodeOrdersLoading, + fetchNextPage: fetchNodeOrdersNextPage, + isFetching: isNodeOrdersFetching, + isFetchingNextPage: isNodeOrdersFetchingNextPage, + hasNextPage: hasNodeOrdersNextPage, + refetch: refetchNodeOrders, + isRefetching: isNodeOrdersRefetching, } = api.edge.orderbooks.getAllOrders.useInfiniteQuery( { userOsmoAddress: userAddress, @@ -293,7 +331,7 @@ export const useOrderbookAllActiveOrders = ({ refetchInterval, cacheTime: refetchInterval, staleTime: refetchInterval, - enabled: !!userAddress && addresses.length > 0, + enabled: !!userAddress && addresses.length > 0 && !sqsActiveOrders, refetchOnMount: true, keepPreviousData: false, trpc: { @@ -305,14 +343,51 @@ export const useOrderbookAllActiveOrders = ({ } ); + return { + data: sqsActiveOrders ? sqsOrders : nodeOrders, + isLoading: sqsActiveOrders ? isSQSOrdersLoading : isNodeOrdersLoading, + fetchNextPage: sqsActiveOrders + ? fetchSQSOrdersNextPage + : fetchNodeOrdersNextPage, + isFetching: sqsActiveOrders ? isSQSOrdersFetching : isNodeOrdersFetching, + isFetchingNextPage: sqsActiveOrders + ? isSQSOrdersFetchingNextPage + : isNodeOrdersFetchingNextPage, + hasNextPage: sqsActiveOrders ? hasSQSOrdersNextPage : hasNodeOrdersNextPage, + refetch: sqsActiveOrders ? refetchSQSOrders : refetchNodeOrders, + isRefetching: sqsActiveOrders + ? isSQSOrdersRefetching + : isNodeOrdersRefetching, + }; +}; + +export const useOrderbookAllActiveOrders = ({ + userAddress, + pageSize = 10, + refetchInterval = 5000, +}: { + userAddress: string; + pageSize?: number; + refetchInterval?: number; +}) => { + const { + data: orders, + isLoading, + fetchNextPage, + isFetching, + isFetchingNextPage, + hasNextPage, + refetch, + isRefetching, + } = useOrdersQuery({ userAddress, pageSize, refetchInterval }); + const allOrders = useMemo(() => { return orders?.pages.flatMap((page) => page.items) ?? []; }, [orders]); const refetchOrders = useCallback(async () => { if (isRefetching) return; - - return refetch(); + await refetch(); }, [refetch, isRefetching]); return { @@ -327,33 +402,97 @@ export const useOrderbookAllActiveOrders = ({ }; }; +/** + * Queries for all claimable orders for a given user. + * Swaps between using SQS passthrough and a direct node query based on feature flag. + */ +const useClaimableOrdersQuery = ({ + userAddress, + disabled = false, + refetchInterval = 5000, +}: { + userAddress: string; + disabled?: boolean; + refetchInterval?: number; +}) => { + const { orderbooks } = useOrderbooks(); + const { sqsActiveOrders } = useFeatureFlags(); + const addresses = orderbooks.map(({ contractAddress }) => contractAddress); + const { data: claimableOrders, isLoading } = + api.local.orderbooks.getAllOrdersSQS.useInfiniteQuery( + { + userOsmoAddress: userAddress, + filter: "filled", + limit: 100, + }, + { + getNextPageParam: (lastPage) => lastPage.nextCursor, + initialCursor: 0, + refetchInterval, + enabled: + !!userAddress && addresses.length > 0 && !disabled && sqsActiveOrders, + refetchOnMount: true, + keepPreviousData: false, + trpc: { + abortOnUnmount: true, + context: { + skipBatch: true, + }, + }, + } + ); + + const { data: nodeClaimableOrders, isLoading: nodeIsLoading } = + api.edge.orderbooks.getClaimableOrders.useQuery( + { + userOsmoAddress: userAddress, + }, + { + enabled: + !!userAddress && + addresses.length > 0 && + !disabled && + !sqsActiveOrders, + refetchOnMount: true, + keepPreviousData: false, + trpc: { + abortOnUnmount: true, + context: { + skipBatch: true, + }, + }, + } + ); + + const orders = useMemo(() => { + if (!sqsActiveOrders) return nodeClaimableOrders; + return claimableOrders?.pages?.flatMap((page) => page.items) ?? []; + }, [claimableOrders?.pages, nodeClaimableOrders, sqsActiveOrders]); + + return { + data: orders, + isLoading: sqsActiveOrders ? isLoading : nodeIsLoading, + }; +}; + export const useOrderbookClaimableOrders = ({ - userAddress: _, - disabled: __, - orders = [], + userAddress, + disabled = false, + refetchInterval = 5000, }: { userAddress: string; disabled?: boolean; - orders: MappedLimitOrder[]; + refetchInterval?: number; }) => { const { orderbooks } = useOrderbooks(); const { accountStore } = useStore(); const account = accountStore.getWallet(accountStore.osmosisChainId); const addresses = orderbooks.map(({ contractAddress }) => contractAddress); - // const { - // data: orders, - // isLoading, - // isFetching, - // refetch, - // } = api.edge.orderbooks.getClaimableOrders.useQuery( - // { - // userOsmoAddress: userAddress, - // }, - // { - // enabled: !!userAddress && addresses.length > 0 && !disabled, - // refetchOnMount: true, - // } - // ); + const { data: orders, isLoading } = useClaimableOrdersQuery({ + userAddress, + disabled, + refetchInterval, + }); const claimAllOrders = useCallback(async () => { if (!account || !orders) return; @@ -390,7 +529,7 @@ export const useOrderbookClaimableOrders = ({ return { orders: orders ?? [], count: orders?.length ?? 0, - isLoading: false, + isLoading, claimAllOrders, }; }; diff --git a/packages/web/hooks/limit-orders/use-place-limit.ts b/packages/web/hooks/limit-orders/use-place-limit.ts index 88f5b2b877..8d58e58991 100644 --- a/packages/web/hooks/limit-orders/use-place-limit.ts +++ b/packages/web/hooks/limit-orders/use-place-limit.ts @@ -225,21 +225,26 @@ export const usePlaceLimit = ({ return; } - // The requested price must account for the ratio between the quote and base asset as the base asset may not be a stablecoin. - // To account for this we divide by the quote asset price. - const tickId = priceToTick( - priceState.price.quo(quoteAssetPrice.toDec()).mul(normalizationFactor) - ); - const msg = { - place_limit: { - tick_id: parseInt(tickId.toString()), - order_direction: orderDirection, - quantity, - claim_bounty: CLAIM_BOUNTY, - }, - }; + try { + // The requested price must account for the ratio between the quote and base asset as the base asset may not be a stablecoin. + // To account for this we divide by the quote asset price. + const tickId = priceToTick( + priceState.price.quo(quoteAssetPrice.toDec()).mul(normalizationFactor) + ); + const msg = { + place_limit: { + tick_id: parseInt(tickId.toString()), + order_direction: orderDirection, + quantity, + claim_bounty: CLAIM_BOUNTY, + }, + }; - return msg; + return msg; + } catch (error) { + console.error("Error attempting to place limit order", error); + return; + } }, [ orderDirection, priceState.price, @@ -295,6 +300,7 @@ export const usePlaceLimit = ({ feeValueUsd: Number(marketState.totalFee?.toString() ?? "0"), page, quoteTimeMilliseconds: marketState.quote?.timeMs, + swapSource: "market" as "swap" | "market", }; try { logEvent([EventName.Swap.swapStarted, baseEvent]); diff --git a/packages/web/hooks/use-amplitude-analytics.ts b/packages/web/hooks/use-amplitude-analytics.ts index bd482f812d..84067301de 100644 --- a/packages/web/hooks/use-amplitude-analytics.ts +++ b/packages/web/hooks/use-amplitude-analytics.ts @@ -5,12 +5,28 @@ import { logEvent as amplitudeLogEvent, } from "@amplitude/analytics-browser"; import { useEffect } from "react"; +import { create } from "zustand"; import { AmplitudeEvent, EventProperties, UserProperties } from "~/config"; /** set to true to see events and properties in console. DON'T COMMIT. */ const DEBUG = false; +type LastEvent = { + eventName: string; + eventProperties?: Partial & Record; +}; + +type AmplitudeStore = { + lastEvent: LastEvent | null; + setLastEvent: (event: LastEvent) => void; +}; + +const useAmplitudeStore = create((set) => ({ + lastEvent: null, + setLastEvent: (event) => set({ lastEvent: event }), +})); + export const logAmplitudeEvent = ([eventName, eventProperties]: | [string, (Partial & Record) | undefined] | [string]) => { @@ -18,6 +34,7 @@ export const logAmplitudeEvent = ([eventName, eventProperties]: console.info({ name: eventName, props: eventProperties }); } amplitudeLogEvent(eventName, eventProperties); + useAmplitudeStore.getState().setLastEvent({ eventName, eventProperties }); }; const setUserAmplitudeProperty = ( @@ -52,8 +69,15 @@ export function useAmplitudeAnalytics({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const logEvent = (event: AmplitudeEvent) => { + logAmplitudeEvent(event); + }; + + const getLastEvent = () => useAmplitudeStore.getState().lastEvent; + return { - logEvent: logAmplitudeEvent, + logEvent, setUserProperty: setUserAmplitudeProperty, + getLastEvent, }; } diff --git a/packages/web/hooks/use-feature-flags.ts b/packages/web/hooks/use-feature-flags.ts index 3a7a9dd561..bbbca4f2de 100644 --- a/packages/web/hooks/use-feature-flags.ts +++ b/packages/web/hooks/use-feature-flags.ts @@ -30,7 +30,8 @@ export type AvailableFlags = | "advancedChart" | "cypherCard" | "newPortfolioPage" - | "inGivenOut"; + | "inGivenOut" + | "sqsActiveOrders"; const defaultFlags: Record = { staking: true, @@ -56,6 +57,7 @@ const defaultFlags: Record = { cypherCard: false, newPortfolioPage: false, inGivenOut: false, + sqsActiveOrders: false, }; const LIMIT_ORDER_COUNTRY_CODES = @@ -67,7 +69,6 @@ export function useFeatureFlags() { const launchdarklyFlags: Record = useFlags(); const { isMobile } = useWindowSize(); const [isInitialized, setIsInitialized] = useState(false); - const client = useLDClient(); const { data: levanaGeoblock } = useQuery( diff --git a/packages/web/localizations/de.json b/packages/web/localizations/de.json index 82fb74ef53..7dcb0a5828 100644 --- a/packages/web/localizations/de.json +++ b/packages/web/localizations/de.json @@ -1158,7 +1158,6 @@ "transactionHash": "Transaktions-Hash", "viewOnExplorer": "Im Explorer anzeigen", "launchAlert": "Derzeit wird nur der Handelsverlauf angezeigt. Unterstützung für weitere Transaktionstypen folgt in Kürze.", - "noPriceData": "Preisdaten nicht verfügbar", "viewAll": "Alle ansehen", "history": "Geschichte", "orders": "Aufträge" diff --git a/packages/web/localizations/en.json b/packages/web/localizations/en.json index ef19e36ab9..1d36b948d3 100644 --- a/packages/web/localizations/en.json +++ b/packages/web/localizations/en.json @@ -1158,7 +1158,6 @@ "transactionHash": "Transaction Hash", "viewOnExplorer": "View on explorer", "launchAlert": "Currently only trade history is displayed. Support for more transaction types coming soon.", - "noPriceData": "Price data unavailable", "viewAll": "View all", "history": "History", "orders": "Orders" diff --git a/packages/web/localizations/es.json b/packages/web/localizations/es.json index 5a06d1fcc9..90028014ea 100644 --- a/packages/web/localizations/es.json +++ b/packages/web/localizations/es.json @@ -1158,7 +1158,6 @@ "transactionHash": "Hash de transacción", "viewOnExplorer": "Ver en el explorador", "launchAlert": "Actualmente solo se muestra el historial comercial. Próximamente soporte para más tipos de transacciones.", - "noPriceData": "Datos de precios no disponibles", "viewAll": "Ver todo", "history": "Historia", "orders": "Pedidos" diff --git a/packages/web/localizations/fa.json b/packages/web/localizations/fa.json index 70c9783676..c8d43d5328 100644 --- a/packages/web/localizations/fa.json +++ b/packages/web/localizations/fa.json @@ -1158,7 +1158,6 @@ "transactionHash": "هش تراکنش", "viewOnExplorer": "مشاهده در اکسپلورر", "launchAlert": "در حال حاضر فقط سابقه تجارت نمایش داده می شود. پشتیبانی از انواع تراکنش های بیشتر به زودی.", - "noPriceData": "اطلاعات قیمت در دسترس نیست", "viewAll": "مشاهده همه", "history": "تاریخ", "orders": "سفارشات" diff --git a/packages/web/localizations/fr.json b/packages/web/localizations/fr.json index 6ac60571e6..53f58ec2ee 100644 --- a/packages/web/localizations/fr.json +++ b/packages/web/localizations/fr.json @@ -1158,7 +1158,6 @@ "transactionHash": "Hachage des transactions", "viewOnExplorer": "Afficher sur l'explorateur", "launchAlert": "Actuellement, seul l'historique des échanges est affiché. Prise en charge d'autres types de transactions à venir.", - "noPriceData": "Données de prix indisponibles", "viewAll": "Voir tout", "history": "Histoire", "orders": "Ordres" diff --git a/packages/web/localizations/gu.json b/packages/web/localizations/gu.json index 0a5ebafc89..460702f9e4 100644 --- a/packages/web/localizations/gu.json +++ b/packages/web/localizations/gu.json @@ -1158,7 +1158,6 @@ "transactionHash": "ટ્રાન્ઝેક્શન હેશ", "viewOnExplorer": "એક્સપ્લોરર પર જુઓ", "launchAlert": "હાલમાં માત્ર વેપાર ઇતિહાસ પ્રદર્શિત થાય છે. વધુ વ્યવહાર પ્રકારો માટે સમર્થન ટૂંક સમયમાં આવી રહ્યું છે.", - "noPriceData": "કિંમત ડેટા ઉપલબ્ધ નથી", "viewAll": "બધુજ જુઓ", "history": "ઇતિહાસ", "orders": "ઓર્ડર" diff --git a/packages/web/localizations/hi.json b/packages/web/localizations/hi.json index 43272cf1d2..9539f01a02 100644 --- a/packages/web/localizations/hi.json +++ b/packages/web/localizations/hi.json @@ -1158,7 +1158,6 @@ "transactionHash": "लेनदेन हैश", "viewOnExplorer": "एक्सप्लोरर पर देखें", "launchAlert": "वर्तमान में केवल व्यापार इतिहास प्रदर्शित किया जाता है। जल्द ही अधिक लेनदेन प्रकारों के लिए सहायता उपलब्ध होगी।", - "noPriceData": "मूल्य डेटा उपलब्ध नहीं है", "viewAll": "सभी को देखें", "history": "इतिहास", "orders": "आदेश" diff --git a/packages/web/localizations/ja.json b/packages/web/localizations/ja.json index 582c5f6858..8732d7eed4 100644 --- a/packages/web/localizations/ja.json +++ b/packages/web/localizations/ja.json @@ -1158,7 +1158,6 @@ "transactionHash": "トランザクションハッシュ", "viewOnExplorer": "エクスプローラーで見る", "launchAlert": "現在は取引履歴のみが表示されます。他の取引タイプも近日中にサポートされる予定です。", - "noPriceData": "価格データは利用できません", "viewAll": "すべて表示", "history": "歴史", "orders": "注文" diff --git a/packages/web/localizations/ko.json b/packages/web/localizations/ko.json index aed9437328..aa7e77a0cb 100644 --- a/packages/web/localizations/ko.json +++ b/packages/web/localizations/ko.json @@ -1158,7 +1158,6 @@ "transactionHash": "거래 해시", "viewOnExplorer": "탐색기에서 보기", "launchAlert": "현재는 거래 내역만 표시됩니다. 더 많은 거래 유형이 곧 지원될 예정입니다.", - "noPriceData": "가격 데이터를 사용할 수 없습니다.", "viewAll": "모두보기", "history": "역사", "orders": "명령" diff --git a/packages/web/localizations/pl.json b/packages/web/localizations/pl.json index 2914d7807c..f4728d10fc 100644 --- a/packages/web/localizations/pl.json +++ b/packages/web/localizations/pl.json @@ -1158,7 +1158,6 @@ "transactionHash": "Hash transakcji", "viewOnExplorer": "Zobacz w eksploratorze", "launchAlert": "Obecnie wyświetlana jest tylko historia transakcji. Wkrótce obsługa większej liczby typów transakcji.", - "noPriceData": "Dane cenowe niedostępne", "viewAll": "Pokaż wszystkie", "history": "Historia", "orders": "Zamówienia" diff --git a/packages/web/localizations/pt-br.json b/packages/web/localizations/pt-br.json index a06b2a08b0..150883f909 100644 --- a/packages/web/localizations/pt-br.json +++ b/packages/web/localizations/pt-br.json @@ -1158,7 +1158,6 @@ "transactionHash": "Hash de transação", "viewOnExplorer": "Ver no explorador", "launchAlert": "Atualmente apenas o histórico de negociações é exibido. Suporte para mais tipos de transação em breve.", - "noPriceData": "Dados de preço indisponíveis", "viewAll": "Ver tudo", "history": "História", "orders": "Pedidos" diff --git a/packages/web/localizations/ro.json b/packages/web/localizations/ro.json index 69418213ee..de825da860 100644 --- a/packages/web/localizations/ro.json +++ b/packages/web/localizations/ro.json @@ -1158,7 +1158,6 @@ "transactionHash": "Hash de tranzacție", "viewOnExplorer": "Vizualizare pe explorer", "launchAlert": "Momentan este afișat doar istoricul comerțului. Asistență pentru mai multe tipuri de tranzacții în curând.", - "noPriceData": "Datele de preț nu sunt disponibile", "viewAll": "A vedea tot", "history": "Istorie", "orders": "Comenzi" diff --git a/packages/web/localizations/ru.json b/packages/web/localizations/ru.json index 7717f21908..e0472d1d3c 100644 --- a/packages/web/localizations/ru.json +++ b/packages/web/localizations/ru.json @@ -1158,7 +1158,6 @@ "transactionHash": "Хэш транзакции", "viewOnExplorer": "Посмотреть в проводнике", "launchAlert": "В настоящее время отображается только история торговли. Скоро появится поддержка большего количества типов транзакций.", - "noPriceData": "Данные о ценах недоступны.", "viewAll": "Посмотреть все", "history": "История", "orders": "Заказы" diff --git a/packages/web/localizations/tr.json b/packages/web/localizations/tr.json index 9c52f6ae8e..21d28da809 100644 --- a/packages/web/localizations/tr.json +++ b/packages/web/localizations/tr.json @@ -1158,7 +1158,6 @@ "transactionHash": "İşlem Karması", "viewOnExplorer": "Explorer'da görüntüle", "launchAlert": "Şu anda yalnızca ticaret geçmişi görüntüleniyor. Yakında daha fazla işlem türü için destek sunulacak.", - "noPriceData": "Fiyat verileri mevcut değil", "viewAll": "Hepsini gör", "history": "Tarih", "orders": "Emirler" diff --git a/packages/web/localizations/zh-cn.json b/packages/web/localizations/zh-cn.json index 004f1efa02..7492a59f56 100644 --- a/packages/web/localizations/zh-cn.json +++ b/packages/web/localizations/zh-cn.json @@ -1158,7 +1158,6 @@ "transactionHash": "交易哈希", "viewOnExplorer": "在资源管理器中查看", "launchAlert": "目前仅显示交易历史。即将支持更多交易类型。", - "noPriceData": "价格数据不可用", "viewAll": "查看全部", "history": "历史", "orders": "命令" diff --git a/packages/web/localizations/zh-hk.json b/packages/web/localizations/zh-hk.json index 4d01e5a91e..0220626ab2 100644 --- a/packages/web/localizations/zh-hk.json +++ b/packages/web/localizations/zh-hk.json @@ -1158,7 +1158,6 @@ "transactionHash": "交易哈希", "viewOnExplorer": "在資源管理器上查看", "launchAlert": "目前僅顯示交易歷史記錄。即將支援更多交易類型。", - "noPriceData": "價格數據不可用", "viewAll": "看全部", "history": "歷史", "orders": "命令" diff --git a/packages/web/localizations/zh-tw.json b/packages/web/localizations/zh-tw.json index 07cf11e00d..7c2d58a5f7 100644 --- a/packages/web/localizations/zh-tw.json +++ b/packages/web/localizations/zh-tw.json @@ -1158,7 +1158,6 @@ "transactionHash": "交易哈希", "viewOnExplorer": "在資源管理器上查看", "launchAlert": "目前僅顯示交易歷史記錄。即將支援更多交易類型。", - "noPriceData": "價格數據不可用", "viewAll": "看全部", "history": "歷史", "orders": "命令" diff --git a/packages/web/pages/earn/index.tsx b/packages/web/pages/earn/index.tsx index ff7e8539eb..d023b3a0cf 100644 --- a/packages/web/pages/earn/index.tsx +++ b/packages/web/pages/earn/index.tsx @@ -38,6 +38,8 @@ function Earn() { const { earnPage, _isInitialized } = useFeatureFlags(); const { accountStore } = useStore(); const router = useRouter(); + const { search } = router.query; + /** * Control the selected table idx for external control * such as the {num} positions onClick on EarnPosition @@ -86,11 +88,11 @@ function Earn() { })) : [], lockDurationType: "all", - search: "", + search: typeof search === "string" ? search : "", specialTokens: [], rewardType: "all", }), - [holdenDenoms?.length, cmsData, isWalletConnected] + [holdenDenoms?.length, cmsData, isWalletConnected, search] ); useEffect(() => { diff --git a/packages/web/server/api/local-router.ts b/packages/web/server/api/local-router.ts index 34ced5f62d..cb4134091f 100644 --- a/packages/web/server/api/local-router.ts +++ b/packages/web/server/api/local-router.ts @@ -4,6 +4,7 @@ import { concentratedLiquidityRouter, createTRPCRouter, oneClickTradingRouter, + orderbookRouter, paramsRouter, portfolioRouter, swapRouter, @@ -23,4 +24,5 @@ export const localRouter = createTRPCRouter({ bridgeTransfer: localBridgeTransferRouter, portfolio: portfolioRouter, params: paramsRouter, + orderbooks: orderbookRouter, }); diff --git a/packages/web/stores/index.tsx b/packages/web/stores/index.tsx index 9dd720703f..0e00910595 100644 --- a/packages/web/stores/index.tsx +++ b/packages/web/stores/index.tsx @@ -28,8 +28,7 @@ export function refetchUserQueries(apiUtils: ReturnType) { apiUtils.local.balances.getUserBalances.invalidate(); apiUtils.local.bridgeTransfer.getSupportedAssetsBalances.invalidate(); apiUtils.edge.assets.getImmersiveBridgeAssets.invalidate(); - apiUtils.edge.orderbooks.getAllOrders.invalidate(); - apiUtils.edge.orderbooks.getClaimableOrders.invalidate(); + apiUtils.local.orderbooks.getAllOrdersSQS.invalidate(); } const EXCEEDS_1CT_NETWORK_FEE_LIMIT_TOAST_ID = "exceeds-1ct-network-fee-limit";