From 1bc86368654068cc551798571eadd31b2e83ab0f Mon Sep 17 00:00:00 2001 From: YY Date: Thu, 30 Oct 2025 15:16:13 +0800 Subject: [PATCH 01/10] feat: perps api --- api-reference/perps.mdx | 5 + api-reference/perps/delete-tpsl.mdx | 5 + api-reference/perps/get-market-stats.mdx | 5 + api-reference/perps/get-ordersexpired.mdx | 5 + api-reference/perps/get-pool-info.mdx | 5 + api-reference/perps/get-positions.mdx | 5 + .../perps/get-positionscollateral-limits.mdx | 5 + api-reference/perps/get-top-traders.mdx | 5 + api-reference/perps/get-trader-stats.mdx | 5 + api-reference/perps/get-trades.mdx | 5 + api-reference/perps/others/get-jlp-info.mdx | 3 + .../perps/others/get-lendinghistory.mdx | 3 + .../perps/others/get-lendinginfo.mdx | 3 + .../perps/others/get-lendingpositions.mdx | 3 + api-reference/perps/others/post-jlpburn.mdx | 3 + api-reference/perps/others/post-jlpmint.mdx | 3 + .../others/post-lendingdeposit-borrow.mdx | 3 + .../perps/others/post-lendingpay-withdraw.mdx | 3 + api-reference/perps/patch-tpsl.mdx | 5 + .../perps/post-positionsclose-all.mdx | 5 + .../perps/post-positionsdecrease.mdx | 5 + .../perps/post-positionsincrease.mdx | 5 + api-reference/perps/post-tpsl.mdx | 5 + docs.json | 32 +- docs/perps/fees.mdx | 0 docs/perps/get-started.mdx | 46 + docs/perps/index.mdx | 80 +- docs/perps/jlp.mdx | 0 docs/perps/liquidation.mdx | 0 docs/perps/oracles.mdx | 0 docs/ultra/get-started.mdx | 27 +- openapi-spec/perps/perps.yaml | 3864 +++++++++++++++++ 32 files changed, 4123 insertions(+), 25 deletions(-) create mode 100644 api-reference/perps.mdx create mode 100644 api-reference/perps/delete-tpsl.mdx create mode 100644 api-reference/perps/get-market-stats.mdx create mode 100644 api-reference/perps/get-ordersexpired.mdx create mode 100644 api-reference/perps/get-pool-info.mdx create mode 100644 api-reference/perps/get-positions.mdx create mode 100644 api-reference/perps/get-positionscollateral-limits.mdx create mode 100644 api-reference/perps/get-top-traders.mdx create mode 100644 api-reference/perps/get-trader-stats.mdx create mode 100644 api-reference/perps/get-trades.mdx create mode 100644 api-reference/perps/others/get-jlp-info.mdx create mode 100644 api-reference/perps/others/get-lendinghistory.mdx create mode 100644 api-reference/perps/others/get-lendinginfo.mdx create mode 100644 api-reference/perps/others/get-lendingpositions.mdx create mode 100644 api-reference/perps/others/post-jlpburn.mdx create mode 100644 api-reference/perps/others/post-jlpmint.mdx create mode 100644 api-reference/perps/others/post-lendingdeposit-borrow.mdx create mode 100644 api-reference/perps/others/post-lendingpay-withdraw.mdx create mode 100644 api-reference/perps/patch-tpsl.mdx create mode 100644 api-reference/perps/post-positionsclose-all.mdx create mode 100644 api-reference/perps/post-positionsdecrease.mdx create mode 100644 api-reference/perps/post-positionsincrease.mdx create mode 100644 api-reference/perps/post-tpsl.mdx create mode 100644 docs/perps/fees.mdx create mode 100644 docs/perps/get-started.mdx create mode 100644 docs/perps/jlp.mdx create mode 100644 docs/perps/liquidation.mdx create mode 100644 docs/perps/oracles.mdx create mode 100644 openapi-spec/perps/perps.yaml diff --git a/api-reference/perps.mdx b/api-reference/perps.mdx new file mode 100644 index 00000000..eb59aeeb --- /dev/null +++ b/api-reference/perps.mdx @@ -0,0 +1,5 @@ +--- +title: "Perps (Beta)" +sidebarTitle: "Overview" +description: "Overview of Jupiter Perps API" +--- diff --git a/api-reference/perps/delete-tpsl.mdx b/api-reference/perps/delete-tpsl.mdx new file mode 100644 index 00000000..8ae32040 --- /dev/null +++ b/api-reference/perps/delete-tpsl.mdx @@ -0,0 +1,5 @@ +--- +title: "DELETE TPSL" +sidebarTitle: "TPSL" +openapi: /openapi-spec/perps/perps.yaml delete /tpsl +--- \ No newline at end of file diff --git a/api-reference/perps/get-market-stats.mdx b/api-reference/perps/get-market-stats.mdx new file mode 100644 index 00000000..cdbad514 --- /dev/null +++ b/api-reference/perps/get-market-stats.mdx @@ -0,0 +1,5 @@ +--- +title: "GET Market Stats" +sidebarTitle: "Market Stats" +openapi: /openapi-spec/perps/perps.yaml get /market-stats +--- \ No newline at end of file diff --git a/api-reference/perps/get-ordersexpired.mdx b/api-reference/perps/get-ordersexpired.mdx new file mode 100644 index 00000000..bd0d5eb3 --- /dev/null +++ b/api-reference/perps/get-ordersexpired.mdx @@ -0,0 +1,5 @@ +--- +title: "GET Orders Expired" +sidebarTitle: "Orders Expired" +openapi: /openapi-spec/perps/perps.yaml get /orders/expired +--- \ No newline at end of file diff --git a/api-reference/perps/get-pool-info.mdx b/api-reference/perps/get-pool-info.mdx new file mode 100644 index 00000000..1748f486 --- /dev/null +++ b/api-reference/perps/get-pool-info.mdx @@ -0,0 +1,5 @@ +--- +title: "GET Pool Info" +sidebarTitle: "Pool Info" +openapi: /openapi-spec/perps/perps.yaml get /pool-info +--- \ No newline at end of file diff --git a/api-reference/perps/get-positions.mdx b/api-reference/perps/get-positions.mdx new file mode 100644 index 00000000..ba0879a9 --- /dev/null +++ b/api-reference/perps/get-positions.mdx @@ -0,0 +1,5 @@ +--- +title: "GET Positions" +sidebarTitle: "Positions" +openapi: /openapi-spec/perps/perps.yaml get /positions +--- \ No newline at end of file diff --git a/api-reference/perps/get-positionscollateral-limits.mdx b/api-reference/perps/get-positionscollateral-limits.mdx new file mode 100644 index 00000000..15ad647c --- /dev/null +++ b/api-reference/perps/get-positionscollateral-limits.mdx @@ -0,0 +1,5 @@ +--- +title: "GET Positions Collateral Limits" +sidebarTitle: "Positions Collateral Limits" +openapi: /openapi-spec/perps/perps.yaml get /positions/collateral-limits +--- \ No newline at end of file diff --git a/api-reference/perps/get-top-traders.mdx b/api-reference/perps/get-top-traders.mdx new file mode 100644 index 00000000..867b9598 --- /dev/null +++ b/api-reference/perps/get-top-traders.mdx @@ -0,0 +1,5 @@ +--- +title: "GET Top Traders" +sidebarTitle: "Top Traders" +openapi: /openapi-spec/perps/perps.yaml get /top-traders +--- \ No newline at end of file diff --git a/api-reference/perps/get-trader-stats.mdx b/api-reference/perps/get-trader-stats.mdx new file mode 100644 index 00000000..b717eb80 --- /dev/null +++ b/api-reference/perps/get-trader-stats.mdx @@ -0,0 +1,5 @@ +--- +title: "GET Trader Stats" +sidebarTitle: "Trader Stats" +openapi: /openapi-spec/perps/perps.yaml get /trader-stats +--- \ No newline at end of file diff --git a/api-reference/perps/get-trades.mdx b/api-reference/perps/get-trades.mdx new file mode 100644 index 00000000..b31eac58 --- /dev/null +++ b/api-reference/perps/get-trades.mdx @@ -0,0 +1,5 @@ +--- +title: "GET Trades" +sidebarTitle: "Trades" +openapi: /openapi-spec/perps/perps.yaml get /trades +--- \ No newline at end of file diff --git a/api-reference/perps/others/get-jlp-info.mdx b/api-reference/perps/others/get-jlp-info.mdx new file mode 100644 index 00000000..a8d1b2ff --- /dev/null +++ b/api-reference/perps/others/get-jlp-info.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml get /jlp-info +--- \ No newline at end of file diff --git a/api-reference/perps/others/get-lendinghistory.mdx b/api-reference/perps/others/get-lendinghistory.mdx new file mode 100644 index 00000000..42537a45 --- /dev/null +++ b/api-reference/perps/others/get-lendinghistory.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml get /lending/history +--- \ No newline at end of file diff --git a/api-reference/perps/others/get-lendinginfo.mdx b/api-reference/perps/others/get-lendinginfo.mdx new file mode 100644 index 00000000..04135dd9 --- /dev/null +++ b/api-reference/perps/others/get-lendinginfo.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml get /lending/info +--- \ No newline at end of file diff --git a/api-reference/perps/others/get-lendingpositions.mdx b/api-reference/perps/others/get-lendingpositions.mdx new file mode 100644 index 00000000..8a39bd9d --- /dev/null +++ b/api-reference/perps/others/get-lendingpositions.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml get /lending/positions +--- \ No newline at end of file diff --git a/api-reference/perps/others/post-jlpburn.mdx b/api-reference/perps/others/post-jlpburn.mdx new file mode 100644 index 00000000..bf568cf6 --- /dev/null +++ b/api-reference/perps/others/post-jlpburn.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml post /jlp/burn +--- \ No newline at end of file diff --git a/api-reference/perps/others/post-jlpmint.mdx b/api-reference/perps/others/post-jlpmint.mdx new file mode 100644 index 00000000..1c99aa42 --- /dev/null +++ b/api-reference/perps/others/post-jlpmint.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml post /jlp/mint +--- \ No newline at end of file diff --git a/api-reference/perps/others/post-lendingdeposit-borrow.mdx b/api-reference/perps/others/post-lendingdeposit-borrow.mdx new file mode 100644 index 00000000..ef67b0bb --- /dev/null +++ b/api-reference/perps/others/post-lendingdeposit-borrow.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml post /lending/deposit-borrow +--- \ No newline at end of file diff --git a/api-reference/perps/others/post-lendingpay-withdraw.mdx b/api-reference/perps/others/post-lendingpay-withdraw.mdx new file mode 100644 index 00000000..f0f66315 --- /dev/null +++ b/api-reference/perps/others/post-lendingpay-withdraw.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml post /lending/pay-withdraw +--- \ No newline at end of file diff --git a/api-reference/perps/patch-tpsl.mdx b/api-reference/perps/patch-tpsl.mdx new file mode 100644 index 00000000..8437c2ff --- /dev/null +++ b/api-reference/perps/patch-tpsl.mdx @@ -0,0 +1,5 @@ +--- +title: "PATCH TPSL" +sidebarTitle: "TPSL" +openapi: /openapi-spec/perps/perps.yaml patch /tpsl +--- \ No newline at end of file diff --git a/api-reference/perps/post-positionsclose-all.mdx b/api-reference/perps/post-positionsclose-all.mdx new file mode 100644 index 00000000..28dd59c8 --- /dev/null +++ b/api-reference/perps/post-positionsclose-all.mdx @@ -0,0 +1,5 @@ +--- +title: "POST Positions Close All" +sidebarTitle: "Positions Close All" +openapi: /openapi-spec/perps/perps.yaml post /positions/close-all +--- \ No newline at end of file diff --git a/api-reference/perps/post-positionsdecrease.mdx b/api-reference/perps/post-positionsdecrease.mdx new file mode 100644 index 00000000..a6bdb14d --- /dev/null +++ b/api-reference/perps/post-positionsdecrease.mdx @@ -0,0 +1,5 @@ +--- +title: "POST Positions Decrease" +sidebarTitle: "Positions Decrease" +openapi: /openapi-spec/perps/perps.yaml post /positions/decrease +--- \ No newline at end of file diff --git a/api-reference/perps/post-positionsincrease.mdx b/api-reference/perps/post-positionsincrease.mdx new file mode 100644 index 00000000..b07a724d --- /dev/null +++ b/api-reference/perps/post-positionsincrease.mdx @@ -0,0 +1,5 @@ +--- +title: "POST Positions Increase" +sidebarTitle: "Positions Increase" +openapi: /openapi-spec/perps/perps.yaml post /positions/increase +--- \ No newline at end of file diff --git a/api-reference/perps/post-tpsl.mdx b/api-reference/perps/post-tpsl.mdx new file mode 100644 index 00000000..a86f137d --- /dev/null +++ b/api-reference/perps/post-tpsl.mdx @@ -0,0 +1,5 @@ +--- +title: "POST TPSL" +sidebarTitle: "TPSL" +openapi: /openapi-spec/perps/perps.yaml post /tpsl +--- \ No newline at end of file diff --git a/docs.json b/docs.json index 78015604..0094e17a 100644 --- a/docs.json +++ b/docs.json @@ -158,8 +158,15 @@ "icon": "chart-line", "groups": [ { - "group": " ", - "pages": ["docs/perps/index"] + "group": "About Perps", + "pages": [ + "docs/perps/index", + "docs/perps/get-started", + "docs/perps/jlp", + "docs/perps/oracles", + "docs/perps/fees", + "docs/perps/liquidation" + ] }, { "group": "Perps Program", @@ -391,6 +398,27 @@ } ] }, + { + "group": "Perps", + "tag": "BETA", + "pages": [ + "api-reference/perps", + "api-reference/perps/get-positions", + "api-reference/perps/post-positionsincrease", + "api-reference/perps/post-positionsdecrease", + "api-reference/perps/post-positionsclose-all", + "api-reference/perps/post-tpsl", + "api-reference/perps/patch-tpsl", + "api-reference/perps/delete-tpsl", + "api-reference/perps/get-ordersexpired", + "api-reference/perps/get-market-stats", + "api-reference/perps/get-positionscollateral-limits", + "api-reference/perps/get-trades", + "api-reference/perps/get-top-traders", + "api-reference/perps/get-trader-stats", + "api-reference/perps/get-pool-info" + ] + }, { "group": "Trigger", "pages": [ diff --git a/docs/perps/fees.mdx b/docs/perps/fees.mdx new file mode 100644 index 00000000..e69de29b diff --git a/docs/perps/get-started.mdx b/docs/perps/get-started.mdx new file mode 100644 index 00000000..225ebea6 --- /dev/null +++ b/docs/perps/get-started.mdx @@ -0,0 +1,46 @@ +--- +title: "Get Started" +description: "Get started to develop with Jupiter Perpetuals." +--- + +## API Reference + +Refer to the [Perps API Reference](/api-reference/perps) for the complete API documentation. + + +## Swap Endpoints +| Endpoint | Description | +| :------- | :---------- | +| [**Get Order**](/docs/ultra/get-order) | Request for a quote and swap transaction. | +| [**Execute Order**](/docs/ultra/execute-order) | Sign and execute the swap transaction. | + +## Data Endpoints +| Endpoint | Description | +| :------- | :---------- | +| [**Search Token**](/docs/ultra/search-token) | Search for a token by its symbol, name or mint address. | +| [**Get Holdings**](/docs/ultra/get-holdings) | Request for token balances of an account. | +| [**Get Shield**](/docs/ultra/get-shield) | Enhanced security feature to provide critical token information contributing to better informed trading decisions. | + +## FAQ + + + + +* **Integrator without custom fees**: Do note that when your users swap using Ultra Swap, we take 5 to 10 bps of the swap amount as a fee. +* **Integrator with custom fees**: If you are an integrator, you can add custom integrator fees via Ultra Swap API and Jupiter will take 20% of the integrator fees. Please refer to the [Add Fees To Ultra Swap](/docs/ultra/add-fees-to-ultra) guide for more information. + + + +* No, you cannot modify Ultra Swap transactions. +* Ultra Swap is intended to use as is, without any modifications. + + + +* Dynamic Rate Limits are now applied to Ultra Swap API. + + * No Pro plans or payment needed. + * Simply generate the universal API Key via [Portal](https://portal.jup.ag) + * Rate limits scale together with your swap volume. + * [Read more about Ultra Swap API Dynamic Rate Limit](/portal/rate-limit). + + diff --git a/docs/perps/index.mdx b/docs/perps/index.mdx index 9abf72b6..a1bcc262 100644 --- a/docs/perps/index.mdx +++ b/docs/perps/index.mdx @@ -1,20 +1,74 @@ --- -title: "About Perps API" +title: "Overview" +sidebarTitle: "Overview" +description: "Overview of Jupiter Perpetuals where you can trade with leverage up to 250x on SOL, ETH and wBTC." --- - - **WARNING** +## Features - The Perps API is still a **work in progress**, stay tuned! - +In this overview, we will cover the core features of the Jupiter Perps +and how it differs from traditional leverage trading exchanges. - - **TIP** - - In the meantime, you can use this amazing github repository to direct Anchor IDL parse the Perps Program. + + To quickstart your developer integration, you can head over to the + [Get Started](/docs/perps/get-started) guide or dive into the + [API Reference](/api-reference/perps) for the complete API documentation. + - * Fetch Perps or JLP pool data - * Interact with the Perps Program +### Trader-to-LP Exchange +**Jupiter Liquidity Providers**: Liquidity for the Jupiter Perps is provided by the JLP Pool, which holds +SOL, ETH, wBTC, and USDC as the underlying tokens. The pool provides ample +liquidity for traders to open highly-leveraged positions, while earning an +attractive return on a portion of the trading fees. - [https://github.com/julianfssen/jupiter-perps-anchor-idl-parsing](https://github.com/julianfssen/jupiter-perps-anchor-idl-parsing) - +**Traders**: Traders can deposit collateral to enter positions and borrow the rest of +the position from the pool. Subsequently, they can manage their positions +by withdrawing collateral to close their positions fully or partially. The +Jupiter Perpetuals Exchange features a simple interface and underlying +trading mechanisms to provide a safe and seamless trading experience. + +### Pool-Based Liquidity +* Liquidity comes from the JLP pool, not from resting orders. +* Traders open and close positions directly against the pool. +* Trade size is limited only by available liquidity and position-level size constraints. +* Refer to the [JLP](/docs/perps/jlp) document for more information. + +### Oracle-Based Pricing +* All trades execute at the oracle price. +* Large trades (e.g., $10 million) do not affect the price for others. +* Prices are sourced from verified oracles and are unaffected by trade size or direction. +* Refer to the [Oracles](/docs/perps/oracles) document for more information. + +### On-Chain Position Accounts +* Each user's exposure per asset and direction (long/short) is stored as a position account on-chain. +* Multiple trades on the same side (e.g., two long SOL trades) merge into a single position. +* Opening opposite positions (e.g., closing a long by shorting) does not flip exposure; it closes the existing position and realizes PnL. +* Refer to the [Position Account](/docs/perps/position-account) document for more information. + +### Immediate-or-Revert Execution +* Every trade executes in a single transaction or fails atomically. +* No partial fills, maker/taker matching, or time-in-force orders. + +### Position-Level Risk Controls +* Before execution, every trade passes a full validation layer: + * Collateral checks: minimum margin and leverage caps. + * Pool liquidity checks: ensure sufficient tokens exist to back exposure. + * Position limits: wallet-level and pool-level maximum size caps. +* Orderbooks typically handle risk at the matching engine level; Jupiter enforces it at the position and pool level. + +### Pool-Driven Fees +* Trading fees are derived from pool mechanics, not spreads or maker/taker roles. +* Open/close/price impact fees: based on pool math (swap, borrow, and price-impact fees). +* Continuous borrow fees: accrue based on the pool's open exposure, not paid between counterparties. +* No traditional funding rates; both longs and shorts pay borrow fees to the pool. +* Refer to the [Fees](/docs/perps/fees) document for more information. + +### Collateral Model +* Longs are backed by the underlying asset (e.g., SOL, ETH, wBTC). +* Shorts are backed by USDC. +* The program handles collateral assignment automatically - traders simply supply margin in their chosen deposit asset. + +### No Synthetic Flipping +* Positions are stored on-chain as PDAs, not synthetic toggles. +* Reducing or closing exposure adjusts the position account. +* You can't accidentally “flip” from long to short via over-selling; you can only close or reduce up to your existing position size. diff --git a/docs/perps/jlp.mdx b/docs/perps/jlp.mdx new file mode 100644 index 00000000..e69de29b diff --git a/docs/perps/liquidation.mdx b/docs/perps/liquidation.mdx new file mode 100644 index 00000000..e69de29b diff --git a/docs/perps/oracles.mdx b/docs/perps/oracles.mdx new file mode 100644 index 00000000..e69de29b diff --git a/docs/ultra/get-started.mdx b/docs/ultra/get-started.mdx index ea095cab..1729ce5e 100644 --- a/docs/ultra/get-started.mdx +++ b/docs/ultra/get-started.mdx @@ -3,16 +3,23 @@ title: "Get Started" description: "Get started with the Ultra Swap API." --- -## Overview - -| Step | Endpoint | Description | -| :--- | :------- | :---------- | -| 1 | [**Get Order**](/docs/ultra/get-order) | Request for a quote and swap transaction. | -| 2 | [**Execute Order**](/docs/ultra/execute-order) | Sign and execute the swap transaction. | -| - | [**Search Token**](/docs/ultra/search-token) | Search for a token by its symbol, name or mint address. | -| - | [**Get Holdings**](/docs/ultra/get-holdings) | Request for token balances of an account. | -| - | [**Get Shield**](/docs/ultra/get-shield) | Enhanced security feature to provide critical token information contributing to better informed trading decisions. | -| - | [**API Reference**](/api-reference/ultra) | Reference for the Ultra Swap API endpoints. | +## API Reference + +Refer to the [Ultra Swap API Reference](/api-reference/ultra) for the complete API documentation. + + +## Swap Endpoints +| Endpoint | Description | +| :------- | :---------- | +| [**Get Order**](/docs/ultra/get-order) | Request for a quote and swap transaction. | +| [**Execute Order**](/docs/ultra/execute-order) | Sign and execute the swap transaction. | + +## Data Endpoints +| Endpoint | Description | +| :------- | :---------- | +| [**Search Token**](/docs/ultra/search-token) | Search for a token by its symbol, name or mint address. | +| [**Get Holdings**](/docs/ultra/get-holdings) | Request for token balances of an account. | +| [**Get Shield**](/docs/ultra/get-shield) | Enhanced security feature to provide critical token information contributing to better informed trading decisions. | ## Guides diff --git a/openapi-spec/perps/perps.yaml b/openapi-spec/perps/perps.yaml new file mode 100644 index 00000000..1bcbc7e5 --- /dev/null +++ b/openapi-spec/perps/perps.yaml @@ -0,0 +1,3864 @@ +openapi: 3.1.0 + +info: + title: Jupiter Perpetuals API Specification + version: 1.0.0 + +servers: + - url: https://lite-api.jup.ag/perps/v1 + description: Free tier API endpoint with rate limits + - url: https://api.jup.ag/perps/v1 + description: Paid tier API endpoint with higher rate limits to be used with an API Key + +paths: + /market-stats: + description: Fetches 24-hour market stats for the given market + get: + parameters: + - in: query + name: mint + description: Mint address for the given market + schema: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + description: Mint address for the given market + required: true + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + price: + type: string + description: Current USD price for the given market + example: '123.00' + priceChange24H: + type: string + description: Current USD 24-hour price change (%) for the given market + example: '-20.00' + priceHigh24H: + type: string + description: USD value for the 24-hour high price for the given market + example: '123.00' + priceLow24H: + type: string + description: USD value for the 24-hour low price for the given market + example: '123.00' + volume: + type: string + description: >- + USD value for the 24-hour total volume for the given + market + example: '48123049.00' + required: + - price + - priceChange24H + - priceHigh24H + - priceLow24H + - volume + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /orders/expired: + description: Fetches expired orders for the wallet address + get: + parameters: + - in: query + name: walletAddress + description: Public key for the wallet to fetch expired orders + schema: + type: string + description: Public key for the wallet to fetch expired orders + required: true + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + serializedTxs: + type: array + items: + type: object + properties: + serializedTxBase64: + type: string + description: >- + The serialized transaction (base64 encoded) + containing the instructions and given parameters for + the close position request instruction. The + transaction can be deserialized, signed by the owner + of `walletAddress` and submitted onchain to close + the position request + positionRequestPubkey: + type: string + description: The public key / address for the position request. + required: + - serializedTxBase64 + - positionRequestPubkey + description: >- + An array of base64-serialized transactions and the + `positionRequestPubkey` to close all expired orders. + txMetadata: + type: object + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + close position request transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed close position request transaction. + required: + - blockhash + - lastValidBlockHeight + description: >- + Contains blockhash metadata for the serialized transaction + to submit and confirm the transactions. + required: + - serializedTxs + - txMetadata + description: >- + An array of base64-serialized transactions and transaction + metadata to close all expired orders. + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /positions: + description: Fetches the open positions for the given wallet address + get: + parameters: + - in: query + name: walletAddress + description: Public key for the wallet to fetch trades + schema: + type: string + description: Public key for the wallet to fetch trades + required: true + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + dataList: + type: array + items: + type: object + properties: + borrowFees: + type: string + description: >- + The outstanding borrow fees for the position in the + integer format corresponding to the 6 decimals + places used by the USDC and USDT token mint + example: '100000' + borrowFeesUsd: + type: string + description: The outstanding borrow fees (USD) for the position + example: '10.00' + closeFees: + type: string + description: >- + The fee for closing the position (0.06%) in the + integer format corresponding to the 6 decimals + places used by the USDC and USDT token mint + example: '100000' + closeFeesUsd: + type: string + description: The fee (USD) for closing the position (0.06%) + example: '10.00' + collateral: + type: string + description: USD value of the position's collateral size + example: '250.00' + collateralUsd: + type: string + description: Raw USD value of the position's collateral size + example: '250000000' + collateralMint: + type: string + description: >- + The mint address for the position's collateral + token. 'SOL' = + 'So11111111111111111111111111111111111111112', 'ETH' + = '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs', + 'BTC' = + '3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh', + 'USDC' = + 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', + 'USDT' = + 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB' + example: So11111111111111111111111111111111111111112 + createdTime: + type: number + description: UNIX timestamp of when the trade was created + example: 1722851463 + entryPrice: + type: string + description: USD value of the position's entry price + example: '123.45' + leverage: + type: string + description: Leverage amount for the position + example: '21.30' + liquidationPrice: + type: string + description: USD value of the position's liquidation price + example: '123.45' + marketMint: + type: string + description: >- + The asset or market being traded against for the + position. 'SOL' = + 'So11111111111111111111111111111111111111112', 'ETH' + = '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs', + 'BTC' = + '3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh' + example: So11111111111111111111111111111111111111112 + markPrice: + type: string + description: USD value of the position's mark price + example: '123.45' + openFees: + type: string + description: >- + The fee for opening the position (0.06%) in the + integer format corresponding to the 6 decimals + places used by the USDC and USDT token mint + example: '100000' + openFeesUsd: + type: string + description: The fee (USD) for opening the position (0.06%) + example: '10.00' + pnlAfterFees: + type: string + description: >- + The position's PNL after fees in the integer format + corresponding to the 6 decimals places used by the + USDC and USDT token mint + example: '10.45' + pnlAfterFeesUsd: + type: string + description: The position's PNL (USD) after fees + example: '10.45' + pnlBeforeFees: + type: string + description: >- + The position's PNL before fees in the integer format + corresponding to the 6 decimals places used by the + USDC and USDT token mint + example: '10.45' + pnlBeforeFeesUsd: + type: string + description: The position's PNL (USD) before fees + example: '10.45' + pnlChangePctAfterFees: + type: string + description: The position's PNL change percentage after fees + pnlChangePctBeforeFees: + type: string + description: The position's PNL change percentage before fees + positionPubkey: + type: string + description: The public key / address for the position + example: 815wh1VLC8D7ZWMa3uB7GgjHFetANuML2dPrJiLV1nVF + side: + type: string + enum: + - long + - short + size: + type: string + description: >- + USD value of the position's trade size (including + leverage) + example: '12345.68' + sizeUsdDelta: + type: string + description: >- + Raw USD value of the position's trade size + (including leverage) + example: '12345.68' + sizeTokenAmount: + type: string + description: >- + Raw token amount for the position's size scaled to + the custody token's mint decimals + example: '250000000' + totalFees: + type: string + description: >- + The total fees for the position in the integer + format corresponding to the 6 decimals places used + by the USDC and USDT token mint. + example: '100000' + totalFeesUsd: + type: string + description: The total fees (USD) for the position. + example: '10.00' + tpslRequests: + type: array + items: + type: object + properties: + desiredMint: + type: string + description: >- + The mint address for the TP position request + account's desired mint + positionRequestPubkey: + type: string + description: >- + The public key / address for the TP position + request account + requestType: + type: string + enum: + - tp + - sl + description: >- + Returns `tp` if it is a take profit request, + `sl` if it is a stop loss request + sizeUsd: + type: string + description: >- + The close size for the TP / SL in integer + format corresponding to the 6 decimals places + used by the USDC and USDT token mint + example: '1234000000' + sizeUsdFormatted: + type: string + description: >- + The formatted close size for the TP / SL in + integer format corresponding to the 6 decimals + places used by the USDC and USDT token mint + example: '12.34' + sizePercentage: + type: string + description: >- + The percentage / ratio TP / SL size to the + position size + example: '12.34' + triggerPrice: + type: + - string + - 'null' + description: >- + The trigger price for the TP / SL request in + integer format corresponding to the 6 decimals + places used by the USDC and USDT token mint + example: '20000000' + triggerPriceUsd: + type: + - string + - 'null' + description: >- + The trigger price (USD) for the TP / SL + request + example: '20000000' + required: + - desiredMint + - positionRequestPubkey + - requestType + - sizeUsd + - sizeUsdFormatted + - sizePercentage + - triggerPrice + - triggerPriceUsd + description: The active TP / SL requests for the position + updatedTime: + type: number + example: 1722851463 + value: + type: string + description: >- + USD value of the currently open position including + fees incurred by opening, closing, and borrowing the + position + example: '120.00' + required: + - borrowFees + - borrowFeesUsd + - closeFees + - closeFeesUsd + - collateral + - collateralUsd + - collateralMint + - createdTime + - entryPrice + - leverage + - liquidationPrice + - marketMint + - markPrice + - openFees + - openFeesUsd + - pnlAfterFees + - pnlAfterFeesUsd + - pnlBeforeFees + - pnlBeforeFeesUsd + - pnlChangePctAfterFees + - pnlChangePctBeforeFees + - positionPubkey + - side + - size + - sizeUsdDelta + - sizeTokenAmount + - totalFees + - totalFeesUsd + - tpslRequests + - updatedTime + - value + count: + type: number + required: + - dataList + - count + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /positions/close-all: + description: >- + Returns an array of serialized transactions to close all open positions + for the given wallet address. + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + walletAddress: + type: string + description: >- + The wallet address / public key for the trader to close all + open positions + required: + - walletAddress + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + serializedTxs: + type: array + items: + type: object + properties: + serializedTxBase64: + type: string + description: >- + The serialized transaction (base64 encoded) + containing the instructions and given parameters for + the close position instruction. The transaction can + be deserialized, signed by the owner of + `walletAddress` and submitted onchain to close the + position. + positionRequestPubkey: + type: string + description: >- + The public key / address for the position request to + close the position. + required: + - serializedTxBase64 + - positionRequestPubkey + description: >- + An array of base64-serialized transactions and the + `positionRequestPubkey` to close all positions. + txMetadata: + type: object + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + close position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed close position transaction. + required: + - blockhash + - lastValidBlockHeight + description: >- + Contains blockhash metadata for the serialized transaction + to submit and confirm the transactions. + required: + - serializedTxs + - txMetadata + description: >- + An array of base64-serialized transactions and transaction + metadata to close all positions. + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /positions/collateral-limits: + description: >- + Returns the minimum and maximum token amounts for collateral deposits, as + well as the maximum token amount for collateral withdrawals. + get: + parameters: + - in: query + name: inputMint + description: >- + The mint address for the input token to deposit as collateral (e.g. + 'So11111111111111111111111111111111111111112' for 'SOL') + schema: + type: string + description: >- + The mint address for the input token to deposit as collateral + (e.g. 'So11111111111111111111111111111111111111112' for 'SOL') + example: So11111111111111111111111111111111111111112 + required: true + - in: query + name: positionPubkey + description: >- + The public key for the open position. Use the `GET positions` + endpoint to fetch the public key for the trader's open positions. + schema: + type: string + description: >- + The public key for the open position. Use the `GET positions` + endpoint to fetch the public key for the trader's open positions. + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + required: true + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + maxCollateralDepositTokenAmount: + type: string + description: >- + The maximum token amount that can be deposited as + collateral for the given input mint token. + maxCollateralDepositUsd: + type: string + description: >- + The maximum amount (USD) that can be deposited as + collateral for the given input mint token. The value is an + integer corresponding to the 6 decimals places used by the + USDC and USDT token mint. + minCollateralDepositTokenAmount: + type: string + description: >- + The minimum token amount that can be deposited as + collateral for the given input mint token. + minCollateralDepositUsd: + type: string + description: >- + The minimum amount (USD) that can be deposited as + collateral for the given input mint token. The value is an + integer corresponding to the 6 decimals places used by the + USDC and USDT token mint. + maxCollateralWithdrawalTokenAmount: + type: string + description: >- + The maximum collateral token amount that can be withdrawed + from the open position. + maxCollateralWithdrawalUsd: + type: string + description: >- + The maximum collateral (USD) that can be withdrawed from + the open position. The value is an integer corresponding + to the 6 decimals places used by the USDC and USDT token + mint. + minCollateralWithdrawalTokenAmount: + type: string + description: >- + The minimum collateral token amount that can be withdrawed + from the open position. + minCollateralWithdrawalUsd: + type: string + description: >- + The minimum collateral (USD) that can be withdrawed from + the open position. The value is an integer corresponding + to the 6 decimals places used by the USDC and USDT token + mint. + required: + - maxCollateralDepositTokenAmount + - maxCollateralDepositUsd + - minCollateralDepositTokenAmount + - minCollateralDepositUsd + - maxCollateralWithdrawalTokenAmount + - maxCollateralWithdrawalUsd + - minCollateralWithdrawalTokenAmount + - minCollateralWithdrawalUsd + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /positions/decrease: + description: >- + Uses the `decreasePositionParams` object from calling `GET + /positions/decrease/quote` and returns a base64-serialized transaction for + the request, the position request PDA, and the position PDA that acts as + the unique identifier for the position. + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + collateralUsdDelta: + type: string + description: >- + The amount of collateral to withdraw in USD from the + position. Must be an integer representing the USD amount + multiplied by 10^6 (1 million) to align with the 6 decimal + places used for USDC/USDT tokens on-chain. For example, to + decrease by $10 USD, set 'collateralUsdDelta' to 10000000; + for $20.50 USD, set 'collateralUsdDelta' to 20500000. + example: '10000000' + desiredMint: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + - Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB + description: >- + The mint address for the token to be used when withdrawing + collateral or closing position. + example: So11111111111111111111111111111111111111112 + entirePosition: + type: boolean + default: false + description: >- + When set to `true`, this will close the position and + transfer the remaining collateral and realised profits (if + the position is profitable) to the trader. + example: false + maxSlippageBps: + type: string + default: '200' + description: >- + The maximum slippage in (BPS) for the token swap (if + required) and the token price when executing the increase + position trade + example: '100' + positionPubkey: + type: string + description: >- + The public key for the open position. Use the `GET + positions` endpoint to fetch the public key for the trader's + open positions. + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + sizeUsdDelta: + type: string + description: >- + The amount in USD to decrease the position size by. Must be + an integer representing the USD amount multiplied by 10^6 (1 + million) to align with the 6 decimal places used for + USDC/USDT tokens on-chain. For example, to decrease by $10 + USD, set 'sizeUsdDelta' to 10000000; for $20.50 USD, set + 'sizeUsdDelta' to 20500000. + example: '10000000' + required: + - collateralUsdDelta + - desiredMint + - positionPubkey + - sizeUsdDelta + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + positionPubkey: + type: string + description: >- + The unique identifier (i.e. a program derived address) for + the position account. Use this address to find the + position account onchain. + positionRequestPubkey: + type: + - string + - 'null' + description: >- + The unique identifier (i.e. a program derived address) for + the position request. Use this address to find the + position request account onchain. Returns null if + `requireKeeperSignature` is true. + quote: + type: object + properties: + closeFeeUsd: + type: string + description: >- + The base close fee (USD) for closing the position or + withdrawing collateral from the position. + example: '0.0063' + feeUsd: + type: string + description: >- + The total fee (USD) for closing or withdrawing + collateral from the position including base fees, + borrowing fees, and price impact fees + example: '0.0063' + leverage: + type: string + description: >- + The leverage amount for the position after withdrawing + collateral + example: '2.99' + liquidationPriceUsd: + type: string + description: >- + The liquidation price (USD) for the position after + withdrawing collateral + example: '13.24' + outstandingBorrowFeeUsd: + type: string + description: >- + The outstanding borrow fees due / to be paid on + closing the position + example: '0.1000' + pnlAfterFees: + type: string + description: >- + The position's PNL after fees in the integer format + corresponding to the 6 decimals places used by the + USDC and USDT token mint + example: '1045000' + pnlAfterFeesPercent: + type: string + description: >- + The PNL change (%) from closing the position after + fees. + example: '-20.24' + pnlAfterFeesUsd: + type: string + description: The position's PNL (USD) after fees + example: '10.45' + pnlBeforeFees: + type: string + description: >- + The position's PNL before fees in the integer format + corresponding to the 6 decimals places used by the + USDC and USDT token mint + example: '1045000' + pnlBeforeFeesPercent: + type: string + description: >- + The PNL change (%) from closing the position before + fees. + example: '20.24' + pnlBeforeFeesUsd: + type: string + description: The position's PNL (USD) before fees + example: '10.45' + positionCollateralSizeUsd: + type: string + description: >- + The total position collateral size (USD) after + withdrawing + example: '1124.45' + positionSizeUsd: + type: string + description: >- + The total position size (USD) including leverage after + withdrawing + example: '1124.45' + priceImpactFeeBps: + type: string + description: >- + The price impact fee bps for closing the position + based on the position size. For more info on how the + price impact fee calculation works: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '1.3301' + priceImpactFeeUsd: + type: string + description: >- + The price impact fee (USD) for closing the position + based on the position size. For more info on how the + price impact fee calculation works: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '1.3301' + side: + type: string + enum: + - long + - short + description: The position side + example: long + transferTokenMint: + type: string + description: >- + The mint address for the token used to transfer the + collateral withdrawal or closing position amount + example: So11111111111111111111111111111111111111112 + transferAmountToken: + type: string + description: >- + The collateral token amount to transfer to the owner + after withdrawing collateral or closing the position + example: '100000000' + transferAmountUsd: + type: string + description: >- + The collateral token amount in USD to transfer to the + owner withdrawing collateral or closing the position + example: '1099.95' + required: + - closeFeeUsd + - feeUsd + - leverage + - liquidationPriceUsd + - outstandingBorrowFeeUsd + - pnlAfterFees + - pnlAfterFeesPercent + - pnlAfterFeesUsd + - pnlBeforeFees + - pnlBeforeFeesPercent + - pnlBeforeFeesUsd + - positionCollateralSizeUsd + - positionSizeUsd + - priceImpactFeeBps + - priceImpactFeeUsd + - side + - transferTokenMint + - transferAmountToken + - transferAmountUsd + description: >- + The 'quote' object contains the position's updated values + (leverage, size, collateral size, etc.) after withdrawing + collateral. + requireKeeperSignature: + type: + - boolean + - 'null' + description: '' + serializedTxBase64: + type: string + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the decrease + position request. The transaction can be deserialized, + signed by the owner of `walletAddress` and submitted + onchain to execute the decrease position request + txMetadata: + type: object + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + decrease position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed decrease position transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: Contains relevant metadata for the serialized transaction. + required: + - positionPubkey + - quote + - serializedTxBase64 + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /positions/increase: + description: >- + Uses the `increasePositionParams` object from calling `GET + /positions/increase/quote` and returns a base64-serialized transaction for + the request, the position request PDA, and the position PDA that acts as + the unique identifier for the position. + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + collateralMint: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + - Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB + description: >- + The mint address for the collateral token (e.g. + 'So11111111111111111111111111111111111111112' for 'SOL'). + 'collateralMint' must be the same as 'marketMint' for long + positions, or USDC + (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v) for short + positions. + example: So11111111111111111111111111111111111111112 + collateralTokenDelta: + type: string + description: >- + The amount of tokens for the input mint to open the position + or deposit collateral. NOTE: The token amount needs to be an + integer and must conform to the token mint decimals + specified onchain. For example, to deposit 1 'SOL', the + 'collateralTokenDelta' value would be equal to '1000000000' + example: '1000000000' + inputMint: + type: string + description: >- + The mint address for the input token (e.g. + 'So11111111111111111111111111111111111111112' for 'SOL') + example: So11111111111111111111111111111111111111112 + leverage: + type: string + description: >- + Leverage of the increase position. Either provide leverage + or sizeUsdDelta. Max leverage for SOL is 100. Max leverage + for BTC / ETH is 150 + example: '10' + marketMint: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + description: >- + The asset or market to trade against. Required when opening + a new position. 'SOL' = + 'So11111111111111111111111111111111111111112', 'ETH' = + '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs', 'BTC' = + '3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh' + example: So11111111111111111111111111111111111111112 + maxSlippageBps: + type: string + description: >- + The maximum slippage in (BPS) for the custody token price + when executing the decrease position trade + example: '100' + includeSerializedTx: + type: boolean + default: true + description: >- + Sets whether to return a serialized transaction + (`serializedTxBase64`) in the response + side: + type: string + enum: + - long + - short + description: Required when opening a new position + sizeUsdDelta: + type: string + description: >- + The amount in USD to increase the position size by. Must be + an integer representing the USD amount multiplied by 10^6 (1 + million) to align with the 6 decimal places used for + USDC/USDT tokens on-chain. For example, to increase the + position size by $10 USD, set 'sizeUsdDelta' to 10000000; + for $0.50 USD, set 'sizeUsdDelta' to 500000. Either provide + leverage or sizeUsdDelta. + example: '10000000' + transactionType: + type: string + enum: + - legacy + - mixed + - instant + default: mixed + description: >- + Sets the type of serialized transaction to execute the + action. If the transaction type is `legacy`, the transaction + must be submitted by the client itself through the RPC. If + the transaction type is `instant`, the transaction must be + sent to the `POST /transaction/execute` endpoint. If the + transaction type is `mixed`, the `transactionType` returned + in the response will be either `legacy` or `instant`. + tpsl: + type: + - array + - 'null' + items: + type: object + properties: + desiredMint: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + - Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB + description: >- + The mint address for the token used when withdrawing + collateral or closing position when the TPSL is + executed. + triggerPrice: + type: string + description: >- + Trigger price at which the TP / SL request will be + executed. The value must be an integer corresponding + to 6 decimal places. For example, to set a trigger + price of $20, pass in 20000000 + example: '20000000' + requestType: + type: string + enum: + - tp + - sl + description: >- + Pass in `tp` to set a take profit request or `sl` to + set a stop loss request + required: + - desiredMint + - triggerPrice + - requestType + description: TPSL requests to set + walletAddress: + type: string + description: >- + The wallet address / public key for the trader, Required + when opening a new position. + required: + - collateralMint + - collateralTokenDelta + - inputMint + - marketMint + - maxSlippageBps + - side + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + positionPubkey: + type: + - string + - 'null' + description: >- + The unique identifier (i.e. a program derived address) for + the position account. Use this address to find the + position account onchain. + positionRequestPubkey: + type: + - string + - 'null' + description: >- + The unique identifier (i.e. a program derived address) for + the position request. Use this address to find the + position request account onchain + tpslRequests: + type: array + items: + type: object + properties: + estimatedPnlUsd: + type: string + description: The estimated PNL (USD) for the TPSL request + estimatedPnlPercent: + type: string + description: The estimated PNL percentage for the TPSL request + hasProfit: + type: boolean + description: Whether the TPSL request has profit + requestType: + type: string + enum: + - tp + - sl + description: The type of TPSL request + positionRequestPubkey: + type: string + description: >- + The unique identifier (i.e. a program derived + address) for the position request. Use this address + to find the position request account onchain + required: + - estimatedPnlUsd + - estimatedPnlPercent + - hasProfit + - requestType + - positionRequestPubkey + description: >- + TPSL requests created with the increase position. Only + returned when TPSL is requested. + quote: + type: object + properties: + collateralLessThanFees: + type: boolean + description: >- + When true, this means the trade's collateral is not + enough to cover the fees required to execute the + trade, causing the trade size to be zero (equivalent + to a collateral deposit). + example: true + entryPriceUsd: + type: string + description: The entry price (USD) for the position + example: '2.99' + leverage: + type: string + description: The leverage amount for the position + example: '2.99' + liquidationPriceUsd: + type: string + description: The liquidation price (USD) for the position + example: '13.24' + openFeeUsd: + type: string + description: >- + The total fee (USD) for opening the position or + depositing collateral to the position including base + fees, borrowing fees, and price impact fees + example: '0.0063' + outstandingBorrowFeeUsd: + type: string + description: >- + The outstanding borrow fees due / to be paid on + depositing collateral to the position + example: '0.1000' + positionCollateralSizeUsd: + type: string + description: The total position collateral size (USD) + example: '1124.45' + positionSizeTokenAmount: + type: string + description: >- + The total position size in the underlying collateral + token's token amount including leverage + example: '112445000' + positionSizeUsd: + type: string + description: The total position size (USD) including leverage + example: '1124.45' + priceImpactFeeBps: + type: string + description: >- + The price impact fee bps for opening the position + based on the position size. For more info on how the + price impact fee calculation works: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '1.3301' + priceImpactFeeUsd: + type: string + description: >- + The price impact fee (USD) for opening the position + based on the position size. For more info on how the + price impact fee calculation works: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '1.3301' + quoteOutAmount: + type: + - string + - 'null' + description: >- + The output amount from Jupiter's quote for the + collateral token if a token swap is required (i.e. if + the `inputMint` is not the same as the collateral + mint) + quotePriceSlippagePct: + type: + - string + - 'null' + description: >- + The price slippage percentage from Jupiter's quote if + a token swap is required (i.e. if the `inputMint` is + not the same as the collateral mint) + quoteSlippageBps: + type: + - string + - 'null' + description: >- + The slippage (BPS) from Jupiter's quote if a token + swap is required (i.e. if the `inputMint` is not the + same as the collateral mint) + side: + type: string + enum: + - long + - short + description: The position side + example: long + sizeTokenDelta: + type: string + description: >- + The change in the position's size in the token amount + for the position's collateral token. + example: '14420000' + expectedSizeUsdDelta: + type: string + description: >- + The expected change in the position's size in USD + before accounting for fees. + example: '112445' + expectedSizeUsdDeltaDiffPct: + type: string + description: >- + The difference between the expected change in the + position's size in USD before fees and the actual + change in the position's size in USD. + example: '14.45' + sizeUsdDelta: + type: string + description: >- + The actual change in the position's size in USD with + formatting. + example: '1124.45' + sizeUsdDeltaRaw: + type: string + description: The actual change in the position's size in USD. + example: '112445' + required: + - collateralLessThanFees + - entryPriceUsd + - leverage + - liquidationPriceUsd + - openFeeUsd + - outstandingBorrowFeeUsd + - positionCollateralSizeUsd + - positionSizeTokenAmount + - positionSizeUsd + - priceImpactFeeBps + - priceImpactFeeUsd + - quoteOutAmount + - quotePriceSlippagePct + - quoteSlippageBps + - side + - sizeTokenDelta + - expectedSizeUsdDelta + - expectedSizeUsdDeltaDiffPct + - sizeUsdDelta + - sizeUsdDeltaRaw + requireKeeperSignature: + type: boolean + description: DEPRECATED + serializedTxBase64: + type: + - string + - 'null' + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the increase + position request. The transaction can be deserialized, + signed by the owner of `walletAddress` and submitted + onchain to execute the increase position request + transactionType: + type: string + enum: + - mixed + - instant + - legacy + description: >- + Returns the type of serialized transaction to execute the + action. If the transaction type is `legacy`, the + transaction must be submitted by the client itself through + the RPC. If the transaction type is `instant`, the + transaction must be sent to the `POST + /transaction/execute` endpoint. + txMetadata: + type: + - object + - 'null' + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + increase position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed increase position transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: >- + Contains relevant metadata for the serialized transaction. + Null if no wallet address passed in. + required: + - positionPubkey + - positionRequestPubkey + - tpslRequests + - quote + - requireKeeperSignature + - serializedTxBase64 + - transactionType + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /pool-info: + description: Fetches the perpetuals base pool config info for the given market + get: + parameters: + - in: query + name: mint + description: The token mint address for the perpetuals market + schema: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + description: The token mint address for the perpetuals market + required: true + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + longAvailableLiquidity: + type: string + description: >- + USD value of the available liquidity for long positions + for the market + example: '2500000' + longBorrowRatePercent: + type: string + description: >- + Base borrow rate (%) for long positions. More info on how + the borrow rate is calculated here: + https://station.jup.ag/guides/perpetual-exchange/how-it-works#hourly-borrow-rate + example: '0.0026' + longUtilizationPercent: + type: string + description: Utilization rate (%) for long positions + example: '26.00' + shortAvailableLiquidity: + type: string + description: >- + USD value of the available liquidity for short positions + for the market + example: '2500000' + shortBorrowRatePercent: + type: string + description: >- + Base borrow rate (%) for short positions. More info on how + the borrow rate is calculated here: + https://station.jup.ag/guides/perpetual-exchange/how-it-works#hourly-borrow-rate + example: '0.0026' + shortUtilizationPercent: + type: string + description: Utilization rate (%) for short positions + example: '26.00' + openFeePercent: + type: string + description: Base open fee (%) for the market + example: '0.06' + maxRequestExecutionSec: + type: string + description: >- + The maximum duration that a position request can be active + (in seconds) before it is considered invalid. + maxPriceImpactFeePercent: + type: string + description: The maximum price impact fee (%) + required: + - longAvailableLiquidity + - longBorrowRatePercent + - longUtilizationPercent + - shortAvailableLiquidity + - shortBorrowRatePercent + - shortUtilizationPercent + - openFeePercent + - maxRequestExecutionSec + - maxPriceImpactFeePercent + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /jlp-info: + description: Fetches the JLP token info + get: + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + aumUsd: + type: string + description: Total AUM in USD (raw value) + example: '123456789000000' + aumUsdFormatted: + type: string + description: Total AUM in USD (formatted) + example: '123,456.79' + aumLimitUsd: + type: string + description: AUM limit in USD (raw value) + example: '500000000000000' + aumLimitUsdFormatted: + type: string + description: AUM limit in USD (formatted) + example: '500,000' + jlpPriceUsd: + type: string + description: JLP price in USD (raw value) + example: '1234567' + jlpPriceUsdFormatted: + type: string + description: JLP price in USD (formatted) + example: '1.2346' + jlpTotalSupply: + type: string + description: Total JLP token supply + example: '100000000000' + jlpTotalSupplyFormatted: + type: string + description: Total JLP token supply (formatted) + example: '100,000' + jlpAprBps: + type: string + description: JLP APR in BPS + example: '100' + jlpAprPct: + type: string + description: JLP APR in percentage + example: '10.00' + jlpApyBps: + type: string + description: JLP APY in BPS + example: '100' + jlpApyPct: + type: string + description: JLP APY in percentage + example: '10.00' + jlpAprLastUpdatedTimestamp: + type: string + description: JLP APR last updated UNIX timestamp + example: '1715404800' + jlpRealizedFeeUsd: + type: string + description: >- + JLP realized fee in USD since the last APR / APY + calculation + example: '100000000' + custodies: + type: array + items: + type: object + properties: + pubkey: + type: string + description: Custody public key + example: '11111111111111111111111111111111' + symbol: + type: string + description: Token symbol + example: SOL + name: + type: string + description: Token name + example: Wrapped SOL + mint: + type: string + description: Token mint + example: So11111111111111111111111111111111111111112 + aumUsd: + type: string + description: Custody AUM in USD (raw value) + example: '12345678900000' + aumUsdFormatted: + type: string + description: Custody AUM in USD (formatted) + example: '123456.79' + aumTokenAmount: + type: string + description: Custody AUM in token amount + example: '123456789' + aumTokenAmountFormatted: + type: string + description: Custody AUM in token amount (formatted) + example: '123,456.79' + currentWeightagePct: + type: string + description: Current weight percentage + example: '25.50' + targetWeightagePct: + type: string + description: Target weight percentage + example: '30.00' + utilizationPct: + type: string + description: Utilization percentage + example: '45.20' + owned: + type: string + description: >- + Tokens owned by the JLP pool scaled to the token's + mint decimals + example: '123456789' + locked: + type: string + description: >- + Tokens locked by the JLP pool for trader's + collateral and leverage scaled to the token's mint + decimals + example: '123456789' + guaranteedUsd: + type: string + description: >- + Current long sizes for the token scaled to the USDC + decimals (6) + example: '123456789' + globalShortSizes: + type: string + description: >- + Current short sizes for the token scaled to the USDC + decimals (6) + example: '123456789' + globalShortAveragePrice: + type: string + description: >- + Average price of all short positions for the token + scaled to the USDC decimals (6) + example: '123456789' + shortPnlDelta: + type: string + description: Short PnL delta scaled to the USDC decimals (6) + example: '123456789' + shortTradersHasProfit: + type: boolean + description: >- + Boolean to indicate whether short traders are in + profit + example: true + totalStakedAmountLamports: + type: string + description: Total staked SOL lamports (zero for other assets) + example: '123456789' + totalStakedAmountUsd: + type: string + description: >- + Total staked SOL lamports in USD scaled to 6 decimal + places as per the USDC mint (zero for other assets) + example: '123456789' + totalStakedAmountUsdFormatted: + type: string + description: >- + Formatted total staked SOL lamports in USD scaled to + 6 decimal places as per the USDC mint (zero for + other assets) + example: '123456789' + required: + - pubkey + - symbol + - name + - mint + - aumUsd + - aumUsdFormatted + - aumTokenAmount + - aumTokenAmountFormatted + - currentWeightagePct + - targetWeightagePct + - utilizationPct + - owned + - locked + - guaranteedUsd + - globalShortSizes + - globalShortAveragePrice + - shortPnlDelta + - shortTradersHasProfit + - totalStakedAmountLamports + - totalStakedAmountUsd + - totalStakedAmountUsdFormatted + description: List of custody information + required: + - aumUsd + - aumUsdFormatted + - aumLimitUsd + - aumLimitUsdFormatted + - jlpPriceUsd + - jlpPriceUsdFormatted + - jlpTotalSupply + - jlpTotalSupplyFormatted + - jlpAprBps + - jlpAprPct + - jlpApyBps + - jlpApyPct + - jlpAprLastUpdatedTimestamp + - jlpRealizedFeeUsd + - custodies + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /trades: + description: Fetches the trade history for the given wallet address + get: + parameters: + - in: query + name: action + schema: + type: string + enum: + - Increase + - Decrease + - in: query + name: createdAtAfter + description: >- + Fetches trades with a 'createdAt' date that is greater or equal to + the given 'createdAtAfter' UNIX timestamp' + schema: + type: string + description: >- + Fetches trades with a 'createdAt' date that is greater or equal to + the given 'createdAtAfter' UNIX timestamp' + - in: query + name: createdAtBefore + description: >- + Fetches trades with a 'createdAt' date that is less than the given + 'createdAtBefore' UNIX timestamp' + schema: + type: string + description: >- + Fetches trades with a 'createdAt' date that is less than the given + 'createdAtBefore' UNIX timestamp' + - in: query + name: end + description: >- + The index of the last row to retrieve. This parameter specifies the + ending point for fetching rows from the dataset. It is exclusive, + meaning that the row at this index will not be included in the + results. + schema: + type: number + default: 20 + description: >- + The index of the last row to retrieve. This parameter specifies + the ending point for fetching rows from the dataset. It is + exclusive, meaning that the row at this index will not be included + in the results. + - in: query + name: mint + description: Mint address for the underlying position of the trade + schema: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + description: Mint address for the underlying position of the trade + - in: query + name: side + schema: + type: string + enum: + - long + - short + - in: query + name: start + description: >- + The index of the first row to retrieve. This parameter specifies the + starting point for fetching rows from the dataset. It is inclusive, + meaning that the row at this index will be included in the results + schema: + type: number + default: 0 + description: >- + The index of the first row to retrieve. This parameter specifies + the starting point for fetching rows from the dataset. It is + inclusive, meaning that the row at this index will be included in + the results + - in: query + name: walletAddress + description: Public key for the wallet to fetch trades + schema: + type: string + description: Public key for the wallet to fetch trades + required: true + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + count: + type: number + dataList: + type: array + items: + type: object + properties: + action: + type: string + enum: + - Increase + - Decrease + collateralUsdDelta: + type: string + description: >- + The collateral delta / change value (USD) for the + trade. `collateralUsdDelta` is negative for + collateral deposits and positive for collateral + withdrawals + example: '250.00' + createdTime: + type: number + description: UNIX timestamp of when the trade was created + example: 1722851463 + baseFee: + type: string + description: USD value of the base open / close fee for the trade + example: '0.45' + borrowFee: + type: string + description: USD value of the borrow fee for the trade + example: '0.45' + liquidationFee: + type: string + description: >- + USD value of the liquidation penalty for the + liquidation + example: '0.45' + priceImpactFee: + type: string + description: USD value of the price impact fee for the trade + example: '0.45' + fee: + type: string + description: >- + USD value of the fees paid (including the + liquidation penalty) for the trade + example: '0.45' + mint: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + description: >- + Mint address for the underlying position of the + trade + orderType: + type: string + enum: + - Market + - Trigger + - Liquidation + description: >- + 'Market' orders are orders placed by the trader. + 'Trigger' orders are orders executed by the keeper + for TP/SL requests. 'Liquidation' orders are also + executed by keeper when a position reaches its + liquidation price + pnl: + type: + - string + - 'null' + description: >- + USD value of the trade profit / loss. The PNL value + shown is before fees (i.e. it does not minus + opening, closing, borrowing, and price impact fees). + 'pnlUsd' is null for collateral deposits and + withdrawals as the realised PNL is unchanged + example: '24.13' + pnlPercentage: + type: + - string + - 'null' + description: >- + PNL percentage of the trade profit / loss. The PNL + percentage shown is before fees (i.e. it does not + minus opening, closing, borrowing, and price impact + fees). 'pnlPercentage' is null for collateral + deposits and withdrawals as the realised PNL is + unchanged + example: '24.13' + positionName: + type: string + enum: + - SOL-PERP + - ETH-PERP + - BTC-PERP + price: + type: string + description: USD value of the position's entry price + example: '123.45' + side: + type: string + enum: + - long + - short + size: + type: string + description: >- + USD value of the position's trade size (including + leverage) + example: '12345.68' + txHash: + type: string + description: Transaction ID for the trade + example: >- + 4sjjb5kKAWAtXg1MQausgyqDx1Q5mU79a6EigxjjLYmCqBrNUE123XuoKr7Qir6ahBbLoSLLzT8gznxC2cgss5gR + updatedTime: + type: number + example: 1722851463 + required: + - action + - collateralUsdDelta + - createdTime + - baseFee + - borrowFee + - liquidationFee + - priceImpactFee + - fee + - mint + - orderType + - positionName + - price + - side + - size + - txHash + - updatedTime + required: + - count + - dataList + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /tpsl: + description: Returns a serialized transaction to create a TP/SL + delete: + requestBody: + content: + application/json: + schema: + type: object + properties: + positionRequestPubkey: + type: string + description: The public key for the TP / SL request + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + required: + - positionRequestPubkey + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + requireKeeperSignature: + type: boolean + description: >- + When `requireKeeperSignature` is true, the transaction + must be signed, serialized, and sent to the the `POST + /transaction/execute` endpoint to execute the transaction. + When `requireKeeperSignature` is `false`, the transaction + can be submitted through the `sendTransaction` RPC call as + usual + serializedTxBase64: + type: string + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the decrease + position request. The transaction can be deserialized, + signed by the owner of `walletAddress` and submitted + onchain to execute the decrease position request + transactionType: + type: string + enum: + - legacy + description: >- + Returns the type of serialized transaction to execute the + action. If the transaction type is `legacy`, the + transaction must be submitted by the client itself through + the RPC. If the transaction type is `instant`, the + transaction must be sent to the `POST + /transaction/execute` endpoint. + txMetadata: + type: object + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + decrease position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed decrease position transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: Contains relevant metadata for the serialized transaction. + required: + - requireKeeperSignature + - serializedTxBase64 + - transactionType + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + owner: + type: string + description: The public key for owner of the position. + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + positionPubkey: + type: string + description: >- + The public key for the open position. Use the `GET + positions` endpoint to fetch the public key for the trader's + open positions. + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + desiredMint: + type: + - string + - 'null' + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + - Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB + description: >- + The mint address for the token used when withdrawing + collateral or closing position when the TPSL is executed. + sizeUsdDelta: + type: + - string + - 'null' + description: >- + The amount in USD to decrease the position size by. Must be + an integer representing the USD amount multiplied by 10^6 (1 + million) to align with the 6 decimal places used for the + USDC mint on-chain. For example, to decrease by $10 USD, set + 'sizeUsdDelta' to 10000000; for $20.50 USD, set + 'sizeUsdDelta' to 20500000. + example: '10000000' + triggerPrice: + type: + - string + - 'null' + description: >- + Trigger price at which the TP / SL request will be executed. + The value must be an integer corresponding to 6 decimal + places. For example, to set a trigger price of $20, pass in + 20000000 + example: '20000000' + requestType: + type: + - string + - 'null' + enum: + - tp + - sl + description: >- + Pass in `tp` to set a take profit request or `sl` to set a + stop loss request + transactionType: + type: string + enum: + - legacy + - mixed + - instant + default: mixed + description: >- + Sets the type of serialized transaction to execute the + action. If the transaction type is `legacy`, the transaction + must be submitted by the client itself through the RPC. If + the transaction type is `instant`, the transaction must be + sent to the `POST /transaction/execute` endpoint. If the + transaction type is `mixed`, the `transactionType` returned + in the response will be either `legacy` or `instant`. + tpsl: + type: + - array + - 'null' + items: + type: object + properties: + desiredMint: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + - Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB + description: >- + The mint address for the token used when withdrawing + collateral or closing position when the TPSL is + executed. + entirePosition: + type: boolean + default: false + description: >- + Pass in `true` to close the entire position or `false` + to close a portion of the position (partial TPSL) + example: false + sizeUsdDelta: + type: string + description: >- + The amount in USD to decrease the position size by. + Must be an integer representing the USD amount + multiplied by 10^6 (1 million) to align with the 6 + decimal places used for the USDC mint on-chain. For + example, to decrease by $10 USD, set 'sizeUsdDelta' to + 10000000; for $20.50 USD, set 'sizeUsdDelta' to + 20500000. + example: '10000000' + triggerPrice: + type: string + description: >- + Trigger price at which the TP / SL request will be + executed. The value must be an integer corresponding + to 6 decimal places. For example, to set a trigger + price of $20, pass in 20000000 + example: '20000000' + requestType: + type: string + enum: + - tp + - sl + description: >- + Pass in `tp` to set a take profit request or `sl` to + set a stop loss request + required: + - desiredMint + - sizeUsdDelta + - triggerPrice + - requestType + description: TPSL requests to set + required: + - owner + - positionPubkey + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + tpslPubkeys: + type: array + items: + type: string + description: The position request account pubkeys for the TP / SL + requireKeeperSignature: + type: boolean + description: >- + When `requireKeeperSignature` is true, the transaction + must be signed, serialized, and sent to the the `POST + /transaction/execute` endpoint to execute the transaction. + When `requireKeeperSignature` is `false`, the transaction + can be submitted through the `sendTransaction` RPC call as + usual + serializedTxBase64: + type: string + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the decrease + position request. The transaction can be deserialized, + signed by the owner of `walletAddress` and submitted + onchain to execute the decrease position request + transactionType: + type: string + enum: + - legacy + - instant + description: >- + Returns the type of serialized transaction to execute the + action. If the transaction type is `legacy`, the + transaction must be submitted by the client itself through + the RPC. If the transaction type is `instant`, the + transaction must be sent to the `POST + /transaction/execute` endpoint. + txMetadata: + type: object + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + decrease position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed decrease position transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: Contains relevant metadata for the serialized transaction. + required: + - tpslPubkeys + - requireKeeperSignature + - serializedTxBase64 + - transactionType + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + patch: + requestBody: + content: + application/json: + schema: + type: object + properties: + positionRequestPubkey: + type: string + description: The public key for the TP / SL request + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + triggerPrice: + type: string + description: >- + Trigger price at which the TP / SL request will be executed. + The value must be an integer corresponding to 6 decimal + places. For example, to set a trigger price of $20, pass in + 20000000 + example: '20000000' + transactionType: + type: string + enum: + - legacy + - mixed + - instant + default: mixed + description: >- + Sets the type of serialized transaction to execute the + action. If the transaction type is `legacy`, the transaction + must be submitted by the client itself through the RPC. If + the transaction type is `instant`, the transaction must be + sent to the `POST /transaction/execute` endpoint. If the + transaction type is `mixed`, the `transactionType` returned + in the response will be either `legacy` or `instant`. + required: + - positionRequestPubkey + - triggerPrice + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + requireKeeperSignature: + type: boolean + description: >- + When `requireKeeperSignature` is true, the transaction + must be signed, serialized, and sent to the the `POST + /transaction/execute` endpoint to execute the transaction. + When `requireKeeperSignature` is `false`, the transaction + can be submitted through the `sendTransaction` RPC call as + usual + serializedTxBase64: + type: string + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the decrease + position request. The transaction can be deserialized, + signed by the owner of `walletAddress` and submitted + onchain to execute the decrease position request + transactionType: + type: string + enum: + - legacy + - instant + description: >- + Returns the type of serialized transaction to execute the + action. If the transaction type is `legacy`, the + transaction must be submitted by the client itself through + the RPC. If the transaction type is `instant`, the + transaction must be sent to the `POST + /transaction/execute` endpoint. + txMetadata: + type: object + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + decrease position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed decrease position transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: Contains relevant metadata for the serialized transaction. + required: + - requireKeeperSignature + - serializedTxBase64 + - transactionType + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /lending/deposit-borrow: + description: Endpoint to deposit JLP and borrow USDC + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + depositTokenAmount: + type: string + description: >- + JLP token amount to deposit based on the JLP mint decimals + (6)` + borrowMint: + type: string + enum: + - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + description: Mint address for the borrow token + default: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + borrowTokenAmount: + type: string + description: >- + Token amount for the borrow based on the mint decimals for + the borrow token defined in `borrowMint` + walletAddress: + type: string + description: Public key for the wallet to deposit / borrow + required: + - depositTokenAmount + - borrowTokenAmount + - walletAddress + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + borrowSizeUsd: + type: string + description: >- + The borrowed amount (including interest) in USD formatted + to 6 decimals as per the USDC mint + borrowSizeTokenAmount: + type: string + description: >- + The borrowed amount (including interest) in the token + amount formatted to the borrowed token mint decimals + borrowTokenMint: + type: string + description: The mint address for the borrowed token + collateralTokenAmount: + type: string + description: Locked JLP token amount as collateral + collateralTokenUsd: + type: string + description: >- + Locked JLP token amount as collateral in USD formatted to + 6 decimals as per the USDC mint + maxBorrowTokenAmount: + type: string + description: >- + Maximum borrow amount in the token amount formatted to the + borrowed token mint decimals + maxBorrowTokenAmountBeforeBorrow: + type: string + description: >- + Maximum borrow amount in the token amount formatted to the + borrowed token mint decimals after deposit + maxBorrowUsd: + type: string + description: >- + Maximum borrow amount in USD formatted to 6 decimals as + per the USDC mint + maxWithdrawUsd: + type: string + description: >- + The maximum withdrawable amount in USD formatted to 6 + decimals as per the USDC mint + maxWithdrawTokenAmount: + type: string + description: The maximum withdrawable JLP token amount + maxRepayTokenAmount: + type: string + description: The maximum repayable USDC token amount for this position + liquidationPriceUsd: + type: string + description: >- + The JLP price at which the borrow position will be + liquidated in the token amount + ltvBps: + type: string + description: >- + LTV (loan-to-value) in basis points. A higher LTV express + a higher risk of liquidation + ltvPercentage: + type: string + description: >- + LTV (loan-to-value) percentage. A higher LTV express a + higher risk of liquidation + positionPubkey: + type: string + description: Pubkey for the borrow lending position + serializedTxBase64: + type: + - string + - 'null' + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the borrow / deposit + request. The transaction can be deserialized, signed by + the owner of `walletAddress` and submitted onchain. + requireKeeperSignature: + type: boolean + description: Whether the transaction requires a keeper signature + transactionType: + type: string + enum: + - legacy + - instant + description: The type of transaction + txMetadata: + type: + - object + - 'null' + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the + transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: >- + Contains relevant metadata for the serialized transaction. + Null if no wallet address passed in. + required: + - borrowSizeUsd + - borrowSizeTokenAmount + - borrowTokenMint + - collateralTokenAmount + - collateralTokenUsd + - maxBorrowTokenAmount + - maxBorrowTokenAmountBeforeBorrow + - maxBorrowUsd + - maxWithdrawUsd + - maxWithdrawTokenAmount + - maxRepayTokenAmount + - liquidationPriceUsd + - ltvBps + - ltvPercentage + - positionPubkey + - serializedTxBase64 + - requireKeeperSignature + - transactionType + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /lending/pay-withdraw: + description: Endpoint to repay debt with USDC and withdraw JLP + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + repayMint: + type: string + enum: + - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + description: Mint address for the payment token + default: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + repayTokenAmount: + type: string + description: Token amount to pay for the position's debt + withdrawTokenAmount: + type: string + description: The JLP token amount to withdraw from the position + walletAddress: + type: string + description: Public key for the wallet to pay / withdraw + required: + - repayTokenAmount + - withdrawTokenAmount + - walletAddress + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + borrowSizeUsd: + type: string + description: >- + The borrowed amount (including interest) in USD formatted + to 6 decimals as per the USDC mint + borrowSizeTokenAmount: + type: string + description: >- + The borrowed amount (including interest) in the token + amount formatted to the borrowed token mint decimals + borrowTokenMint: + type: string + description: The mint address for the borrowed token + collateralTokenAmount: + type: string + description: Locked JLP token amount as collateral + collateralTokenUsd: + type: string + description: >- + Locked JLP token amount as collateral in USD formatted to + 6 decimals as per the USDC mint + maxBorrowTokenAmount: + type: string + description: >- + Maximum borrow amount in the token amount formatted to the + borrowed token mint decimals + maxBorrowUsd: + type: string + description: >- + Maximum borrow amount in USD formatted to 6 decimals as + per the USDC mint + maxWithdrawUsd: + type: string + description: >- + The maximum withdrawable amount in USD formatted to 6 + decimals as per the USDC mint + maxWithdrawTokenAmount: + type: string + description: The maximum withdrawable JLP token amount + maxWithdrawTokenAmountBeforeWithdraw: + type: string + description: The maximum withdrawable JLP token amount before repaying + maxRepayTokenAmount: + type: string + description: The maximum repayable USDC token amount for this position + liquidationPriceUsd: + type: string + description: >- + The JLP price at which the borrow position will be + liquidated in the token amount + ltvBps: + type: string + description: >- + LTV (loan-to-value) in basis points. A higher LTV express + a higher risk of liquidation + ltvPercentage: + type: string + description: >- + LTV (loan-to-value) percentage. A higher LTV express a + higher risk of liquidation + positionPubkey: + type: string + description: Pubkey for the borrow lending position + serializedTxBase64: + type: + - string + - 'null' + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the borrow / deposit + request. The transaction can be deserialized, signed by + the owner of `walletAddress` and submitted onchain. + txMetadata: + type: + - object + - 'null' + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the + transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: >- + Contains relevant metadata for the serialized transaction. + Null if no wallet address passed in. + requireKeeperSignature: + type: boolean + description: Whether this transaction requires a keeper signature + transactionType: + type: string + const: legacy + description: The type of transaction + required: + - borrowSizeUsd + - borrowSizeTokenAmount + - borrowTokenMint + - collateralTokenAmount + - collateralTokenUsd + - maxBorrowTokenAmount + - maxBorrowUsd + - maxWithdrawUsd + - maxWithdrawTokenAmount + - maxWithdrawTokenAmountBeforeWithdraw + - maxRepayTokenAmount + - liquidationPriceUsd + - ltvBps + - ltvPercentage + - positionPubkey + - serializedTxBase64 + - txMetadata + - requireKeeperSignature + - transactionType + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /lending/positions: + description: Fetches the borrow lending positions for the given wallet address + get: + parameters: + - in: query + name: walletAddress + description: Public key for the wallet to pay / withdraw + schema: + type: string + description: Public key for the wallet to pay / withdraw + required: true + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + dataList: + type: array + items: + type: object + properties: + borrowSizeUsd: + type: string + description: >- + The borrowed amount (including interest) for this + position in USD formatted to 6 decimals as per the + USDC mint + borrowSizeTokenAmount: + type: string + description: >- + The borrowed amount (including interest) for this + position in the token amount formatted to the + borrowed token mint decimals + borrowTokenMint: + type: string + description: The mint address for the borrowed token + maxBorrowTokenAmount: + type: string + description: >- + The maximum borrowable USDC token amount for this + position + maxBorrowUsd: + type: string + description: >- + Maximum borrow amount for this position in USD + formatted to 6 decimals as per the USDC mint + maxWithdrawUsd: + type: string + description: >- + The maximum withdrawable amount for this position in + USD formatted to 6 decimals as per the USDC mint + maxWithdrawTokenAmount: + type: string + description: >- + The maximum withdrawable JLP token amount for this + position + maxRepayTokenAmount: + type: string + description: >- + The maximum repayable USDC token amount for this + position + ltvBps: + type: string + description: >- + LTV (loan-to-value) percentage for the borrow + lending position. A higher LTV express a higher risk + of liquidation for the position + ltvPercentage: + type: string + description: >- + LTV (loan-to-value) percentage for the borrow + lending position. A higher LTV express a higher risk + of liquidation for the position + liquidationPriceUsd: + type: string + description: >- + The JLP price at which the borrow position will be + liquidated in the token amount + collateralTokenAmount: + type: string + description: >- + Locked JLP token amount as collateral in the borrow + lending position + collateralUsd: + type: string + description: >- + Locked JLP token amount as collateral in the borrow + lending position in USD formatted to 6 decimals as + per the USDC mint + positionPubkey: + type: string + description: Pubkey for the borrow lending position + required: + - borrowSizeUsd + - borrowSizeTokenAmount + - borrowTokenMint + - maxBorrowTokenAmount + - maxBorrowUsd + - maxWithdrawUsd + - maxWithdrawTokenAmount + - maxRepayTokenAmount + - ltvBps + - ltvPercentage + - liquidationPriceUsd + - collateralTokenAmount + - collateralUsd + - positionPubkey + count: + type: number + required: + - dataList + - count + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /lending/info: + description: Fetches global stats and info for the borrow lending pool + get: + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + currentJlpPriceUsd: + type: string + description: >- + The current JLP price in USD formatted to 6 decimals as + per the USDC mint + borrowTokenMint: + type: string + description: The mint address for the borrow token + availableLiquidityUsd: + type: string + description: >- + Available liquidity for borrowing in USD formatted to 6 + decimals + availableLiquidityTokenAmount: + type: string + description: >- + Available liquidity for borrowing in token amount + formatted to token decimals + totalSupplyUsd: + type: string + description: Total supply in USD formatted to 6 decimals + totalSupplyTokenAmount: + type: string + description: Total supply in token amount formatted to token decimals + utilizationRateBps: + type: string + description: Current utilization rate in basis points (borrowed/total) + utilizationRatePercentage: + type: string + description: Current utilization rate as a percentage + borrowApr: + type: string + description: Current borrow APR as a percentage + liquidationMarginBps: + type: string + description: Liquidation margin threshold in basis points + liquidationMarginPercentage: + type: string + description: Liquidation margin as a percentage + liquidationPenaltyBps: + type: string + description: Liquidation penalty in basis points + liquidationPenaltyPercentage: + type: string + description: Liquidation penalty as a percentage + maxLtvBps: + type: string + description: Maximum LTV in basis points + maxLtvPercentage: + type: string + description: Maximum LTV as a percentage + required: + - currentJlpPriceUsd + - borrowTokenMint + - availableLiquidityUsd + - availableLiquidityTokenAmount + - totalSupplyUsd + - totalSupplyTokenAmount + - utilizationRateBps + - utilizationRatePercentage + - borrowApr + - liquidationMarginBps + - liquidationMarginPercentage + - liquidationPenaltyBps + - liquidationPenaltyPercentage + - maxLtvBps + - maxLtvPercentage + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /lending/history: + description: Fetches borrow lending history for the given wallet address + get: + parameters: + - in: query + name: walletAddress + description: Filter by wallet address + schema: + type: string + description: Filter by wallet address + - in: query + name: borrowPositionPubkey + description: Filter by specific borrow position pubkey + schema: + type: string + description: Filter by specific borrow position pubkey + - in: query + name: transactionType + description: Filter by transaction type + schema: + type: string + enum: + - DepositCollateral + - WithdrawCollateral + - Borrow + - Repay + - Liquidation + description: Filter by transaction type + - in: query + name: createdAtAfter + description: >- + Fetches transactions with a 'createdAt' date that is greater or + equal to the given 'createdAtAfter' UNIX timestamp + schema: + type: string + description: >- + Fetches transactions with a 'createdAt' date that is greater or + equal to the given 'createdAtAfter' UNIX timestamp + - in: query + name: createdAtBefore + description: >- + Fetches transactions with a 'createdAt' date that is less than the + given 'createdAtBefore' UNIX timestamp + schema: + type: string + description: >- + Fetches transactions with a 'createdAt' date that is less than the + given 'createdAtBefore' UNIX timestamp + - in: query + name: start + description: >- + The index of the first row to retrieve. This parameter specifies the + starting point for fetching rows from the dataset. It is inclusive, + meaning that the row at this index will be included in the results + schema: + type: number + default: 0 + description: >- + The index of the first row to retrieve. This parameter specifies + the starting point for fetching rows from the dataset. It is + inclusive, meaning that the row at this index will be included in + the results + - in: query + name: end + description: >- + The index of the last row to retrieve. This parameter specifies the + ending point for fetching rows from the dataset. It is exclusive, + meaning that the row at this index will not be included in the + results. + schema: + type: number + default: 20 + description: >- + The index of the last row to retrieve. This parameter specifies + the ending point for fetching rows from the dataset. It is + exclusive, meaning that the row at this index will not be included + in the results. + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + dataList: + type: array + items: + type: object + properties: + txHash: + type: string + description: Solana transaction signature + transactionType: + type: string + enum: + - DepositCollateral + - WithdrawCollateral + - Borrow + - Repay + - Liquidation + description: Type of lending transaction + walletAddress: + type: string + description: Wallet address that initiated the transaction + borrowPositionPubkey: + type: string + description: Borrow position account pubkey + createdTime: + type: number + description: UNIX timestamp of when the transaction was created + tokenAmount: + type: string + description: >- + Token amount for the borrow / withdraw / repay / + deposit depending on the transaction type + tokenMint: + type: string + description: >- + Mint address of the token for the borrow / withdraw + / repay / deposit depending on the transaction type + required: + - txHash + - transactionType + - walletAddress + - borrowPositionPubkey + - createdTime + - tokenAmount + - tokenMint + description: List of lending transactions + count: + type: number + description: Total number of transactions matching the filter criteria + required: + - dataList + - count + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /top-traders: + description: Returns traders by top PNL and top volume according to the given period. + get: + parameters: + - in: query + name: marketMint + description: Mint address for the given market to filter top trader data + schema: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + description: Mint address for the given market to filter top trader data + required: true + - in: query + name: year + description: The year for the week to query + schema: + type: string + description: The year for the week to query + required: true + - in: query + name: week + description: The week number (1-53) or "current" for the current week + schema: + anyOf: + - type: string + const: current + - type: string + description: The week number (1-53) or "current" for the current week + required: true + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + marketMint: + type: string + description: The market mint to filter top traders by. + totalVolumeUsd: + type: string + description: The total volume (USD) for the market. + startTimestamp: + type: number + description: >- + The start timestamp for the week (UNIX timestamp in + seconds). + endTimestamp: + type: number + description: >- + The end timestamp for the week (UNIX timestamp in + seconds). + topTradersByPnl: + type: array + items: + type: object + properties: + totalVolumeUsd: + type: string + description: The total volume (USD) for the trader. + totalPnlUsd: + type: string + description: The total PNL (USD) for the trader. + owner: + type: string + description: The wallet address for the trader. + required: + - totalVolumeUsd + - totalPnlUsd + - owner + description: The top 50 traders sorted by PNL in descending order. + topTradersByVolume: + type: array + items: + type: object + properties: + totalVolumeUsd: + type: string + description: The total volume (USD) for the trader. + totalPnlUsd: + type: string + description: The total PNL (USD) for the trader. + owner: + type: string + description: The wallet address for the trader. + required: + - totalVolumeUsd + - totalPnlUsd + - owner + description: The top 50 traders sorted by volume in descending order. + required: + - marketMint + - totalVolumeUsd + - startTimestamp + - endTimestamp + - topTradersByPnl + - topTradersByVolume + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /trader-stats: + description: Returns stats for the given trader + get: + parameters: + - in: query + name: walletAddress + description: The pubkey of trader to get volume data + schema: + type: string + description: The pubkey of trader to get volume data + required: true + - in: query + name: marketMint + description: Mint address for the given market to filter top trader data + schema: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + description: Mint address for the given market to filter top trader data + required: true + - in: query + name: year + description: The year for the week to query + schema: + type: string + description: The year for the week to query + required: true + - in: query + name: week + description: The week number (1-53) or "current" for the current week + schema: + anyOf: + - type: string + const: current + - type: string + description: The week number (1-53) or "current" for the current week + required: true + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + totalVolumeUsd: + type: string + description: The total volume (USD) for the trader. + totalPnlUsd: + type: string + description: The total PNL (USD) for the trader. + startTimestamp: + type: number + description: >- + The start timestamp for the week (UNIX timestamp in + seconds). + endTimestamp: + type: number + description: >- + The end timestamp for the week (UNIX timestamp in + seconds). + required: + - totalVolumeUsd + - totalPnlUsd + - startTimestamp + - endTimestamp + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /jlp/burn: + description: Endpoint to burn JLP + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + burnTokenAmount: + type: string + description: >- + The amount of JLP tokens to burn scaled to 6 decimal places + as per the JLP mint + receiveToken: + type: string + enum: + - WBTC + - ETH + - SOL + - USDC + description: Token to receive from burning JLP + walletAddress: + type: string + description: Public key for the wallet to burn JLP + required: + - burnTokenAmount + - receiveToken + - walletAddress + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + burnFeeBps: + type: string + description: JLP burn fee (BPS) + burnFeePercent: + type: string + description: JLP burn fee (%) + burnFeeTokenAmount: + type: string + description: JLP burn fee in the receive token + receiveToken: + type: string + description: The receive token from burning JLP + receiveTokenAmount: + type: string + description: >- + The amount of the receive token to receive from burning + JLP after fees + receiveTokenCustody: + type: string + description: The receive token's custody pubkey + receiveTokenMint: + type: string + description: The receive token's mint pubkey + serializedTxBase64: + type: + - string + - 'null' + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the borrow / deposit + request. The transaction can be deserialized, signed by + the owner of `walletAddress` and submitted onchain. + transactionType: + type: string + enum: + - legacy + description: The type of transaction + default: legacy + txMetadata: + type: + - object + - 'null' + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the + transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: >- + Contains relevant metadata for the serialized transaction. + Null if no wallet address passed in. + required: + - burnFeeBps + - burnFeePercent + - burnFeeTokenAmount + - receiveToken + - receiveTokenAmount + - receiveTokenCustody + - receiveTokenMint + - serializedTxBase64 + - transactionType + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /jlp/mint: + description: Endpoint to mint JLP + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + depositToken: + type: string + enum: + - WBTC + - ETH + - SOL + - USDC + description: Token to deposit to mint JLP + depositTokenAmount: + type: string + description: The amount of the deposit token to deposit to mint JLP + walletAddress: + type: string + description: Public key for the wallet to mint JLP + required: + - depositToken + - depositTokenAmount + - walletAddress + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + mintFeeBps: + type: string + description: JLP mint fee (BPS) + mintFeePercent: + type: string + description: JLP mint fee (%) + mintTokenAmount: + type: string + description: The amount of JLP minted (after fees) + serializedTxBase64: + type: + - string + - 'null' + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the mint request. + The transaction can be deserialized, signed by the owner + of `walletAddress` and submitted onchain. + transactionType: + type: string + enum: + - legacy + description: The type of transaction + default: legacy + txMetadata: + type: + - object + - 'null' + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the + transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: >- + Contains relevant metadata for the serialized transaction. + Null if no wallet address passed in. + required: + - mintFeeBps + - mintFeePercent + - mintTokenAmount + - serializedTxBase64 + - transactionType + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' +components: + schemas: + errorSchema: + type: object + properties: + code: + type: string + message: + type: string + required: + - code + - message + description: Error object + example: + code: http_error + message: >- + Invalid path /hello-world. Consult the OpenAPI documentation for the + list of valid routes: https://perps-api.jup.ag/v1/docs From faaac3bcff741683b17f09d33fec9b3b27416005 Mon Sep 17 00:00:00 2001 From: YY Date: Wed, 5 Nov 2025 14:38:51 +0800 Subject: [PATCH 02/10] chore: update --- api-reference/lend.mdx | 2 +- api-reference/perps.mdx | 12 + api-reference/perps/delete-orders-limit.mdx | 3 + api-reference/perps/delete-tpsl-with-fee.mdx | 3 + api-reference/perps/delete-tpsl.mdx | 2 - .../perps/{others => }/get-jlp-info.mdx | 0 ...inghistory.mdx => get-lending-history.mdx} | 0 ...t-lendinginfo.mdx => get-lending-info.mdx} | 0 ...ositions.mdx => get-lending-positions.mdx} | 0 api-reference/perps/get-market-stats.mdx | 2 - ...dersexpired.mdx => get-orders-expired.mdx} | 2 - api-reference/perps/get-orders-limit.mdx | 3 + api-reference/perps/get-pool-info.mdx | 2 - .../perps/get-positions-collateral-limits.mdx | 3 + api-reference/perps/get-positions.mdx | 2 - .../perps/get-positionscollateral-limits.mdx | 5 - api-reference/perps/get-top-traders.mdx | 2 - api-reference/perps/get-trader-stats.mdx | 2 - api-reference/perps/get-trades.mdx | 2 - api-reference/perps/jlp-lending-overview.mdx | 17 + api-reference/perps/jlp-overview.mdx | 17 + api-reference/perps/patch-orders-limit.mdx | 3 + api-reference/perps/patch-tpsl-with-fee.mdx | 3 + api-reference/perps/patch-tpsl.mdx | 2 - .../post-jlpburn.mdx => post-jlp-burn.mdx} | 0 .../post-jlpmint.mdx => post-jlp-mint.mdx} | 0 ...ow.mdx => post-lending-deposit-borrow.mdx} | 0 ...draw.mdx => post-lending-pay-withdraw.mdx} | 0 api-reference/perps/post-orders-limit.mdx | 3 + ...e-all.mdx => post-positions-close-all.mdx} | 2 - .../post-positions-decrease-with-fee.mdx | 3 + ...crease.mdx => post-positions-decrease.mdx} | 2 - .../post-positions-increase-with-fee.mdx | 3 + ...crease.mdx => post-positions-increase.mdx} | 2 - api-reference/perps/post-tpsl-with-fee.mdx | 3 + api-reference/perps/post-tpsl.mdx | 2 - .../perps/post-transaction-execute.mdx | 3 + api-reference/perps/trading-overview.mdx | 17 + docs.json | 89 +- openapi-spec/perps/perps.yaml | 5426 ++++++++++++----- 40 files changed, 3974 insertions(+), 1670 deletions(-) create mode 100644 api-reference/perps/delete-orders-limit.mdx create mode 100644 api-reference/perps/delete-tpsl-with-fee.mdx rename api-reference/perps/{others => }/get-jlp-info.mdx (100%) rename api-reference/perps/{others/get-lendinghistory.mdx => get-lending-history.mdx} (100%) rename api-reference/perps/{others/get-lendinginfo.mdx => get-lending-info.mdx} (100%) rename api-reference/perps/{others/get-lendingpositions.mdx => get-lending-positions.mdx} (100%) rename api-reference/perps/{get-ordersexpired.mdx => get-orders-expired.mdx} (53%) create mode 100644 api-reference/perps/get-orders-limit.mdx create mode 100644 api-reference/perps/get-positions-collateral-limits.mdx delete mode 100644 api-reference/perps/get-positionscollateral-limits.mdx create mode 100644 api-reference/perps/jlp-lending-overview.mdx create mode 100644 api-reference/perps/jlp-overview.mdx create mode 100644 api-reference/perps/patch-orders-limit.mdx create mode 100644 api-reference/perps/patch-tpsl-with-fee.mdx rename api-reference/perps/{others/post-jlpburn.mdx => post-jlp-burn.mdx} (100%) rename api-reference/perps/{others/post-jlpmint.mdx => post-jlp-mint.mdx} (100%) rename api-reference/perps/{others/post-lendingdeposit-borrow.mdx => post-lending-deposit-borrow.mdx} (100%) rename api-reference/perps/{others/post-lendingpay-withdraw.mdx => post-lending-pay-withdraw.mdx} (100%) create mode 100644 api-reference/perps/post-orders-limit.mdx rename api-reference/perps/{post-positionsclose-all.mdx => post-positions-close-all.mdx} (51%) create mode 100644 api-reference/perps/post-positions-decrease-with-fee.mdx rename api-reference/perps/{post-positionsdecrease.mdx => post-positions-decrease.mdx} (51%) create mode 100644 api-reference/perps/post-positions-increase-with-fee.mdx rename api-reference/perps/{post-positionsincrease.mdx => post-positions-increase.mdx} (51%) create mode 100644 api-reference/perps/post-tpsl-with-fee.mdx create mode 100644 api-reference/perps/post-transaction-execute.mdx create mode 100644 api-reference/perps/trading-overview.mdx diff --git a/api-reference/lend.mdx b/api-reference/lend.mdx index 921b8814..5585590e 100644 --- a/api-reference/lend.mdx +++ b/api-reference/lend.mdx @@ -6,6 +6,6 @@ description: "Overview of Jupiter Lend API" - 11 items + 11 items diff --git a/api-reference/perps.mdx b/api-reference/perps.mdx index eb59aeeb..f1d66d4a 100644 --- a/api-reference/perps.mdx +++ b/api-reference/perps.mdx @@ -3,3 +3,15 @@ title: "Perps (Beta)" sidebarTitle: "Overview" description: "Overview of Jupiter Perps API" --- + + + + 24 items + + + 3 items + + + 5 items + + diff --git a/api-reference/perps/delete-orders-limit.mdx b/api-reference/perps/delete-orders-limit.mdx new file mode 100644 index 00000000..47bfb0c0 --- /dev/null +++ b/api-reference/perps/delete-orders-limit.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml delete /orders/limit +--- \ No newline at end of file diff --git a/api-reference/perps/delete-tpsl-with-fee.mdx b/api-reference/perps/delete-tpsl-with-fee.mdx new file mode 100644 index 00000000..0f908cc8 --- /dev/null +++ b/api-reference/perps/delete-tpsl-with-fee.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml delete /tpsl-with-fee +--- \ No newline at end of file diff --git a/api-reference/perps/delete-tpsl.mdx b/api-reference/perps/delete-tpsl.mdx index 8ae32040..8af76fef 100644 --- a/api-reference/perps/delete-tpsl.mdx +++ b/api-reference/perps/delete-tpsl.mdx @@ -1,5 +1,3 @@ --- -title: "DELETE TPSL" -sidebarTitle: "TPSL" openapi: /openapi-spec/perps/perps.yaml delete /tpsl --- \ No newline at end of file diff --git a/api-reference/perps/others/get-jlp-info.mdx b/api-reference/perps/get-jlp-info.mdx similarity index 100% rename from api-reference/perps/others/get-jlp-info.mdx rename to api-reference/perps/get-jlp-info.mdx diff --git a/api-reference/perps/others/get-lendinghistory.mdx b/api-reference/perps/get-lending-history.mdx similarity index 100% rename from api-reference/perps/others/get-lendinghistory.mdx rename to api-reference/perps/get-lending-history.mdx diff --git a/api-reference/perps/others/get-lendinginfo.mdx b/api-reference/perps/get-lending-info.mdx similarity index 100% rename from api-reference/perps/others/get-lendinginfo.mdx rename to api-reference/perps/get-lending-info.mdx diff --git a/api-reference/perps/others/get-lendingpositions.mdx b/api-reference/perps/get-lending-positions.mdx similarity index 100% rename from api-reference/perps/others/get-lendingpositions.mdx rename to api-reference/perps/get-lending-positions.mdx diff --git a/api-reference/perps/get-market-stats.mdx b/api-reference/perps/get-market-stats.mdx index cdbad514..5fb845a9 100644 --- a/api-reference/perps/get-market-stats.mdx +++ b/api-reference/perps/get-market-stats.mdx @@ -1,5 +1,3 @@ --- -title: "GET Market Stats" -sidebarTitle: "Market Stats" openapi: /openapi-spec/perps/perps.yaml get /market-stats --- \ No newline at end of file diff --git a/api-reference/perps/get-ordersexpired.mdx b/api-reference/perps/get-orders-expired.mdx similarity index 53% rename from api-reference/perps/get-ordersexpired.mdx rename to api-reference/perps/get-orders-expired.mdx index bd0d5eb3..726f58d0 100644 --- a/api-reference/perps/get-ordersexpired.mdx +++ b/api-reference/perps/get-orders-expired.mdx @@ -1,5 +1,3 @@ --- -title: "GET Orders Expired" -sidebarTitle: "Orders Expired" openapi: /openapi-spec/perps/perps.yaml get /orders/expired --- \ No newline at end of file diff --git a/api-reference/perps/get-orders-limit.mdx b/api-reference/perps/get-orders-limit.mdx new file mode 100644 index 00000000..7e5c8b4a --- /dev/null +++ b/api-reference/perps/get-orders-limit.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml get /orders/limit +--- \ No newline at end of file diff --git a/api-reference/perps/get-pool-info.mdx b/api-reference/perps/get-pool-info.mdx index 1748f486..75e9a8d8 100644 --- a/api-reference/perps/get-pool-info.mdx +++ b/api-reference/perps/get-pool-info.mdx @@ -1,5 +1,3 @@ --- -title: "GET Pool Info" -sidebarTitle: "Pool Info" openapi: /openapi-spec/perps/perps.yaml get /pool-info --- \ No newline at end of file diff --git a/api-reference/perps/get-positions-collateral-limits.mdx b/api-reference/perps/get-positions-collateral-limits.mdx new file mode 100644 index 00000000..aa127735 --- /dev/null +++ b/api-reference/perps/get-positions-collateral-limits.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml get /positions/collateral-limits +--- \ No newline at end of file diff --git a/api-reference/perps/get-positions.mdx b/api-reference/perps/get-positions.mdx index ba0879a9..103bae1b 100644 --- a/api-reference/perps/get-positions.mdx +++ b/api-reference/perps/get-positions.mdx @@ -1,5 +1,3 @@ --- -title: "GET Positions" -sidebarTitle: "Positions" openapi: /openapi-spec/perps/perps.yaml get /positions --- \ No newline at end of file diff --git a/api-reference/perps/get-positionscollateral-limits.mdx b/api-reference/perps/get-positionscollateral-limits.mdx deleted file mode 100644 index 15ad647c..00000000 --- a/api-reference/perps/get-positionscollateral-limits.mdx +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "GET Positions Collateral Limits" -sidebarTitle: "Positions Collateral Limits" -openapi: /openapi-spec/perps/perps.yaml get /positions/collateral-limits ---- \ No newline at end of file diff --git a/api-reference/perps/get-top-traders.mdx b/api-reference/perps/get-top-traders.mdx index 867b9598..d20ae6d3 100644 --- a/api-reference/perps/get-top-traders.mdx +++ b/api-reference/perps/get-top-traders.mdx @@ -1,5 +1,3 @@ --- -title: "GET Top Traders" -sidebarTitle: "Top Traders" openapi: /openapi-spec/perps/perps.yaml get /top-traders --- \ No newline at end of file diff --git a/api-reference/perps/get-trader-stats.mdx b/api-reference/perps/get-trader-stats.mdx index b717eb80..7505e88f 100644 --- a/api-reference/perps/get-trader-stats.mdx +++ b/api-reference/perps/get-trader-stats.mdx @@ -1,5 +1,3 @@ --- -title: "GET Trader Stats" -sidebarTitle: "Trader Stats" openapi: /openapi-spec/perps/perps.yaml get /trader-stats --- \ No newline at end of file diff --git a/api-reference/perps/get-trades.mdx b/api-reference/perps/get-trades.mdx index b31eac58..54d5fb78 100644 --- a/api-reference/perps/get-trades.mdx +++ b/api-reference/perps/get-trades.mdx @@ -1,5 +1,3 @@ --- -title: "GET Trades" -sidebarTitle: "Trades" openapi: /openapi-spec/perps/perps.yaml get /trades --- \ No newline at end of file diff --git a/api-reference/perps/jlp-lending-overview.mdx b/api-reference/perps/jlp-lending-overview.mdx new file mode 100644 index 00000000..553c58d8 --- /dev/null +++ b/api-reference/perps/jlp-lending-overview.mdx @@ -0,0 +1,17 @@ +--- +title: "JLP Lending Overview" +sidebarTitle: "Overview" +description: "Overview of JLP LendingEndpoints in Jupiter Perps API" +--- + + + + 24 items + + + 3 items + + + 5 items + + diff --git a/api-reference/perps/jlp-overview.mdx b/api-reference/perps/jlp-overview.mdx new file mode 100644 index 00000000..bf4a0172 --- /dev/null +++ b/api-reference/perps/jlp-overview.mdx @@ -0,0 +1,17 @@ +--- +title: "JLP Overview" +sidebarTitle: "Overview" +description: "Overview of JLP Endpoints in Jupiter Perps API" +--- + + + + 24 items + + + 3 items + + + 5 items + + diff --git a/api-reference/perps/patch-orders-limit.mdx b/api-reference/perps/patch-orders-limit.mdx new file mode 100644 index 00000000..193d3bcf --- /dev/null +++ b/api-reference/perps/patch-orders-limit.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml patch /orders/limit +--- \ No newline at end of file diff --git a/api-reference/perps/patch-tpsl-with-fee.mdx b/api-reference/perps/patch-tpsl-with-fee.mdx new file mode 100644 index 00000000..d16eb439 --- /dev/null +++ b/api-reference/perps/patch-tpsl-with-fee.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml patch /tpsl-with-fee +--- \ No newline at end of file diff --git a/api-reference/perps/patch-tpsl.mdx b/api-reference/perps/patch-tpsl.mdx index 8437c2ff..0a1fcb2e 100644 --- a/api-reference/perps/patch-tpsl.mdx +++ b/api-reference/perps/patch-tpsl.mdx @@ -1,5 +1,3 @@ --- -title: "PATCH TPSL" -sidebarTitle: "TPSL" openapi: /openapi-spec/perps/perps.yaml patch /tpsl --- \ No newline at end of file diff --git a/api-reference/perps/others/post-jlpburn.mdx b/api-reference/perps/post-jlp-burn.mdx similarity index 100% rename from api-reference/perps/others/post-jlpburn.mdx rename to api-reference/perps/post-jlp-burn.mdx diff --git a/api-reference/perps/others/post-jlpmint.mdx b/api-reference/perps/post-jlp-mint.mdx similarity index 100% rename from api-reference/perps/others/post-jlpmint.mdx rename to api-reference/perps/post-jlp-mint.mdx diff --git a/api-reference/perps/others/post-lendingdeposit-borrow.mdx b/api-reference/perps/post-lending-deposit-borrow.mdx similarity index 100% rename from api-reference/perps/others/post-lendingdeposit-borrow.mdx rename to api-reference/perps/post-lending-deposit-borrow.mdx diff --git a/api-reference/perps/others/post-lendingpay-withdraw.mdx b/api-reference/perps/post-lending-pay-withdraw.mdx similarity index 100% rename from api-reference/perps/others/post-lendingpay-withdraw.mdx rename to api-reference/perps/post-lending-pay-withdraw.mdx diff --git a/api-reference/perps/post-orders-limit.mdx b/api-reference/perps/post-orders-limit.mdx new file mode 100644 index 00000000..3b46e35f --- /dev/null +++ b/api-reference/perps/post-orders-limit.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml post /orders/limit +--- \ No newline at end of file diff --git a/api-reference/perps/post-positionsclose-all.mdx b/api-reference/perps/post-positions-close-all.mdx similarity index 51% rename from api-reference/perps/post-positionsclose-all.mdx rename to api-reference/perps/post-positions-close-all.mdx index 28dd59c8..54c17f6a 100644 --- a/api-reference/perps/post-positionsclose-all.mdx +++ b/api-reference/perps/post-positions-close-all.mdx @@ -1,5 +1,3 @@ --- -title: "POST Positions Close All" -sidebarTitle: "Positions Close All" openapi: /openapi-spec/perps/perps.yaml post /positions/close-all --- \ No newline at end of file diff --git a/api-reference/perps/post-positions-decrease-with-fee.mdx b/api-reference/perps/post-positions-decrease-with-fee.mdx new file mode 100644 index 00000000..18e48338 --- /dev/null +++ b/api-reference/perps/post-positions-decrease-with-fee.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml post /positions/decrease-with-fee +--- \ No newline at end of file diff --git a/api-reference/perps/post-positionsdecrease.mdx b/api-reference/perps/post-positions-decrease.mdx similarity index 51% rename from api-reference/perps/post-positionsdecrease.mdx rename to api-reference/perps/post-positions-decrease.mdx index a6bdb14d..a271e2db 100644 --- a/api-reference/perps/post-positionsdecrease.mdx +++ b/api-reference/perps/post-positions-decrease.mdx @@ -1,5 +1,3 @@ --- -title: "POST Positions Decrease" -sidebarTitle: "Positions Decrease" openapi: /openapi-spec/perps/perps.yaml post /positions/decrease --- \ No newline at end of file diff --git a/api-reference/perps/post-positions-increase-with-fee.mdx b/api-reference/perps/post-positions-increase-with-fee.mdx new file mode 100644 index 00000000..941a4d61 --- /dev/null +++ b/api-reference/perps/post-positions-increase-with-fee.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml post /positions/increase-with-fee +--- \ No newline at end of file diff --git a/api-reference/perps/post-positionsincrease.mdx b/api-reference/perps/post-positions-increase.mdx similarity index 51% rename from api-reference/perps/post-positionsincrease.mdx rename to api-reference/perps/post-positions-increase.mdx index b07a724d..6f663294 100644 --- a/api-reference/perps/post-positionsincrease.mdx +++ b/api-reference/perps/post-positions-increase.mdx @@ -1,5 +1,3 @@ --- -title: "POST Positions Increase" -sidebarTitle: "Positions Increase" openapi: /openapi-spec/perps/perps.yaml post /positions/increase --- \ No newline at end of file diff --git a/api-reference/perps/post-tpsl-with-fee.mdx b/api-reference/perps/post-tpsl-with-fee.mdx new file mode 100644 index 00000000..4ddf0755 --- /dev/null +++ b/api-reference/perps/post-tpsl-with-fee.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml post /tpsl-with-fee +--- \ No newline at end of file diff --git a/api-reference/perps/post-tpsl.mdx b/api-reference/perps/post-tpsl.mdx index a86f137d..aac5bafc 100644 --- a/api-reference/perps/post-tpsl.mdx +++ b/api-reference/perps/post-tpsl.mdx @@ -1,5 +1,3 @@ --- -title: "POST TPSL" -sidebarTitle: "TPSL" openapi: /openapi-spec/perps/perps.yaml post /tpsl --- \ No newline at end of file diff --git a/api-reference/perps/post-transaction-execute.mdx b/api-reference/perps/post-transaction-execute.mdx new file mode 100644 index 00000000..8835748d --- /dev/null +++ b/api-reference/perps/post-transaction-execute.mdx @@ -0,0 +1,3 @@ +--- +openapi: /openapi-spec/perps/perps.yaml post /transaction/execute +--- \ No newline at end of file diff --git a/api-reference/perps/trading-overview.mdx b/api-reference/perps/trading-overview.mdx new file mode 100644 index 00000000..3acfb9d4 --- /dev/null +++ b/api-reference/perps/trading-overview.mdx @@ -0,0 +1,17 @@ +--- +title: "Trading Overview" +sidebarTitle: "Overview" +description: "Overview of Trading Endpoints in Jupiter Perps API" +--- + + + + 24 items + + + 3 items + + + 5 items + + diff --git a/docs.json b/docs.json index 0094e17a..c9676da0 100644 --- a/docs.json +++ b/docs.json @@ -403,20 +403,81 @@ "tag": "BETA", "pages": [ "api-reference/perps", - "api-reference/perps/get-positions", - "api-reference/perps/post-positionsincrease", - "api-reference/perps/post-positionsdecrease", - "api-reference/perps/post-positionsclose-all", - "api-reference/perps/post-tpsl", - "api-reference/perps/patch-tpsl", - "api-reference/perps/delete-tpsl", - "api-reference/perps/get-ordersexpired", - "api-reference/perps/get-market-stats", - "api-reference/perps/get-positionscollateral-limits", - "api-reference/perps/get-trades", - "api-reference/perps/get-top-traders", - "api-reference/perps/get-trader-stats", - "api-reference/perps/get-pool-info" + { + "group": "Transaction Execution", + "pages": [ + "api-reference/perps/post-transaction-execute" + ] + }, + { + "group": "Trading", + "pages": [ + "api-reference/perps/trading-overview", + { + "group": "Informational", + "pages": [ + "api-reference/perps/get-market-stats", + "api-reference/perps/get-trader-stats", + "api-reference/perps/get-top-traders", + "api-reference/perps/get-pool-info", + "api-reference/perps/get-positions", + "api-reference/perps/get-positions-collateral-limits", + "api-reference/perps/get-orders-limit", + "api-reference/perps/get-orders-expired", + "api-reference/perps/get-trades" + ] + }, + { + "group": "Positions", + "pages": [ + "api-reference/perps/post-positions-increase", + "api-reference/perps/post-positions-increase-with-fee", + "api-reference/perps/post-positions-decrease", + "api-reference/perps/post-positions-decrease-with-fee", + "api-reference/perps/post-positions-close-all" + ] + }, + { + "group": "Limit Orders", + "pages": [ + "api-reference/perps/post-orders-limit", + "api-reference/perps/patch-orders-limit", + "api-reference/perps/delete-orders-limit" + ] + }, + { + "group": "TPSL", + "pages": [ + "api-reference/perps/post-tpsl", + "api-reference/perps/post-tpsl-with-fee", + "api-reference/perps/patch-tpsl", + "api-reference/perps/patch-tpsl-with-fee", + "api-reference/perps/delete-tpsl", + "api-reference/perps/delete-tpsl-with-fee" + ] + } + ] + }, + { + "group": "JLP", + "pages": [ + "api-reference/perps/jlp-overview", + "api-reference/perps/get-jlp-info", + "api-reference/perps/post-jlp-mint", + "api-reference/perps/post-jlp-burn" + ] + }, + { + "group": "JLP Lending", + "pages": [ + "api-reference/perps/jlp-lending-overview", + "api-reference/perps/post-lending-deposit-borrow", + "api-reference/perps/post-lending-pay-withdraw", + "api-reference/perps/get-lending-positions", + "api-reference/perps/get-lending-info", + "api-reference/perps/get-lending-history" + ] + } ] }, { diff --git a/openapi-spec/perps/perps.yaml b/openapi-spec/perps/perps.yaml index 1bcbc7e5..7b87cbb2 100644 --- a/openapi-spec/perps/perps.yaml +++ b/openapi-spec/perps/perps.yaml @@ -179,17 +179,130 @@ paths: application/json: schema: $ref: '#/components/schemas/errorSchema' - /positions: - description: Fetches the open positions for the given wallet address + /orders/limit: + description: Returns a serialized transaction to create a limit order. + delete: + requestBody: + content: + application/json: + schema: + type: object + properties: + positionRequestPubkey: + type: string + description: >- + Public key / account address for the position request + account for the limit order. + required: + - positionRequestPubkey + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + serializedTxBase64: + type: + - string + - 'null' + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the close limit + order request. The transaction can be deserialized, signed + by the owner of `walletAddress` and submitted onchain to + execute the close limit order request + txMetadata: + type: object + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the + transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + positionPubkey: + type: + - string + - 'null' + description: >- + The unique identifier (i.e. a program derived address) for + the position account. Use this address to find the + position account onchain. + positionRequestPubkey: + type: + - string + - 'null' + description: >- + The unique identifier (i.e. a program derived address) for + the position request. Use this address to find the + position request account onchain + requireKeeperSignature: + type: + - boolean + - 'null' + description: '' + required: + - serializedTxBase64 + - txMetadata + - positionPubkey + - positionRequestPubkey + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' get: - parameters: - - in: query - name: walletAddress - description: Public key for the wallet to fetch trades - schema: - type: string - description: Public key for the wallet to fetch trades - required: true + requestBody: + content: + application/json: + schema: + type: object + properties: + walletAddress: + type: string + description: Public key for the wallet to fetch expired orders + required: + - walletAddress responses: '200': description: 200 OK @@ -198,279 +311,137 @@ paths: schema: type: object properties: + count: + type: number dataList: type: array items: type: object properties: - borrowFees: + collateralMint: type: string description: >- - The outstanding borrow fees for the position in the - integer format corresponding to the 6 decimals - places used by the USDC and USDT token mint - example: '100000' - borrowFeesUsd: + The mint address for the limit order's collateral + token / custody + collateralCustody: type: string - description: The outstanding borrow fees (USD) for the position - example: '10.00' - closeFees: + description: The public key for the collateral custody account + collateralUsd: type: string description: >- - The fee for closing the position (0.06%) in the - integer format corresponding to the 6 decimals - places used by the USDC and USDT token mint - example: '100000' - closeFeesUsd: - type: string - description: The fee (USD) for closing the position (0.06%) - example: '10.00' - collateral: - type: string - description: USD value of the position's collateral size - example: '250.00' - collateralUsd: + The collateral value (USD) expressed as a raw + integer with 6 decimal places. + example: '1234000000' + collateralUsdAtTriggerPrice: type: string - description: Raw USD value of the position's collateral size - example: '250000000' - collateralMint: + description: >- + The collateral value (USD) at the trigger price (raw + value with 6 decimal places). + example: '1234000000' + collateralTokenAmount: type: string description: >- - The mint address for the position's collateral - token. 'SOL' = - 'So11111111111111111111111111111111111111112', 'ETH' - = '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs', - 'BTC' = - '3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh', - 'USDC' = - 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', - 'USDT' = - 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB' - example: So11111111111111111111111111111111111111112 - createdTime: - type: number - description: UNIX timestamp of when the trade was created - example: 1722851463 - entryPrice: + The collateral amount for the limit order scaled to + the token mint's decimals. + custody: type: string - description: USD value of the position's entry price - example: '123.45' - leverage: + description: The mint address for the limit order custody + executed: + type: boolean + description: >- + `executed` is true when the limit order has been + executed, `false` otherwise. + inputMint: type: string - description: Leverage amount for the position - example: '21.30' - liquidationPrice: + description: >- + The mint address for the token used to create the + limit order. + liquidationPriceUsd: type: string - description: USD value of the position's liquidation price - example: '123.45' + description: >- + The liquidation price (USD) expressed as a raw + integer with 6 decimal places. + example: '13240000' marketMint: type: string description: >- - The asset or market being traded against for the - position. 'SOL' = - 'So11111111111111111111111111111111111111112', 'ETH' - = '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs', - 'BTC' = - '3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh' - example: So11111111111111111111111111111111111111112 - markPrice: - type: string - description: USD value of the position's mark price - example: '123.45' - openFees: + The mint address for the limit order's token / + custody. + maxSizeUsdDelta: type: string description: >- - The fee for opening the position (0.06%) in the - integer format corresponding to the 6 decimals - places used by the USDC and USDT token mint - example: '100000' - openFeesUsd: - type: string - description: The fee (USD) for opening the position (0.06%) - example: '10.00' - pnlAfterFees: + The maximum size (USD) for the limit order (raw + value with 6 decimal places). + example: '1234000000' + minSizeUsdDelta: type: string description: >- - The position's PNL after fees in the integer format - corresponding to the 6 decimals places used by the - USDC and USDT token mint - example: '10.45' - pnlAfterFeesUsd: + The minimum size (USD) for the limit order (raw + value with 6 decimal places). + example: '1234000000' + openTime: type: string - description: The position's PNL (USD) after fees - example: '10.45' - pnlBeforeFees: + description: The UNIX timestamp when the limit order was created + positionPubkey: type: string description: >- - The position's PNL before fees in the integer format - corresponding to the 6 decimals places used by the - USDC and USDT token mint - example: '10.45' - pnlBeforeFeesUsd: - type: string - description: The position's PNL (USD) before fees - example: '10.45' - pnlChangePctAfterFees: - type: string - description: The position's PNL change percentage after fees - pnlChangePctBeforeFees: - type: string - description: The position's PNL change percentage before fees - positionPubkey: + The public key / account address for the limit + order's open position + positionRequestPubkey: type: string - description: The public key / address for the position - example: 815wh1VLC8D7ZWMa3uB7GgjHFetANuML2dPrJiLV1nVF + description: >- + The public key / account address for the limit + order's position request side: type: string enum: - long - short - size: - type: string - description: >- - USD value of the position's trade size (including - leverage) - example: '12345.68' sizeUsdDelta: type: string description: >- - Raw USD value of the position's trade size - (including leverage) - example: '12345.68' - sizeTokenAmount: - type: string + The size (USD) of the limit order (raw value with 6 + decimal places). + triggerPrice: + type: + - string + - 'null' description: >- - Raw token amount for the position's size scaled to - the custody token's mint decimals - example: '250000000' - totalFees: - type: string + The price (USD) at which the limit order is executed + (raw value with 6 decimal places). + triggerToLiquidationPercent: + type: + - string + - 'null' description: >- - The total fees for the position in the integer - format corresponding to the 6 decimals places used - by the USDC and USDT token mint. - example: '100000' - totalFeesUsd: - type: string - description: The total fees (USD) for the position. - example: '10.00' - tpslRequests: - type: array - items: - type: object - properties: - desiredMint: - type: string - description: >- - The mint address for the TP position request - account's desired mint - positionRequestPubkey: - type: string - description: >- - The public key / address for the TP position - request account - requestType: - type: string - enum: - - tp - - sl - description: >- - Returns `tp` if it is a take profit request, - `sl` if it is a stop loss request - sizeUsd: - type: string - description: >- - The close size for the TP / SL in integer - format corresponding to the 6 decimals places - used by the USDC and USDT token mint - example: '1234000000' - sizeUsdFormatted: - type: string - description: >- - The formatted close size for the TP / SL in - integer format corresponding to the 6 decimals - places used by the USDC and USDT token mint - example: '12.34' - sizePercentage: - type: string - description: >- - The percentage / ratio TP / SL size to the - position size - example: '12.34' - triggerPrice: - type: - - string - - 'null' - description: >- - The trigger price for the TP / SL request in - integer format corresponding to the 6 decimals - places used by the USDC and USDT token mint - example: '20000000' - triggerPriceUsd: - type: - - string - - 'null' - description: >- - The trigger price (USD) for the TP / SL - request - example: '20000000' - required: - - desiredMint - - positionRequestPubkey - - requestType - - sizeUsd - - sizeUsdFormatted - - sizePercentage - - triggerPrice - - triggerPriceUsd - description: The active TP / SL requests for the position - updatedTime: - type: number - example: 1722851463 - value: - type: string - description: >- - USD value of the currently open position including - fees incurred by opening, closing, and borrowing the - position - example: '120.00' + Percentage buffer between the limit order trigger + price and position liquidation price. Calculated as + ((triggerPrice - liquidationPrice) / + liquidationPrice) * 100. + example: '5.75' required: - - borrowFees - - borrowFeesUsd - - closeFees - - closeFeesUsd - - collateral - - collateralUsd - collateralMint - - createdTime - - entryPrice - - leverage - - liquidationPrice + - collateralCustody + - collateralUsd + - collateralUsdAtTriggerPrice + - collateralTokenAmount + - custody + - executed + - inputMint + - liquidationPriceUsd - marketMint - - markPrice - - openFees - - openFeesUsd - - pnlAfterFees - - pnlAfterFeesUsd - - pnlBeforeFees - - pnlBeforeFeesUsd - - pnlChangePctAfterFees - - pnlChangePctBeforeFees + - maxSizeUsdDelta + - minSizeUsdDelta + - openTime - positionPubkey + - positionRequestPubkey - side - - size - sizeUsdDelta - - sizeTokenAmount - - totalFees - - totalFeesUsd - - tpslRequests - - updatedTime - - value - count: - type: number + - triggerPrice + - triggerToLiquidationPercent required: - - dataList - count + - dataList '400': description: 400 Bad Request content: @@ -495,10 +466,6 @@ paths: application/json: schema: $ref: '#/components/schemas/errorSchema' - /positions/close-all: - description: >- - Returns an array of serialized transactions to close all open positions - for the given wallet address. post: requestBody: content: @@ -506,13 +473,77 @@ paths: schema: type: object properties: + asset: + type: string + enum: + - BTC + - ETH + - SOL + description: The asset or market to trade against for the limit order. + example: SOL + includeSerializedTx: + type: boolean + default: true + description: >- + Sets whether to return a serialized transaction + (`serializedTxBase64`) in the response. + inputToken: + type: string + enum: + - BTC + - ETH + - SOL + - USDC + description: >- + The token symbol for the input token used to fund the limit + order. + example: USDC + inputTokenAmount: + type: string + description: >- + The amount of tokens for the input token. NOTE: The token + amount needs to be an integer and must conform to the token + mint decimals specified onchain. For example, to deposit 1 + SOL, the value would be '1000000000' (9 decimals). + example: '1000000000' + leverage: + type: string + description: >- + Leverage of the limit order. Either provide leverage or + sizeUsdDelta. + example: '10' + side: + type: string + enum: + - long + - short + description: Required when creating a limit order request. + sizeUsdDelta: + type: string + description: >- + The amount in USD for the size of the limit order (raw value + with 6 decimal places). Either provide leverage or + sizeUsdDelta. + example: '10000000' + triggerPrice: + type: string + description: >- + Trigger price at which the limit order will be executed (raw + value with 6 decimal places). For example, to set a trigger + price of $20, pass in 20000000. + example: '20000000' walletAddress: type: string description: >- - The wallet address / public key for the trader to close all - open positions + The wallet address / public key for the trader. Required + when creating a limit order that returns a serialized + transaction. required: - - walletAddress + - asset + - inputToken + - inputTokenAmount + - side + - triggerPrice responses: '200': description: 200 OK @@ -521,58 +552,167 @@ paths: schema: type: object properties: - serializedTxs: - type: array - items: - type: object - properties: - serializedTxBase64: - type: string - description: >- - The serialized transaction (base64 encoded) - containing the instructions and given parameters for - the close position instruction. The transaction can - be deserialized, signed by the owner of - `walletAddress` and submitted onchain to close the - position. - positionRequestPubkey: - type: string - description: >- - The public key / address for the position request to - close the position. - required: - - serializedTxBase64 - - positionRequestPubkey + positionPubkey: + type: + - string + - 'null' description: >- - An array of base64-serialized transactions and the - `positionRequestPubkey` to close all positions. - txMetadata: + The unique identifier (i.e. a program derived address) for + the position account. Use this address to find the + position account onchain. + quote: type: object + properties: + averagePriceUsd: + type: string + description: >- + The average price for the position in USD (raw value + with 6 decimal places) + example: '10000000' + collateralUsdDelta: + type: string + description: >- + The change in collateral amount in USD (raw value with + 6 decimal places) + example: '1124450000' + leverage: + type: string + description: The leverage amount for the position + example: '2.99' + liquidationPriceUsd: + type: string + description: >- + The liquidation price in USD (raw value with 6 decimal + places) + example: '13240000' + openFeeUsd: + type: string + description: >- + The total fee in USD for opening the position or + depositing collateral including base fees, borrowing + fees, and price impact fees (raw value with 6 decimal + places) + example: '100000' + outstandingBorrowFeeUsd: + type: string + description: >- + The outstanding borrow fees due / to be paid on + depositing collateral to the position (raw value with + 6 decimal places) + example: '100000' + positionCollateralUsd: + type: string + description: >- + The total position collateral size in USD after the + increase (raw value with 6 decimal places) + example: '100000000' + positionSizeUsd: + type: string + description: >- + The total position size in USD including leverage + after the increase (raw value with 6 decimal places) + example: '10000000' + priceImpactFeeBps: + type: string + description: >- + The price impact fee bps for opening the position + based on the position size. For more info on how the + price impact fee calculation works: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '100' + priceImpactFeeUsd: + type: string + description: >- + The price impact fee in USD for opening the position + based on the position size (raw value with 6 decimal + places). For more info: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '13301' + side: + type: string + enum: + - long + - short + description: The position side + example: long + sizeUsdDelta: + type: string + description: >- + The change in position size in USD (raw value with 6 + decimal places) + example: '1124450000' + sizeTokenDelta: + type: string + description: >- + The change in the position's size in the token amount + for the position's collateral token. + example: '14420000' + required: + - averagePriceUsd + - collateralUsdDelta + - leverage + - liquidationPriceUsd + - openFeeUsd + - outstandingBorrowFeeUsd + - positionCollateralUsd + - positionSizeUsd + - priceImpactFeeBps + - priceImpactFeeUsd + - side + - sizeUsdDelta + - sizeTokenDelta + serializedTxBase64: + type: + - string + - 'null' + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the limit order. The + transaction can be deserialized, signed by the owner of + `walletAddress` and submitted onchain to execute the + request + txMetadata: + type: + - object + - 'null' properties: blockhash: type: string description: >- The blockhash used for the serialized transaction. This blockhash must be used when submitting the signed - close position transaction. + limit order transaction. lastValidBlockHeight: type: string description: >- The block height used for the serialized transaction. This block height must be used when submitting the - signed close position transaction. + signed limit order transaction. + transactionFeeLamports: + type: string + description: >- + The transaction fee in lamports (1 SOL = 1,000,000,000 + lamports) + example: '5000' + accountRentLamports: + type: string + description: >- + The account rent in lamports for creating the position + request (1 SOL = 1,000,000,000 lamports) + example: '2039280' required: - blockhash - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports description: >- - Contains blockhash metadata for the serialized transaction - to submit and confirm the transactions. + Contains relevant metadata for the serialized transaction. + Null if no wallet address passed in. required: - - serializedTxs + - positionPubkey + - quote + - serializedTxBase64 - txMetadata - description: >- - An array of base64-serialized transactions and transaction - metadata to close all positions. '400': description: 400 Bad Request content: @@ -597,36 +737,26 @@ paths: application/json: schema: $ref: '#/components/schemas/errorSchema' - /positions/collateral-limits: - description: >- - Returns the minimum and maximum token amounts for collateral deposits, as - well as the maximum token amount for collateral withdrawals. - get: - parameters: - - in: query - name: inputMint - description: >- - The mint address for the input token to deposit as collateral (e.g. - 'So11111111111111111111111111111111111111112' for 'SOL') - schema: - type: string - description: >- - The mint address for the input token to deposit as collateral - (e.g. 'So11111111111111111111111111111111111111112' for 'SOL') - example: So11111111111111111111111111111111111111112 - required: true - - in: query - name: positionPubkey - description: >- - The public key for the open position. Use the `GET positions` - endpoint to fetch the public key for the trader's open positions. - schema: - type: string - description: >- - The public key for the open position. Use the `GET positions` - endpoint to fetch the public key for the trader's open positions. - example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 - required: true + patch: + requestBody: + content: + application/json: + schema: + type: object + properties: + positionRequestPubkey: + type: string + description: The public key for the limit order position request. + triggerPrice: + type: string + description: >- + Trigger price at which the limit order will be executed (raw + value with 6 decimal places). For example, to set a trigger + price of $20, pass in 20000000. + example: '20000000' + required: + - positionRequestPubkey + - triggerPrice responses: '200': description: 200 OK @@ -635,170 +765,10 @@ paths: schema: type: object properties: - maxCollateralDepositTokenAmount: - type: string - description: >- - The maximum token amount that can be deposited as - collateral for the given input mint token. - maxCollateralDepositUsd: - type: string - description: >- - The maximum amount (USD) that can be deposited as - collateral for the given input mint token. The value is an - integer corresponding to the 6 decimals places used by the - USDC and USDT token mint. - minCollateralDepositTokenAmount: - type: string - description: >- - The minimum token amount that can be deposited as - collateral for the given input mint token. - minCollateralDepositUsd: - type: string - description: >- - The minimum amount (USD) that can be deposited as - collateral for the given input mint token. The value is an - integer corresponding to the 6 decimals places used by the - USDC and USDT token mint. - maxCollateralWithdrawalTokenAmount: - type: string - description: >- - The maximum collateral token amount that can be withdrawed - from the open position. - maxCollateralWithdrawalUsd: - type: string - description: >- - The maximum collateral (USD) that can be withdrawed from - the open position. The value is an integer corresponding - to the 6 decimals places used by the USDC and USDT token - mint. - minCollateralWithdrawalTokenAmount: - type: string - description: >- - The minimum collateral token amount that can be withdrawed - from the open position. - minCollateralWithdrawalUsd: - type: string - description: >- - The minimum collateral (USD) that can be withdrawed from - the open position. The value is an integer corresponding - to the 6 decimals places used by the USDC and USDT token - mint. - required: - - maxCollateralDepositTokenAmount - - maxCollateralDepositUsd - - minCollateralDepositTokenAmount - - minCollateralDepositUsd - - maxCollateralWithdrawalTokenAmount - - maxCollateralWithdrawalUsd - - minCollateralWithdrawalTokenAmount - - minCollateralWithdrawalUsd - '400': - description: 400 Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/errorSchema' - '404': - description: 404 Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/errorSchema' - '422': - description: 422 Unprocessable entity - content: - application/json: - schema: - $ref: '#/components/schemas/errorSchema' - '500': - description: 500 Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/errorSchema' - /positions/decrease: - description: >- - Uses the `decreasePositionParams` object from calling `GET - /positions/decrease/quote` and returns a base64-serialized transaction for - the request, the position request PDA, and the position PDA that acts as - the unique identifier for the position. - post: - requestBody: - content: - application/json: - schema: - type: object - properties: - collateralUsdDelta: - type: string - description: >- - The amount of collateral to withdraw in USD from the - position. Must be an integer representing the USD amount - multiplied by 10^6 (1 million) to align with the 6 decimal - places used for USDC/USDT tokens on-chain. For example, to - decrease by $10 USD, set 'collateralUsdDelta' to 10000000; - for $20.50 USD, set 'collateralUsdDelta' to 20500000. - example: '10000000' - desiredMint: - type: string - enum: - - So11111111111111111111111111111111111111112 - - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs - - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh - - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v - - Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB - description: >- - The mint address for the token to be used when withdrawing - collateral or closing position. - example: So11111111111111111111111111111111111111112 - entirePosition: - type: boolean - default: false - description: >- - When set to `true`, this will close the position and - transfer the remaining collateral and realised profits (if - the position is profitable) to the trader. - example: false - maxSlippageBps: - type: string - default: '200' - description: >- - The maximum slippage in (BPS) for the token swap (if - required) and the token price when executing the increase - position trade - example: '100' - positionPubkey: - type: string - description: >- - The public key for the open position. Use the `GET - positions` endpoint to fetch the public key for the trader's - open positions. - example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 - sizeUsdDelta: - type: string - description: >- - The amount in USD to decrease the position size by. Must be - an integer representing the USD amount multiplied by 10^6 (1 - million) to align with the 6 decimal places used for - USDC/USDT tokens on-chain. For example, to decrease by $10 - USD, set 'sizeUsdDelta' to 10000000; for $20.50 USD, set - 'sizeUsdDelta' to 20500000. - example: '10000000' - required: - - collateralUsdDelta - - desiredMint - - positionPubkey - - sizeUsdDelta - responses: - '200': - description: 200 OK - content: - application/json: - schema: - type: object - properties: - positionPubkey: - type: string + positionPubkey: + type: + - string + - 'null' description: >- The unique identifier (i.e. a program derived address) for the position account. Use this address to find the @@ -810,104 +780,75 @@ paths: description: >- The unique identifier (i.e. a program derived address) for the position request. Use this address to find the - position request account onchain. Returns null if - `requireKeeperSignature` is true. + position request account onchain quote: type: object properties: - closeFeeUsd: + averagePriceUsd: type: string description: >- - The base close fee (USD) for closing the position or - withdrawing collateral from the position. - example: '0.0063' - feeUsd: + The average price for the position in USD (raw value + with 6 decimal places) + example: '10000000' + collateralUsdDelta: type: string description: >- - The total fee (USD) for closing or withdrawing - collateral from the position including base fees, - borrowing fees, and price impact fees - example: '0.0063' + The change in collateral amount in USD (raw value with + 6 decimal places) + example: '1124450000' leverage: type: string - description: >- - The leverage amount for the position after withdrawing - collateral + description: The leverage amount for the position example: '2.99' liquidationPriceUsd: type: string description: >- - The liquidation price (USD) for the position after - withdrawing collateral - example: '13.24' - outstandingBorrowFeeUsd: - type: string - description: >- - The outstanding borrow fees due / to be paid on - closing the position - example: '0.1000' - pnlAfterFees: - type: string - description: >- - The position's PNL after fees in the integer format - corresponding to the 6 decimals places used by the - USDC and USDT token mint - example: '1045000' - pnlAfterFeesPercent: - type: string - description: >- - The PNL change (%) from closing the position after - fees. - example: '-20.24' - pnlAfterFeesUsd: - type: string - description: The position's PNL (USD) after fees - example: '10.45' - pnlBeforeFees: + The liquidation price in USD (raw value with 6 decimal + places) + example: '13240000' + openFeeUsd: type: string description: >- - The position's PNL before fees in the integer format - corresponding to the 6 decimals places used by the - USDC and USDT token mint - example: '1045000' - pnlBeforeFeesPercent: + The total fee in USD for opening the position or + depositing collateral including base fees, borrowing + fees, and price impact fees (raw value with 6 decimal + places) + example: '100000' + outstandingBorrowFeeUsd: type: string description: >- - The PNL change (%) from closing the position before - fees. - example: '20.24' - pnlBeforeFeesUsd: - type: string - description: The position's PNL (USD) before fees - example: '10.45' - positionCollateralSizeUsd: + The outstanding borrow fees due / to be paid on + depositing collateral to the position (raw value with + 6 decimal places) + example: '100000' + positionCollateralUsd: type: string description: >- - The total position collateral size (USD) after - withdrawing - example: '1124.45' + The total position collateral size in USD after the + increase (raw value with 6 decimal places) + example: '100000000' positionSizeUsd: type: string description: >- - The total position size (USD) including leverage after - withdrawing - example: '1124.45' + The total position size in USD including leverage + after the increase (raw value with 6 decimal places) + example: '10000000' priceImpactFeeBps: type: string description: >- - The price impact fee bps for closing the position + The price impact fee bps for opening the position based on the position size. For more info on how the price impact fee calculation works: https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 - example: '1.3301' + example: '100' priceImpactFeeUsd: type: string description: >- - The price impact fee (USD) for closing the position - based on the position size. For more info on how the - price impact fee calculation works: + The price impact fee in USD for opening the position + based on the position size (raw value with 6 decimal + places). For more info: https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 - example: '1.3301' + example: '13301' side: type: string enum: @@ -915,84 +856,71 @@ paths: - short description: The position side example: long - transferTokenMint: - type: string - description: >- - The mint address for the token used to transfer the - collateral withdrawal or closing position amount - example: So11111111111111111111111111111111111111112 - transferAmountToken: + sizeUsdDelta: type: string description: >- - The collateral token amount to transfer to the owner - after withdrawing collateral or closing the position - example: '100000000' - transferAmountUsd: + The change in position size in USD (raw value with 6 + decimal places) + example: '1124450000' + sizeTokenDelta: type: string description: >- - The collateral token amount in USD to transfer to the - owner withdrawing collateral or closing the position - example: '1099.95' + The change in the position's size in the token amount + for the position's collateral token. + example: '14420000' required: - - closeFeeUsd - - feeUsd + - averagePriceUsd + - collateralUsdDelta - leverage - liquidationPriceUsd + - openFeeUsd - outstandingBorrowFeeUsd - - pnlAfterFees - - pnlAfterFeesPercent - - pnlAfterFeesUsd - - pnlBeforeFees - - pnlBeforeFeesPercent - - pnlBeforeFeesUsd - - positionCollateralSizeUsd + - positionCollateralUsd - positionSizeUsd - priceImpactFeeBps - priceImpactFeeUsd - side - - transferTokenMint - - transferAmountToken - - transferAmountUsd - description: >- - The 'quote' object contains the position's updated values - (leverage, size, collateral size, etc.) after withdrawing - collateral. - requireKeeperSignature: + - sizeUsdDelta + - sizeTokenDelta + serializedTxBase64: type: - - boolean + - string - 'null' - description: '' - serializedTxBase64: - type: string description: >- The serialized transaction (base64 encoded) containing the - instructions and given parameters for the decrease - position request. The transaction can be deserialized, - signed by the owner of `walletAddress` and submitted - onchain to execute the decrease position request + instructions and given parameters for the update limit + order request. The transaction can be deserialized, signed + by the owner of `walletAddress` and submitted onchain to + execute the update limit order request txMetadata: - type: object + type: + - object + - 'null' properties: blockhash: type: string description: >- The blockhash used for the serialized transaction. This blockhash must be used when submitting the signed - decrease position transaction. + limit order transaction. lastValidBlockHeight: type: string description: >- The block height used for the serialized transaction. This block height must be used when submitting the - signed decrease position transaction. + signed limit order transaction. transactionFeeLamports: type: string - description: The transaction fee (in lamports) in decimal format. - example: '0.5' + description: >- + The transaction fee in lamports (1 SOL = 1,000,000,000 + lamports) + example: '5000' accountRentLamports: type: string - description: The account rent (in lamports) for the transaction - example: '0.5' + description: >- + The account rent in lamports for creating the position + request (1 SOL = 1,000,000,000 lamports) + example: '2039280' required: - blockhash - lastValidBlockHeight @@ -1001,6 +929,7 @@ paths: description: Contains relevant metadata for the serialized transaction. required: - positionPubkey + - positionRequestPubkey - quote - serializedTxBase64 - txMetadata @@ -1028,166 +957,24 @@ paths: application/json: schema: $ref: '#/components/schemas/errorSchema' - /positions/increase: - description: >- - Uses the `increasePositionParams` object from calling `GET - /positions/increase/quote` and returns a base64-serialized transaction for - the request, the position request PDA, and the position PDA that acts as - the unique identifier for the position. - post: - requestBody: - content: - application/json: - schema: - type: object - properties: - collateralMint: - type: string - enum: - - So11111111111111111111111111111111111111112 - - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs - - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh - - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v - - Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB - description: >- - The mint address for the collateral token (e.g. - 'So11111111111111111111111111111111111111112' for 'SOL'). - 'collateralMint' must be the same as 'marketMint' for long - positions, or USDC - (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v) for short - positions. - example: So11111111111111111111111111111111111111112 - collateralTokenDelta: - type: string - description: >- - The amount of tokens for the input mint to open the position - or deposit collateral. NOTE: The token amount needs to be an - integer and must conform to the token mint decimals - specified onchain. For example, to deposit 1 'SOL', the - 'collateralTokenDelta' value would be equal to '1000000000' - example: '1000000000' - inputMint: - type: string - description: >- - The mint address for the input token (e.g. - 'So11111111111111111111111111111111111111112' for 'SOL') - example: So11111111111111111111111111111111111111112 - leverage: - type: string - description: >- - Leverage of the increase position. Either provide leverage - or sizeUsdDelta. Max leverage for SOL is 100. Max leverage - for BTC / ETH is 150 - example: '10' - marketMint: - type: string - enum: - - So11111111111111111111111111111111111111112 - - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs - - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh - description: >- - The asset or market to trade against. Required when opening - a new position. 'SOL' = - 'So11111111111111111111111111111111111111112', 'ETH' = - '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs', 'BTC' = - '3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh' - example: So11111111111111111111111111111111111111112 - maxSlippageBps: - type: string - description: >- - The maximum slippage in (BPS) for the custody token price - when executing the decrease position trade - example: '100' - includeSerializedTx: - type: boolean - default: true - description: >- - Sets whether to return a serialized transaction - (`serializedTxBase64`) in the response - side: - type: string - enum: - - long - - short - description: Required when opening a new position - sizeUsdDelta: - type: string - description: >- - The amount in USD to increase the position size by. Must be - an integer representing the USD amount multiplied by 10^6 (1 - million) to align with the 6 decimal places used for - USDC/USDT tokens on-chain. For example, to increase the - position size by $10 USD, set 'sizeUsdDelta' to 10000000; - for $0.50 USD, set 'sizeUsdDelta' to 500000. Either provide - leverage or sizeUsdDelta. - example: '10000000' - transactionType: - type: string - enum: - - legacy - - mixed - - instant - default: mixed - description: >- - Sets the type of serialized transaction to execute the - action. If the transaction type is `legacy`, the transaction - must be submitted by the client itself through the RPC. If - the transaction type is `instant`, the transaction must be - sent to the `POST /transaction/execute` endpoint. If the - transaction type is `mixed`, the `transactionType` returned - in the response will be either `legacy` or `instant`. - tpsl: - type: - - array - - 'null' - items: - type: object - properties: - desiredMint: - type: string - enum: - - So11111111111111111111111111111111111111112 - - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs - - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh - - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v - - Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB - description: >- - The mint address for the token used when withdrawing - collateral or closing position when the TPSL is - executed. - triggerPrice: - type: string - description: >- - Trigger price at which the TP / SL request will be - executed. The value must be an integer corresponding - to 6 decimal places. For example, to set a trigger - price of $20, pass in 20000000 - example: '20000000' - requestType: - type: string - enum: - - tp - - sl - description: >- - Pass in `tp` to set a take profit request or `sl` to - set a stop loss request - required: - - desiredMint - - triggerPrice - - requestType - description: TPSL requests to set - walletAddress: - type: string - description: >- - The wallet address / public key for the trader, Required - when opening a new position. - required: - - collateralMint - - collateralTokenDelta - - inputMint - - marketMint - - maxSlippageBps - - side + /positions: + description: Fetches the open positions for the given wallet address + get: + parameters: + - in: query + name: includeClosedPositions + description: Set to true to return closed positions + schema: + type: boolean + default: false + description: Set to true to return closed positions + - in: query + name: walletAddress + description: Public key for the wallet to fetch trades + schema: + type: string + description: Public key for the wallet to fetch trades + required: true responses: '200': description: 200 OK @@ -1196,273 +983,369 @@ paths: schema: type: object properties: - positionPubkey: - type: - - string - - 'null' - description: >- - The unique identifier (i.e. a program derived address) for - the position account. Use this address to find the - position account onchain. - positionRequestPubkey: - type: - - string - - 'null' - description: >- - The unique identifier (i.e. a program derived address) for - the position request. Use this address to find the - position request account onchain - tpslRequests: + dataList: type: array items: type: object properties: - estimatedPnlUsd: + asset: type: string - description: The estimated PNL (USD) for the TPSL request - estimatedPnlPercent: + enum: + - BTC + - ETH + - SOL + description: >- + The asset or market being traded against for the + position. + example: SOL + assetMint: type: string - description: The estimated PNL percentage for the TPSL request - hasProfit: - type: boolean - description: Whether the TPSL request has profit - requestType: + description: The mint address for the position asset. + example: So11111111111111111111111111111111111111112 + collateralToken: type: string enum: - - tp - - sl - description: The type of TPSL request - positionRequestPubkey: + - BTC + - ETH + - SOL + - USDC + - USDT + description: >- + The token symbol for the collateral backing the + position. + example: SOL + collateralMint: + type: string + description: The mint address for the collateral token. + example: So11111111111111111111111111111111111111112 + positionPubkey: + type: string + description: The public key / address for the position + example: 815wh1VLC8D7ZWMa3uB7GgjHFetANuML2dPrJiLV1nVF + side: + type: string + enum: + - long + - short + description: Side for the position + leverage: + type: string + description: Leverage amount for the position + example: '21.30' + sizeUsd: type: string description: >- - The unique identifier (i.e. a program derived - address) for the position request. Use this address - to find the position request account onchain - required: - - estimatedPnlUsd - - estimatedPnlPercent - - hasProfit - - requestType - - positionRequestPubkey - description: >- - TPSL requests created with the increase position. Only - returned when TPSL is requested. - quote: - type: object - properties: - collateralLessThanFees: - type: boolean - description: >- - When true, this means the trade's collateral is not - enough to cover the fees required to execute the - trade, causing the trade size to be zero (equivalent - to a collateral deposit). - example: true - entryPriceUsd: - type: string - description: The entry price (USD) for the position - example: '2.99' - leverage: - type: string - description: The leverage amount for the position - example: '2.99' - liquidationPriceUsd: - type: string - description: The liquidation price (USD) for the position - example: '13.24' - openFeeUsd: - type: string - description: >- - The total fee (USD) for opening the position or - depositing collateral to the position including base - fees, borrowing fees, and price impact fees - example: '0.0063' - outstandingBorrowFeeUsd: - type: string - description: >- - The outstanding borrow fees due / to be paid on - depositing collateral to the position - example: '0.1000' - positionCollateralSizeUsd: - type: string - description: The total position collateral size (USD) - example: '1124.45' - positionSizeTokenAmount: - type: string - description: >- - The total position size in the underlying collateral - token's token amount including leverage - example: '112445000' - positionSizeUsd: - type: string - description: The total position size (USD) including leverage - example: '1124.45' - priceImpactFeeBps: - type: string - description: >- - The price impact fee bps for opening the position - based on the position size. For more info on how the - price impact fee calculation works: - https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 - example: '1.3301' - priceImpactFeeUsd: - type: string - description: >- - The price impact fee (USD) for opening the position - based on the position size. For more info on how the - price impact fee calculation works: - https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 - example: '1.3301' - quoteOutAmount: - type: - - string - - 'null' - description: >- - The output amount from Jupiter's quote for the - collateral token if a token swap is required (i.e. if - the `inputMint` is not the same as the collateral - mint) - quotePriceSlippagePct: - type: - - string - - 'null' - description: >- - The price slippage percentage from Jupiter's quote if - a token swap is required (i.e. if the `inputMint` is - not the same as the collateral mint) - quoteSlippageBps: - type: - - string - - 'null' - description: >- - The slippage (BPS) from Jupiter's quote if a token - swap is required (i.e. if the `inputMint` is not the - same as the collateral mint) - side: - type: string - enum: - - long - - short - description: The position side - example: long - sizeTokenDelta: - type: string - description: >- - The change in the position's size in the token amount - for the position's collateral token. - example: '14420000' - expectedSizeUsdDelta: - type: string - description: >- - The expected change in the position's size in USD - before accounting for fees. - example: '112445' - expectedSizeUsdDeltaDiffPct: - type: string - description: >- - The difference between the expected change in the - position's size in USD before fees and the actual - change in the position's size in USD. - example: '14.45' - sizeUsdDelta: - type: string - description: >- - The actual change in the position's size in USD with - formatting. - example: '1124.45' - sizeUsdDeltaRaw: - type: string - description: The actual change in the position's size in USD. - example: '112445' - required: - - collateralLessThanFees - - entryPriceUsd - - leverage - - liquidationPriceUsd - - openFeeUsd - - outstandingBorrowFeeUsd - - positionCollateralSizeUsd - - positionSizeTokenAmount - - positionSizeUsd - - priceImpactFeeBps - - priceImpactFeeUsd - - quoteOutAmount - - quotePriceSlippagePct - - quoteSlippageBps - - side - - sizeTokenDelta - - expectedSizeUsdDelta - - expectedSizeUsdDeltaDiffPct - - sizeUsdDelta - - sizeUsdDeltaRaw - requireKeeperSignature: - type: boolean - description: DEPRECATED - serializedTxBase64: - type: - - string - - 'null' - description: >- - The serialized transaction (base64 encoded) containing the - instructions and given parameters for the increase - position request. The transaction can be deserialized, - signed by the owner of `walletAddress` and submitted - onchain to execute the increase position request - transactionType: - type: string - enum: - - mixed - - instant - - legacy + Raw USD value of the position's trade size + (including leverage) + example: '1234567800' + sizeTokenAmount: + type: string + description: >- + Raw token amount for the position's size scaled to + the custody token's mint decimals + example: '250000000' + collateralUsd: + type: string + description: Raw USD value of the position's collateral size + example: '250000000' + valueUsd: + type: string + description: >- + Raw USD value of the currently open position + including opening, closing, and borrowing fees + incurred + example: '120000000' + entryPriceUsd: + type: string + description: Raw USD value of the position's entry price + example: '123450000' + markPriceUsd: + type: string + description: Raw USD value of the position's mark price + example: '125000000' + liquidationPriceUsd: + type: string + description: Raw USD value of the position's liquidation price + example: '113450000' + openFeesUsd: + type: string + description: >- + Raw fee for opening the position in the integer + format corresponding to 6 decimal places (USD terms) + example: '100000' + closeFeesUsd: + type: string + description: >- + Raw fee for closing the position in the integer + format corresponding to 6 decimal places (USD terms) + example: '100000' + borrowFeesUsd: + type: string + description: >- + Raw outstanding borrow fees for the position in the + integer format corresponding to 6 decimal places + (USD terms) + example: '100000' + totalFeesUsd: + type: string + description: >- + Raw total fees for the position in the integer + format corresponding to 6 decimal places (USD terms) + example: '200000' + pnlBeforeFeesUsd: + type: string + description: >- + Raw value of the position's PNL before fees in the + integer format corresponding to 6 decimal places + (USD terms) + example: '1045000' + pnlBeforeFeesPct: + type: string + description: >- + The PNL change (%) from closing the position before + fees. + example: '20.24' + pnlAfterFeesUsd: + type: string + description: >- + Raw value of the position's PNL after fees in the + integer format corresponding to 6 decimal places + (USD terms) + example: '1045000' + pnlAfterFeesPct: + type: string + description: >- + The PNL change (%) from closing the position after + fees. + example: '-20.24' + createdTime: + type: number + description: UNIX timestamp of when the trade was created + example: 1722851463 + updatedTime: + type: number + example: 1722851463 + tpslRequests: + type: array + items: + type: object + properties: + positionRequestPubkey: + type: string + description: >- + The public key / address for the TP / SL + position request account + requestType: + type: string + enum: + - tp + - sl + description: >- + Returns `tp` if it is a take profit request, + `sl` if it is a stop loss request + desiredMint: + type: string + description: >- + The mint address for the TP / SL position + request account desired mint + example: So11111111111111111111111111111111111111112 + desiredToken: + type: string + enum: + - BTC + - ETH + - SOL + - USDC + - USDT + description: >- + The token symbol for the TP / SL position + request account desired mint + example: SOL + collateralUsdDelta: + type: string + description: >- + Raw collateral delta (USD) for the TP / SL in + the integer format corresponding to 6 decimal + places + example: '1234000000' + entirePosition: + type: boolean + description: >- + Whether the TP / SL request closes the entire + position + sizeUsd: + type: string + description: >- + Raw close size for the TP / SL in integer + format corresponding to the 6 decimal places + used by the USDC and USDT token mint + example: '1234000000' + sizePercentage: + type: string + description: >- + The percentage / ratio TP / SL size to the + position size + example: '12.34' + triggerPriceUsd: + type: + - string + - 'null' + description: >- + Raw trigger price for the TP / SL request in + integer format corresponding to the 6 decimals + places used by the USDC and USDT token mint + example: '20000000' + openTime: + type: string + description: >- + Unix timestamp of when the TP / SL request was + created + example: '1722851463' + required: + - positionRequestPubkey + - requestType + - desiredMint + - desiredToken + - collateralUsdDelta + - entirePosition + - sizeUsd + - sizePercentage + - triggerPriceUsd + - openTime + description: The active TP / SL requests for the position + required: + - asset + - assetMint + - collateralToken + - collateralMint + - positionPubkey + - side + - leverage + - sizeUsd + - sizeTokenAmount + - collateralUsd + - valueUsd + - entryPriceUsd + - markPriceUsd + - liquidationPriceUsd + - openFeesUsd + - closeFeesUsd + - borrowFeesUsd + - totalFeesUsd + - pnlBeforeFeesUsd + - pnlBeforeFeesPct + - pnlAfterFeesUsd + - pnlAfterFeesPct + - createdTime + - updatedTime + - tpslRequests + count: + type: number + required: + - dataList + - count + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /positions/close-all: + description: >- + Returns an array of serialized transactions to close all open positions + for the given wallet address. + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + walletAddress: + type: string + description: >- + The wallet address / public key for the trader to close all + open positions + required: + - walletAddress + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + serializedTxs: + type: array + items: + type: object + properties: + serializedTxBase64: + type: string + description: >- + The serialized transaction (base64 encoded) + containing the instructions and given parameters for + the close position instruction. The transaction can + be deserialized, signed by the owner of + `walletAddress` and submitted onchain to close the + position. + positionRequestPubkey: + type: string + description: >- + The public key / address for the position request to + close the position. + required: + - serializedTxBase64 + - positionRequestPubkey description: >- - Returns the type of serialized transaction to execute the - action. If the transaction type is `legacy`, the - transaction must be submitted by the client itself through - the RPC. If the transaction type is `instant`, the - transaction must be sent to the `POST - /transaction/execute` endpoint. + An array of base64-serialized transactions and the + `positionRequestPubkey` to close all positions. txMetadata: - type: - - object - - 'null' + type: object properties: blockhash: type: string description: >- The blockhash used for the serialized transaction. This blockhash must be used when submitting the signed - increase position transaction. + close position transaction. lastValidBlockHeight: type: string description: >- The block height used for the serialized transaction. This block height must be used when submitting the - signed increase position transaction. - transactionFeeLamports: - type: string - description: The transaction fee (in lamports) in decimal format. - example: '0.5' - accountRentLamports: - type: string - description: The account rent (in lamports) for the transaction - example: '0.5' + signed close position transaction. required: - blockhash - lastValidBlockHeight - - transactionFeeLamports - - accountRentLamports description: >- - Contains relevant metadata for the serialized transaction. - Null if no wallet address passed in. + Contains blockhash metadata for the serialized transaction + to submit and confirm the transactions. required: - - positionPubkey - - positionRequestPubkey - - tpslRequests - - quote - - requireKeeperSignature - - serializedTxBase64 - - transactionType + - serializedTxs - txMetadata + description: >- + An array of base64-serialized transactions and transaction + metadata to close all positions. '400': description: 400 Bad Request content: @@ -1487,20 +1370,35 @@ paths: application/json: schema: $ref: '#/components/schemas/errorSchema' - /pool-info: - description: Fetches the perpetuals base pool config info for the given market + /positions/collateral-limits: + description: >- + Returns the minimum and maximum token amounts for collateral deposits, as + well as the maximum token amount for collateral withdrawals. get: parameters: - in: query - name: mint - description: The token mint address for the perpetuals market + name: inputMint + description: >- + The mint address for the input token to deposit as collateral (e.g. + 'So11111111111111111111111111111111111111112' for 'SOL') schema: type: string - enum: - - So11111111111111111111111111111111111111112 - - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs - - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh - description: The token mint address for the perpetuals market + description: >- + The mint address for the input token to deposit as collateral + (e.g. 'So11111111111111111111111111111111111111112' for 'SOL') + example: So11111111111111111111111111111111111111112 + required: true + - in: query + name: positionPubkey + description: >- + The public key for the open position. Use the `GET positions` + endpoint to fetch the public key for the trader's open positions. + schema: + type: string + description: >- + The public key for the open position. Use the `GET positions` + endpoint to fetch the public key for the trader's open positions. + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 required: true responses: '200': @@ -1510,62 +1408,63 @@ paths: schema: type: object properties: - longAvailableLiquidity: + maxCollateralDepositTokenAmount: type: string description: >- - USD value of the available liquidity for long positions - for the market - example: '2500000' - longBorrowRatePercent: + The maximum token amount that can be deposited as + collateral for the given input mint token. + maxCollateralDepositUsd: type: string description: >- - Base borrow rate (%) for long positions. More info on how - the borrow rate is calculated here: - https://station.jup.ag/guides/perpetual-exchange/how-it-works#hourly-borrow-rate - example: '0.0026' - longUtilizationPercent: - type: string - description: Utilization rate (%) for long positions - example: '26.00' - shortAvailableLiquidity: + The maximum amount (USD) that can be deposited as + collateral for the given input mint token. The value is an + integer corresponding to the 6 decimals places used by the + USDC and USDT token mint. + minCollateralDepositTokenAmount: type: string description: >- - USD value of the available liquidity for short positions - for the market - example: '2500000' - shortBorrowRatePercent: + The minimum token amount that can be deposited as + collateral for the given input mint token. + minCollateralDepositUsd: type: string description: >- - Base borrow rate (%) for short positions. More info on how - the borrow rate is calculated here: - https://station.jup.ag/guides/perpetual-exchange/how-it-works#hourly-borrow-rate - example: '0.0026' - shortUtilizationPercent: + The minimum amount (USD) that can be deposited as + collateral for the given input mint token. The value is an + integer corresponding to the 6 decimals places used by the + USDC and USDT token mint. + maxCollateralWithdrawalTokenAmount: type: string - description: Utilization rate (%) for short positions - example: '26.00' - openFeePercent: + description: >- + The maximum collateral token amount that can be withdrawed + from the open position. + maxCollateralWithdrawalUsd: type: string - description: Base open fee (%) for the market - example: '0.06' - maxRequestExecutionSec: + description: >- + The maximum collateral (USD) that can be withdrawed from + the open position. The value is an integer corresponding + to the 6 decimals places used by the USDC and USDT token + mint. + minCollateralWithdrawalTokenAmount: type: string description: >- - The maximum duration that a position request can be active - (in seconds) before it is considered invalid. - maxPriceImpactFeePercent: + The minimum collateral token amount that can be withdrawed + from the open position. + minCollateralWithdrawalUsd: type: string - description: The maximum price impact fee (%) + description: >- + The minimum collateral (USD) that can be withdrawed from + the open position. The value is an integer corresponding + to the 6 decimals places used by the USDC and USDT token + mint. required: - - longAvailableLiquidity - - longBorrowRatePercent - - longUtilizationPercent - - shortAvailableLiquidity - - shortBorrowRatePercent - - shortUtilizationPercent - - openFeePercent - - maxRequestExecutionSec - - maxPriceImpactFeePercent + - maxCollateralDepositTokenAmount + - maxCollateralDepositUsd + - minCollateralDepositTokenAmount + - minCollateralDepositUsd + - maxCollateralWithdrawalTokenAmount + - maxCollateralWithdrawalUsd + - minCollateralWithdrawalTokenAmount + - minCollateralWithdrawalUsd '400': description: 400 Bad Request content: @@ -1590,9 +1489,82 @@ paths: application/json: schema: $ref: '#/components/schemas/errorSchema' - /jlp-info: - description: Fetches the JLP token info - get: + /positions/decrease: + description: >- + Uses the `decreasePositionParams` object from calling `GET + /positions/decrease/quote` and returns a base64-serialized transaction for + the request, the position request PDA, and the position PDA that acts as + the unique identifier for the position. + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + collateralUsdDelta: + type: + - string + - 'null' + description: >- + The amount of collateral to withdraw in USD from the + position. Must be an integer representing the USD amount + multiplied by 10^6 (1 million) to align with the 6 decimal + places used for USDC/USDT tokens on-chain. For example, to + decrease by $10 USD, set 'collateralUsdDelta' to 10000000; + for $20.50 USD, set 'collateralUsdDelta' to 20500000. + example: '10000000' + entirePosition: + type: boolean + default: false + description: >- + When set to `true`, this will close the position and + transfer the remaining collateral and realised profits (if + the position is profitable) to the trader. + example: false + maxSlippageBps: + type: string + default: '200' + description: >- + The maximum slippage in (BPS) for the asset's price when + executing the trade + example: '100' + positionPubkey: + type: string + description: >- + The public key for the open position. Use the `GET + positions` endpoint to fetch the public key for the trader's + open positions. + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + priorityFeeMicroLamports: + type: string + description: >- + Custom priority fee in microlamports for the transaction + (1,000,000 microlamports = 1 lamport). If not set, the API + will automatically set the optimal priority fee + receiveToken: + type: string + enum: + - BTC + - ETH + - SOL + - USDC + description: The token to receive. + sizeUsdDelta: + type: + - string + - 'null' + description: >- + The amount in USD to decrease the position size by. Must be + an integer representing the USD amount multiplied by 10^6 (1 + million) to align with the 6 decimal places used for + USDC/USDT tokens on-chain. For example, to decrease by $10 + USD, set 'sizeUsdDelta' to 10000000; for $20.50 USD, set + 'sizeUsdDelta' to 20500000. + example: '10000000' + required: + - positionPubkey + - receiveToken responses: '200': description: 200 OK @@ -1601,74 +1573,1654 @@ paths: schema: type: object properties: - aumUsd: - type: string - description: Total AUM in USD (raw value) - example: '123456789000000' - aumUsdFormatted: - type: string - description: Total AUM in USD (formatted) - example: '123,456.79' - aumLimitUsd: - type: string - description: AUM limit in USD (raw value) - example: '500000000000000' - aumLimitUsdFormatted: - type: string - description: AUM limit in USD (formatted) - example: '500,000' - jlpPriceUsd: - type: string - description: JLP price in USD (raw value) - example: '1234567' - jlpPriceUsdFormatted: - type: string - description: JLP price in USD (formatted) - example: '1.2346' - jlpTotalSupply: - type: string - description: Total JLP token supply - example: '100000000000' - jlpTotalSupplyFormatted: - type: string - description: Total JLP token supply (formatted) - example: '100,000' - jlpAprBps: - type: string - description: JLP APR in BPS - example: '100' - jlpAprPct: - type: string - description: JLP APR in percentage - example: '10.00' - jlpApyBps: - type: string - description: JLP APY in BPS - example: '100' - jlpApyPct: - type: string - description: JLP APY in percentage - example: '10.00' - jlpAprLastUpdatedTimestamp: - type: string - description: JLP APR last updated UNIX timestamp - example: '1715404800' - jlpRealizedFeeUsd: + positionPubkey: type: string description: >- - JLP realized fee in USD since the last APR / APY - calculation - example: '100000000' - custodies: - type: array - items: - type: object - properties: - pubkey: - type: string - description: Custody public key - example: '11111111111111111111111111111111' - symbol: + The unique identifier (i.e. a program derived address) for + the position account. Use this address to find the + position account onchain. + quote: + type: object + properties: + closeFeeUsd: + type: string + description: >- + The base close fee for closing the position or + withdrawing collateral (raw value with 6 decimal + places) + example: '100000' + collateralUsdDelta: + type: string + description: >- + The change in collateral amount in USD (raw value with + 6 decimal places) + example: '10000000' + leverage: + type: string + description: >- + The leverage amount for the position after the + decrease + example: '2.99' + liquidationPriceUsd: + type: string + description: >- + The liquidation price in USD (raw value with 6 decimal + places) + example: '13240000' + outstandingBorrowFeeUsd: + type: string + description: >- + The outstanding borrow fees due / to be paid on + closing the position (raw value with 6 decimal places) + example: '100000' + pnlAfterFeesUsd: + type: string + description: >- + The position PNL after fees (raw value with 6 decimal + places) + example: '1045000' + pnlAfterFeesPercent: + type: string + description: >- + The PNL change (%) from closing the position after + fees + example: '-20.24' + pnlBeforeFeesUsd: + type: string + description: >- + The position PNL before fees (raw value with 6 decimal + places) + example: '1045000' + pnlBeforeFeesPercent: + type: string + description: >- + The PNL change (%) from closing the position before + fees + example: '20.24' + positionCollateralUsd: + type: string + description: >- + The total position collateral size in USD after the + decrease (raw value with 6 decimal places) + example: '100000000' + positionSizeUsd: + type: string + description: >- + The total position size in USD including leverage + after the decrease (raw value with 6 decimal places) + example: '10000000' + priceImpactFeeBps: + type: string + description: >- + The price impact fee bps for closing the position + based on the position size. For more info on how the + price impact fee calculation works: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '1.3301' + priceImpactFeeUsd: + type: string + description: >- + The price impact fee for closing the position based on + the position size (raw value with 6 decimal places). + For more info: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '13301' + side: + type: string + enum: + - long + - short + description: The position side + example: long + sizeUsdDelta: + type: string + description: >- + The change in position size in USD (raw value with 6 + decimal places) + example: '10000000' + totalFeeUsd: + type: string + description: >- + The total fee in USD for closing or withdrawing + collateral including base fees, borrowing fees, and + price impact fees (raw value with 6 decimal places) + example: '100000' + transferAmountToken: + type: string + description: >- + The collateral token amount to transfer to the owner + after withdrawing collateral or closing the position + (raw value) + example: '100000000' + transferAmountUsd: + type: string + description: >- + The collateral token amount in USD to transfer to the + owner (raw value with 6 decimal places) + example: '10000000' + transferTokenMint: + type: string + description: >- + The mint address for the token used to transfer the + collateral withdrawal or closing position amount + example: So11111111111111111111111111111111111111112 + required: + - closeFeeUsd + - collateralUsdDelta + - leverage + - liquidationPriceUsd + - outstandingBorrowFeeUsd + - pnlAfterFeesUsd + - pnlAfterFeesPercent + - pnlBeforeFeesUsd + - pnlBeforeFeesPercent + - positionCollateralUsd + - positionSizeUsd + - priceImpactFeeBps + - priceImpactFeeUsd + - side + - sizeUsdDelta + - totalFeeUsd + - transferAmountToken + - transferAmountUsd + - transferTokenMint + serializedTxBase64: + type: string + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the decrease + position request. The transaction can be deserialized, + signed by the owner of `walletAddress` and submitted + onchain to execute the decrease position request + txMetadata: + type: object + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + decrease position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed decrease position transaction. + transactionFeeLamports: + type: string + description: >- + The transaction fee in lamports (1 SOL = 1,000,000,000 + lamports) + example: '5000' + accountRentLamports: + type: string + description: >- + The account rent in lamports for the transaction (1 + SOL = 1,000,000,000 lamports) + example: '2039280' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: Contains relevant metadata for the serialized transaction. + required: + - positionPubkey + - quote + - serializedTxBase64 + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /positions/increase: + description: >- + Uses the `increasePositionParams` object from calling `GET + /positions/increase/quote` and returns a base64-serialized transaction for + the request, the position request PDA, and the position PDA that acts as + the unique identifier for the position. + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + asset: + type: string + enum: + - BTC + - ETH + - SOL + description: The asset or market to trade against + example: SOL + inputToken: + type: string + enum: + - BTC + - ETH + - SOL + - USDC + description: >- + The token symbol for the input token used to fund the + position + example: SOL + inputTokenAmount: + type: string + description: >- + The amount of tokens for the input token to open the + position or deposit collateral. NOTE: The token amount needs + to be an integer and must conform to the token mint decimals + specified onchain. For example, to deposit 1 SOL, the value + would be '1000000000' (9 decimals) + example: '1000000000' + leverage: + type: string + description: >- + Leverage of the increase position, up to 1 decimal place. + Either provide 'leverage' or 'sizeUsdDelta' to open a trade. + Min leverage is '1.1'. Max leverage for SOL is 250.0 + example: '11.5' + maxSlippageBps: + type: string + description: >- + The maximum slippage in (BPS) for the asset's price when + executing trade + example: '100' + priorityFeeMicroLamports: + type: string + description: >- + Custom priority fee in microlamports for the transaction + (1,000,000 microlamports = 1 lamport). If not set, the API + will automatically set the optimal priority fee + side: + type: string + enum: + - long + - short + description: Side for the trade + sizeUsdDelta: + type: string + description: >- + The amount in USD to increase the position size by. Must be + an integer representing the USD amount multiplied by 10^6 (1 + million) to align with the 6 decimal places used for + USDC/USDT tokens on-chain. For example, to increase the + position size by $10 USD, set 'sizeUsdDelta' to 10000000; + for $0.50 USD, set 'sizeUsdDelta' to 500000. Either provide + 'leverage' or 'sizeUsdDelta'. + example: '10000000' + tpsl: + type: + - array + - 'null' + items: + type: object + properties: + receiveToken: + type: string + enum: + - BTC + - ETH + - SOL + - USDC + description: The token to receive when the TPSL is executed. + triggerPrice: + type: string + description: >- + Trigger price at which the TP / SL request will be + executed. The value must be an integer corresponding + to 6 decimal places. For example, to set a trigger + price of $20, pass in 20000000 + example: '20000000' + requestType: + type: string + enum: + - tp + - sl + description: >- + Pass in `tp` to set a take profit request or `sl` to + set a stop loss request + required: + - receiveToken + - triggerPrice + - requestType + maxItems: 2 + description: >- + TPSL requests to set. TPSL requests can only be set for + positions that 150x leverage or below. Only 2 TPSLs can be + set at a time. + walletAddress: + type: string + description: >- + The wallet address / public key for the trader, Required + when opening a new position. + required: + - asset + - inputToken + - inputTokenAmount + - maxSlippageBps + - side + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + positionPubkey: + type: + - string + - 'null' + description: >- + The unique identifier (i.e. a program derived address) for + the position account. Use this address to find the + position account onchain. + quote: + type: object + properties: + averagePriceUsd: + type: string + description: >- + The average price for the position in USD (raw value + with 6 decimal places) + example: '10000000' + collateralUsdDelta: + type: string + description: >- + The change in collateral amount in USD (raw value with + 6 decimal places) + example: '1124450000' + leverage: + type: string + description: The leverage amount for the position + example: '2.99' + liquidationPriceUsd: + type: string + description: >- + The liquidation price in USD (raw value with 6 decimal + places) + example: '13240000' + openFeeUsd: + type: string + description: >- + The total fee in USD for opening the position or + depositing collateral including base fees, borrowing + fees, and price impact fees (raw value with 6 decimal + places) + example: '100000' + outstandingBorrowFeeUsd: + type: string + description: >- + The outstanding borrow fees due / to be paid on + depositing collateral to the position (raw value with + 6 decimal places) + example: '100000' + positionCollateralUsd: + type: string + description: >- + The total position collateral size in USD after the + increase (raw value with 6 decimal places) + example: '100000000' + positionSizeUsd: + type: string + description: >- + The total position size in USD including leverage + after the increase (raw value with 6 decimal places) + example: '10000000' + priceImpactFeeBps: + type: string + description: >- + The price impact fee bps for opening the position + based on the position size. For more info on how the + price impact fee calculation works: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '100' + priceImpactFeeUsd: + type: string + description: >- + The price impact fee in USD for opening the position + based on the position size (raw value with 6 decimal + places). For more info: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '13301' + side: + type: string + enum: + - long + - short + description: The position side + example: long + sizeUsdDelta: + type: string + description: >- + The change in position size in USD (raw value with 6 + decimal places) + example: '1124450000' + sizeTokenDelta: + type: string + description: >- + The change in the position's size in the token amount + for the position's collateral token. + example: '14420000' + required: + - averagePriceUsd + - collateralUsdDelta + - leverage + - liquidationPriceUsd + - openFeeUsd + - outstandingBorrowFeeUsd + - positionCollateralUsd + - positionSizeUsd + - priceImpactFeeBps + - priceImpactFeeUsd + - side + - sizeUsdDelta + - sizeTokenDelta + serializedTxBase64: + type: + - string + - 'null' + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the increase + position request. The transaction can be deserialized, + signed by the owner of `walletAddress` and submitted + onchain to execute the increase position request + tpsl: + type: array + items: + type: object + properties: + hasProfit: + type: boolean + description: Whether the TPSL request is profitable + pnlUsd: + type: string + description: The estimated PNL (USD) delta for the TPSL request + pnlPercent: + type: string + description: The estimated PNL percentage for the TPSL request + pubkey: + type: string + description: >- + The pubkey for the TPSL. Use this address to find + the TPSL account onchain + requestType: + type: string + enum: + - tp + - sl + description: The type of TPSL request + required: + - hasProfit + - pnlUsd + - pnlPercent + - pubkey + - requestType + description: TPSL requests created with the increase position + txMetadata: + type: + - object + - 'null' + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + increase position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed increase position transaction. + transactionFeeLamports: + type: string + description: >- + The transaction fee in lamports (1 SOL = 1,000,000,000 + lamports) + example: '5000' + accountRentLamports: + type: string + description: >- + The account rent in lamports for creating the position + account (1 SOL = 1,000,000,000 lamports) + example: '2039280' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: >- + Contains relevant metadata for the serialized transaction. + Null if no wallet address passed in. + required: + - positionPubkey + - quote + - serializedTxBase64 + - tpsl + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /positions/increase-with-fee: + description: >- + Uses the `increasePositionParams` object from calling `GET + /positions/increase/quote` and returns a base64-serialized transaction for + the request, the position request PDA, and the position PDA that acts as + the unique identifier for the position. + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + asset: + type: string + enum: + - BTC + - ETH + - SOL + description: >- + The asset or market to trade against. Required when opening + a new position. 'SOL' = + 'So11111111111111111111111111111111111111112', 'ETH' = + '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs', 'BTC' = + '3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh' + example: SOL + feeToken: + type: string + enum: + - USDC + description: >- + The token symbol for the fee token. Currently only USDC is + supported. Must be the same as input token. + feeTokenAmount: + type: string + description: >- + The amount of fee tokens to send to `feeReceiver`. The value + must match the token mint decimals specified in `feeToken` + (e.g., for USDC with 6 decimals, 1000000 = 1 USDC) + example: '1000000' + feeReceiver: + type: string + description: >- + The token address (ATA) to receive the fee specified in + `feeTokenAmount`. The ATA must match the token mint + specified in `feeToken` + inputToken: + type: string + enum: + - BTC + - ETH + - SOL + - USDC + description: >- + The token symbol for the input token used to fund the + position. Must be the same as fee token. + example: SOL + inputTokenAmount: + type: string + description: >- + The amount of tokens for the input token to open the + position or deposit collateral. NOTE: The token amount needs + to be an integer and must conform to the token mint decimals + specified onchain. For example, to deposit 1 SOL, the value + would be '1000000000' (9 decimals) + example: '1000000000' + leverage: + type: string + description: >- + Leverage of the increase position, up to 1 decimal place. + Either provide 'leverage' or 'sizeUsdDelta' to open a trade. + Min leverage is '1.1'. Max leverage for SOL is 100.0. Max + leverage for BTC / ETH is 150.0 + example: '11.5' + maxSlippageBps: + type: string + description: >- + The maximum slippage in (BPS) for the custody token price + when executing the decrease position trade + example: '100' + priorityFeeMicroLamports: + type: string + description: >- + Custom priority fee in microlamports for the transaction + (1,000,000 microlamports = 1 lamport). If not set, the API + will automatically set the optimal priority fee + side: + type: string + enum: + - long + - short + description: Required when opening a new position + sizeUsdDelta: + type: string + description: >- + The amount in USD to increase the position size by. Must be + an integer representing the USD amount multiplied by 10^6 (1 + million) to align with the 6 decimal places used for + USDC/USDT tokens on-chain. For example, to increase the + position size by $10 USD, set 'sizeUsdDelta' to 10000000; + for $0.50 USD, set 'sizeUsdDelta' to 500000. Either provide + leverage or sizeUsdDelta. + example: '10000000' + tpsl: + type: + - array + - 'null' + items: + type: object + properties: + receiveToken: + type: string + enum: + - BTC + - ETH + - SOL + - USDC + description: The token to receive when the TPSL is executed. + triggerPrice: + type: string + description: >- + Trigger price at which the TP / SL request will be + executed. The value must be an integer corresponding + to 6 decimal places. For example, to set a trigger + price of $20, pass in 20000000 + example: '20000000' + requestType: + type: string + enum: + - tp + - sl + description: >- + Pass in `tp` to set a take profit request or `sl` to + set a stop loss request + required: + - receiveToken + - triggerPrice + - requestType + description: TPSL requests to set + walletAddress: + type: string + description: >- + The wallet address / public key for the trader, Required + when opening a new position. + required: + - asset + - feeToken + - feeTokenAmount + - feeReceiver + - inputToken + - inputTokenAmount + - maxSlippageBps + - side + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + positionPubkey: + type: + - string + - 'null' + description: >- + The unique identifier (i.e. a program derived address) for + the position account. Use this address to find the + position account onchain. + quote: + type: object + properties: + collateralUsdDelta: + type: string + description: >- + The change in collateral amount in USD (raw value with + 6 decimal places) + example: '1124450000' + collateralUsdDeltaFormatted: + type: string + description: >- + The change in collateral amount in USD (human-readable + format) + example: '1124.45' + leverage: + type: string + description: The leverage amount for the position + example: '2.99' + integratorFeeTokenMint: + type: string + description: The token mint for the integrator fee token + integratorFeeTokenAmount: + type: string + description: The amount of the integrator fee token + integratorFeeUsd: + type: string + description: >- + The estimated integrator fee in USD (raw value with 6 + decimal places) + integratorFeeUsdFormatted: + type: string + description: >- + The estimated integrator fee in USD (human-readable + format) + liquidationPriceUsd: + type: string + description: >- + The liquidation price in USD (raw value with 6 decimal + places) + example: '13240000' + liquidationPriceUsdFormatted: + type: string + description: The liquidation price in USD (human-readable format) + example: '13.24' + openFeeUsd: + type: string + description: >- + The total fee in USD for opening the position or + depositing collateral including base fees, borrowing + fees, and price impact fees (raw value with 6 decimal + places) + example: '100000' + openFeeUsdFormatted: + type: string + description: >- + The total fee in USD for opening the position or + depositing collateral including base fees, borrowing + fees, and price impact fees (human-readable format) + example: '0.1000' + outstandingBorrowFeeUsd: + type: string + description: >- + The outstanding borrow fees due / to be paid on + depositing collateral to the position (raw value with + 6 decimal places) + example: '100000' + outstandingBorrowFeeUsdFormatted: + type: string + description: >- + The outstanding borrow fees due / to be paid on + depositing collateral to the position (human-readable + format) + example: '0.1000' + positionCollateralUsd: + type: string + description: >- + The total position collateral size in USD after the + increase (raw value with 6 decimal places) + example: '100000000' + positionCollateralUsdFormatted: + type: string + description: >- + The total position collateral size in USD after the + increase (human-readable format) + example: '100.00' + positionPriceUsd: + type: string + description: >- + The position's average price in USD (raw value with 6 + decimal places) + example: '2990000' + positionPriceUsdFormatted: + type: string + description: >- + The position's average price in USD (human-readable + format) + example: '2.99' + positionSizeUsd: + type: string + description: >- + The total position size in USD including leverage + after the increase (raw value with 6 decimal places) + example: '10000000' + positionSizeUsdFormatted: + type: string + description: >- + The total position size in USD including leverage + after the increase (human-readable format) + example: '10.00' + priceImpactFeeBps: + type: string + description: >- + The price impact fee bps for opening the position + based on the position size. For more info on how the + price impact fee calculation works: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '1.3301' + priceImpactFeeUsd: + type: string + description: >- + The price impact fee in USD for opening the position + based on the position size (raw value with 6 decimal + places). For more info: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '13301' + priceImpactFeeUsdFormatted: + type: string + description: >- + The price impact fee in USD for opening the position + based on the position size (human-readable format). + For more info: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '0.0133' + side: + type: string + enum: + - long + - short + description: The position side + example: long + sizeUsdDelta: + type: string + description: >- + The change in position size in USD (raw value with 6 + decimal places) + example: '1124450000' + sizeUsdDeltaFormatted: + type: string + description: >- + The change in position size in USD (human-readable + format) + example: '1124.45' + required: + - collateralUsdDelta + - collateralUsdDeltaFormatted + - leverage + - integratorFeeTokenMint + - integratorFeeTokenAmount + - integratorFeeUsd + - integratorFeeUsdFormatted + - liquidationPriceUsd + - liquidationPriceUsdFormatted + - openFeeUsd + - openFeeUsdFormatted + - outstandingBorrowFeeUsd + - outstandingBorrowFeeUsdFormatted + - positionCollateralUsd + - positionCollateralUsdFormatted + - positionPriceUsd + - positionPriceUsdFormatted + - positionSizeUsd + - positionSizeUsdFormatted + - priceImpactFeeBps + - priceImpactFeeUsd + - priceImpactFeeUsdFormatted + - side + - sizeUsdDelta + - sizeUsdDeltaFormatted + serializedTxBase64: + type: + - string + - 'null' + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the increase + position request. The transaction can be deserialized, + signed by the owner of `walletAddress` and submitted + onchain to execute the increase position request + tpsl: + type: array + items: + type: object + properties: + hasProfit: + type: boolean + description: Whether the TPSL request is profitable + pnlUsd: + type: string + description: The estimated PNL (USD) delta for the TPSL request + pnlUsdFormatted: + type: string + description: The estimated PNL (USD) delta for the TPSL request + pnlPercent: + type: string + description: The estimated PNL percentage for the TPSL request + pubkey: + type: string + description: >- + The pubkey for the TPSL. Use this address to find + the TPSL account onchain + requestType: + type: string + enum: + - tp + - sl + description: The type of TPSL request + required: + - hasProfit + - pnlUsd + - pnlUsdFormatted + - pnlPercent + - pubkey + - requestType + description: TPSL requests created with the increase position + txMetadata: + type: + - object + - 'null' + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + increase position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed increase position transaction. + transactionFeeLamports: + type: string + description: >- + The transaction fee in lamports (1 SOL = 1,000,000,000 + lamports) + example: '5000' + accountRentLamports: + type: string + description: >- + The account rent in lamports for creating the position + account (1 SOL = 1,000,000,000 lamports) + example: '2039280' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: >- + Contains relevant metadata for the serialized transaction. + Null if no wallet address passed in. + required: + - positionPubkey + - quote + - serializedTxBase64 + - tpsl + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /positions/decrease-with-fee: + description: >- + Uses the `decreasePositionParams` object from calling `GET + /positions/decrease/quote` and returns a base64-serialized transaction for + the request, the position request PDA, and the position PDA that acts as + the unique identifier for the position. + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + collateralUsdDelta: + type: + - string + - 'null' + description: >- + The amount of collateral to withdraw in USD from the + position. Must be an integer representing the USD amount + multiplied by 10^6 (1 million) to align with the 6 decimal + places used for USDC/USDT tokens on-chain. For example, to + decrease by $10 USD, set 'collateralUsdDelta' to 10000000; + for $20.50 USD, set 'collateralUsdDelta' to 20500000. + example: '10000000' + entirePosition: + type: boolean + default: false + description: >- + When set to `true`, this will close the position and + transfer the remaining collateral and realised profits (if + the position is profitable) to the trader. + example: false + feeToken: + type: string + enum: + - USDC + description: >- + The token symbol for the fee token. Currently only USDC is + supported + feeTokenAmount: + type: string + description: >- + The amount of fee tokens to send to `feeReceiver`. The value + must match the token mint decimals specified in `feeToken` + (e.g., for USDC with 6 decimals, 1000000 = 1 USDC) + example: '1000000' + feeReceiver: + type: string + description: >- + The token address (ATA) to receive the fee specified in + `feeTokenAmount`. The ATA must match the token mint + specified in `feeToken` + maxSlippageBps: + type: string + default: '200' + description: >- + The maximum slippage in (BPS) for the token swap (if + required) and the token price when executing the increase + position trade + example: '100' + positionPubkey: + type: string + description: >- + The public key for the open position. Use the `GET + positions` endpoint to fetch the public key for the trader's + open positions. + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + priorityFeeMicroLamports: + type: string + description: >- + Custom priority fee in microlamports for the transaction + (1,000,000 microlamports = 1 lamport). If not set, the API + will automatically set the optimal priority fee + receiveToken: + type: string + enum: + - BTC + - ETH + - SOL + - USDC + description: The token to receive. + sizeUsdDelta: + type: + - string + - 'null' + description: >- + The amount in USD to decrease the position size by. Must be + an integer representing the USD amount multiplied by 10^6 (1 + million) to align with the 6 decimal places used for + USDC/USDT tokens on-chain. For example, to decrease by $10 + USD, set 'sizeUsdDelta' to 10000000; for $20.50 USD, set + 'sizeUsdDelta' to 20500000. + example: '10000000' + required: + - feeToken + - feeTokenAmount + - feeReceiver + - positionPubkey + - receiveToken + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + positionPubkey: + type: string + description: >- + The unique identifier (i.e. a program derived address) for + the position account. Use this address to find the + position account onchain. + quote: + type: object + properties: + closeFeeUsd: + type: string + description: >- + The base close fee for closing the position or + withdrawing collateral (raw value with 6 decimal + places) + example: '100000' + closeFeeUsdFormatted: + type: string + description: >- + The base close fee for closing the position or + withdrawing collateral (human-readable format) + example: '0.1000' + collateralUsdDelta: + type: string + description: >- + The change in collateral amount in USD (raw value with + 6 decimal places) + example: '10000000' + collateralUsdDeltaFormatted: + type: string + description: >- + The change in collateral amount in USD (human-readable + format) + example: '10.00' + integratorFeeTokenMint: + type: string + description: The token mint for the integrator fee token + integratorFeeTokenAmount: + type: string + description: The amount of the integrator fee token + integratorFeeUsd: + type: string + description: >- + The estimated integrator fee in USD (raw value with 6 + decimal places) + integratorFeeUsdFormatted: + type: string + description: >- + The estimated integrator fee in USD (human-readable + format) + leverage: + type: string + description: >- + The leverage amount for the position after the + decrease + example: '2.99' + liquidationPriceUsd: + type: string + description: >- + The liquidation price in USD (raw value with 6 decimal + places) + example: '13240000' + liquidationPriceUsdFormatted: + type: string + description: The liquidation price in USD (human-readable format) + example: '13.24' + outstandingBorrowFeeUsd: + type: string + description: >- + The outstanding borrow fees due / to be paid on + closing the position (raw value with 6 decimal places) + example: '100000' + outstandingBorrowFeeUsdFormatted: + type: string + description: >- + The outstanding borrow fees due / to be paid on + closing the position (human-readable format) + example: '0.1000' + pnlAfterFeesUsd: + type: string + description: >- + The position PNL after fees (raw value with 6 decimal + places) + example: '1045000' + pnlAfterFeesUsdFormatted: + type: string + description: The position PNL after fees (human-readable format) + example: '1.045' + pnlAfterFeesPercent: + type: string + description: >- + The PNL change (%) from closing the position after + fees + example: '-20.24' + pnlBeforeFeesUsd: + type: string + description: >- + The position PNL before fees (raw value with 6 decimal + places) + example: '1045000' + pnlBeforeFeesUsdFormatted: + type: string + description: The position PNL before fees (human-readable format) + example: '1.045' + pnlBeforeFeesPercent: + type: string + description: >- + The PNL change (%) from closing the position before + fees + example: '20.24' + positionCollateralUsd: + type: string + description: >- + The total position collateral size in USD after the + decrease (raw value with 6 decimal places) + example: '100000000' + positionCollateralUsdFormatted: + type: string + description: >- + The total position collateral size in USD after the + decrease (human-readable format) + example: '100.00' + positionSizeUsd: + type: string + description: >- + The total position size in USD including leverage + after the decrease (raw value with 6 decimal places) + example: '10000000' + positionSizeUsdFormatted: + type: string + description: >- + The total position size in USD including leverage + after the decrease (human-readable format) + example: '10.00' + priceImpactFeeBps: + type: string + description: >- + The price impact fee bps for closing the position + based on the position size. For more info on how the + price impact fee calculation works: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '1.3301' + priceImpactFeeUsd: + type: string + description: >- + The price impact fee for closing the position based on + the position size (raw value with 6 decimal places). + For more info: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '13301' + priceImpactFeeUsdFormatted: + type: string + description: >- + The price impact fee for closing the position based on + the position size (human-readable format). For more + info: + https://www.jupresear.ch/t/jupiter-perpetuals-price-impact-fee-mechanism/17140 + example: '0.0133' + side: + type: string + enum: + - long + - short + description: The position side + example: long + sizeUsdDelta: + type: string + description: >- + The change in position size in USD (raw value with 6 + decimal places) + example: '10000000' + sizeUsdDeltaFormatted: + type: string + description: >- + The change in position size in USD (human-readable + format) + example: '10.00' + totalFeeUsd: + type: string + description: >- + The total fee in USD for closing or withdrawing + collateral including base fees, borrowing fees, and + price impact fees (raw value with 6 decimal places) + example: '100000' + totalFeeUsdFormatted: + type: string + description: >- + The total fee in USD for closing or withdrawing + collateral including base fees, borrowing fees, and + price impact fees (human-readable format) + example: '0.1000' + transferAmountToken: + type: string + description: >- + The collateral token amount to transfer to the owner + after withdrawing collateral or closing the position + (raw value) + example: '100000000' + transferAmountUsd: + type: string + description: >- + The collateral token amount in USD to transfer to the + owner (raw value with 6 decimal places) + example: '10000000' + transferAmountUsdFormatted: + type: string + description: >- + The collateral token amount in USD to transfer to the + owner (human-readable format) + example: '10.00' + transferTokenMint: + type: string + description: >- + The mint address for the token used to transfer the + collateral withdrawal or closing position amount + example: So11111111111111111111111111111111111111112 + required: + - closeFeeUsd + - closeFeeUsdFormatted + - collateralUsdDelta + - collateralUsdDeltaFormatted + - integratorFeeTokenMint + - integratorFeeTokenAmount + - integratorFeeUsd + - integratorFeeUsdFormatted + - leverage + - liquidationPriceUsd + - liquidationPriceUsdFormatted + - outstandingBorrowFeeUsd + - outstandingBorrowFeeUsdFormatted + - pnlAfterFeesUsd + - pnlAfterFeesUsdFormatted + - pnlAfterFeesPercent + - pnlBeforeFeesUsd + - pnlBeforeFeesUsdFormatted + - pnlBeforeFeesPercent + - positionCollateralUsd + - positionCollateralUsdFormatted + - positionSizeUsd + - positionSizeUsdFormatted + - priceImpactFeeBps + - priceImpactFeeUsd + - priceImpactFeeUsdFormatted + - side + - sizeUsdDelta + - sizeUsdDeltaFormatted + - totalFeeUsd + - totalFeeUsdFormatted + - transferAmountToken + - transferAmountUsd + - transferAmountUsdFormatted + - transferTokenMint + serializedTxBase64: + type: string + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the decrease + position request. The transaction can be deserialized, + signed by the owner of `walletAddress` and submitted + onchain to execute the decrease position request + txMetadata: + type: object + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + decrease position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed decrease position transaction. + transactionFeeLamports: + type: string + description: >- + The transaction fee in lamports (1 SOL = 1,000,000,000 + lamports) + example: '5000' + accountRentLamports: + type: string + description: >- + The account rent in lamports for the transaction (1 + SOL = 1,000,000,000 lamports) + example: '2039280' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: Contains relevant metadata for the serialized transaction. + required: + - positionPubkey + - quote + - serializedTxBase64 + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /pool-info: + description: Fetches the perpetuals base pool config info for the given market + get: + parameters: + - in: query + name: mint + description: The token mint address for the perpetuals market + schema: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + description: The token mint address for the perpetuals market + required: true + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + longAvailableLiquidity: + type: string + description: >- + USD value of the available liquidity for long positions + for the market + example: '2500000' + longBorrowRatePercent: + type: string + description: >- + Base borrow rate (%) for long positions. More info on how + the borrow rate is calculated here: + https://station.jup.ag/guides/perpetual-exchange/how-it-works#hourly-borrow-rate + example: '0.0026' + longUtilizationPercent: + type: string + description: Utilization rate (%) for long positions + example: '26.00' + shortAvailableLiquidity: + type: string + description: >- + USD value of the available liquidity for short positions + for the market + example: '2500000' + shortBorrowRatePercent: + type: string + description: >- + Base borrow rate (%) for short positions. More info on how + the borrow rate is calculated here: + https://station.jup.ag/guides/perpetual-exchange/how-it-works#hourly-borrow-rate + example: '0.0026' + shortUtilizationPercent: + type: string + description: Utilization rate (%) for short positions + example: '26.00' + openFeePercent: + type: string + description: Base open fee (%) for the market + example: '0.06' + maxRequestExecutionSec: + type: string + description: >- + The maximum duration that a position request can be active + (in seconds) before it is considered invalid. + maxPriceImpactFeePercent: + type: string + description: The maximum price impact fee (%) + required: + - longAvailableLiquidity + - longBorrowRatePercent + - longUtilizationPercent + - shortAvailableLiquidity + - shortBorrowRatePercent + - shortUtilizationPercent + - openFeePercent + - maxRequestExecutionSec + - maxPriceImpactFeePercent + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /jlp-info: + description: Fetches the JLP token info + get: + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + aumUsd: + type: string + description: Total AUM in USD (raw value) + example: '123456789000000' + aumUsdFormatted: + type: string + description: Total AUM in USD (formatted) + example: '123,456.79' + aumLimitUsd: + type: string + description: AUM limit in USD (raw value) + example: '500000000000000' + aumLimitUsdFormatted: + type: string + description: AUM limit in USD (formatted) + example: '500,000' + jlpPriceUsd: + type: string + description: JLP price in USD (raw value) + example: '1234567' + jlpPriceUsdFormatted: + type: string + description: JLP price in USD (formatted) + example: '1.2346' + jlpTotalSupply: + type: string + description: Total JLP token supply + example: '100000000000' + jlpTotalSupplyFormatted: + type: string + description: Total JLP token supply (formatted) + example: '100,000' + jlpAprBps: + type: string + description: JLP APR in BPS + example: '100' + jlpAprPct: + type: string + description: JLP APR in percentage + example: '10.00' + jlpApyBps: + type: string + description: JLP APY in BPS + example: '100' + jlpApyPct: + type: string + description: JLP APY in percentage + example: '10.00' + jlpAprLastUpdatedTimestamp: + type: string + description: JLP APR last updated UNIX timestamp + example: '1715404800' + jlpRealizedFeeUsd: + type: string + description: >- + JLP realized fee in USD since the last APR / APY + calculation + example: '100000000' + custodies: + type: array + items: + type: object + properties: + pubkey: + type: string + description: Custody public key + example: '11111111111111111111111111111111' + symbol: type: string description: Token symbol example: SOL @@ -1686,125 +3238,628 @@ paths: example: '12345678900000' aumUsdFormatted: type: string - description: Custody AUM in USD (formatted) - example: '123456.79' - aumTokenAmount: + description: Custody AUM in USD (formatted) + example: '123456.79' + aumTokenAmount: + type: string + description: Custody AUM in token amount + example: '123456789' + aumTokenAmountFormatted: + type: string + description: Custody AUM in token amount (formatted) + example: '123,456.79' + currentWeightagePct: + type: string + description: Current weight percentage + example: '25.50' + targetWeightagePct: + type: string + description: Target weight percentage + example: '30.00' + utilizationPct: + type: string + description: Utilization percentage + example: '45.20' + owned: + type: string + description: >- + Tokens owned by the JLP pool scaled to the token's + mint decimals + example: '123456789' + locked: + type: string + description: >- + Tokens locked by the JLP pool for trader's + collateral and leverage scaled to the token's mint + decimals + example: '123456789' + guaranteedUsd: + type: string + description: >- + Current long sizes for the token scaled to the USDC + decimals (6) + example: '123456789' + globalShortSizes: + type: string + description: >- + Current short sizes for the token scaled to the USDC + decimals (6) + example: '123456789' + globalShortAveragePrice: + type: string + description: >- + Average price of all short positions for the token + scaled to the USDC decimals (6) + example: '123456789' + shortPnlDelta: + type: string + description: Short PnL delta scaled to the USDC decimals (6) + example: '123456789' + shortTradersHasProfit: + type: boolean + description: >- + Boolean to indicate whether short traders are in + profit + example: true + totalStakedAmountLamports: + type: string + description: Total staked SOL lamports (zero for other assets) + example: '123456789' + totalStakedAmountUsd: + type: string + description: >- + Total staked SOL lamports in USD scaled to 6 decimal + places as per the USDC mint (zero for other assets) + example: '123456789' + totalStakedAmountUsdFormatted: + type: string + description: >- + Formatted total staked SOL lamports in USD scaled to + 6 decimal places as per the USDC mint (zero for + other assets) + example: '123456789' + required: + - pubkey + - symbol + - name + - mint + - aumUsd + - aumUsdFormatted + - aumTokenAmount + - aumTokenAmountFormatted + - currentWeightagePct + - targetWeightagePct + - utilizationPct + - owned + - locked + - guaranteedUsd + - globalShortSizes + - globalShortAveragePrice + - shortPnlDelta + - shortTradersHasProfit + - totalStakedAmountLamports + - totalStakedAmountUsd + - totalStakedAmountUsdFormatted + description: List of custody information + required: + - aumUsd + - aumUsdFormatted + - aumLimitUsd + - aumLimitUsdFormatted + - jlpPriceUsd + - jlpPriceUsdFormatted + - jlpTotalSupply + - jlpTotalSupplyFormatted + - jlpAprBps + - jlpAprPct + - jlpApyBps + - jlpApyPct + - jlpAprLastUpdatedTimestamp + - jlpRealizedFeeUsd + - custodies + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /trades: + description: Fetches the trade history for the given wallet address + get: + parameters: + - in: query + name: action + schema: + type: string + enum: + - Increase + - Decrease + - in: query + name: createdAtAfter + description: >- + Fetches trades with a 'createdAt' date that is greater or equal to + the given 'createdAtAfter' UNIX timestamp' + schema: + type: string + description: >- + Fetches trades with a 'createdAt' date that is greater or equal to + the given 'createdAtAfter' UNIX timestamp' + - in: query + name: createdAtBefore + description: >- + Fetches trades with a 'createdAt' date that is less than the given + 'createdAtBefore' UNIX timestamp' + schema: + type: string + description: >- + Fetches trades with a 'createdAt' date that is less than the given + 'createdAtBefore' UNIX timestamp' + - in: query + name: end + description: >- + The index of the last row to retrieve. This parameter specifies the + ending point for fetching rows from the dataset. It is exclusive, + meaning that the row at this index will not be included in the + results. + schema: + type: number + default: 20 + description: >- + The index of the last row to retrieve. This parameter specifies + the ending point for fetching rows from the dataset. It is + exclusive, meaning that the row at this index will not be included + in the results. + - in: query + name: mint + description: Mint address for the underlying position of the trade + schema: + type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh + description: Mint address for the underlying position of the trade + - in: query + name: side + schema: + type: string + enum: + - long + - short + - in: query + name: start + description: >- + The index of the first row to retrieve. This parameter specifies the + starting point for fetching rows from the dataset. It is inclusive, + meaning that the row at this index will be included in the results + schema: + type: number + default: 0 + description: >- + The index of the first row to retrieve. This parameter specifies + the starting point for fetching rows from the dataset. It is + inclusive, meaning that the row at this index will be included in + the results + - in: query + name: walletAddress + description: >- + Public key for the wallet to fetch trades (required unless txid is + provided) + schema: + type: string + description: >- + Public key for the wallet to fetch trades (required unless txid is + provided) + - in: query + name: txid + description: Transaction ID for the trade to fetch directly + schema: + type: string + description: Transaction ID for the trade to fetch directly + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + count: + type: number + dataList: + type: array + items: + type: object + properties: + action: + type: string + enum: + - Increase + - Decrease + collateralUsdDelta: type: string - description: Custody AUM in token amount - example: '123456789' - aumTokenAmountFormatted: + description: >- + The collateral delta / change value (USD) for the + trade. `collateralUsdDelta` is negative for + collateral deposits and positive for collateral + withdrawals + example: '250.00' + createdTime: + type: number + description: UNIX timestamp of when the trade was created + example: 1722851463 + baseFee: type: string - description: Custody AUM in token amount (formatted) - example: '123,456.79' - currentWeightagePct: + description: USD value of the base open / close fee for the trade + example: '0.45' + borrowFee: type: string - description: Current weight percentage - example: '25.50' - targetWeightagePct: + description: USD value of the borrow fee for the trade + example: '0.45' + liquidationFee: type: string - description: Target weight percentage - example: '30.00' - utilizationPct: + description: >- + USD value of the liquidation penalty for the + liquidation + example: '0.45' + priceImpactFee: type: string - description: Utilization percentage - example: '45.20' - owned: + description: USD value of the price impact fee for the trade + example: '0.45' + fee: type: string description: >- - Tokens owned by the JLP pool scaled to the token's - mint decimals - example: '123456789' - locked: - type: string + USD value of the fees paid (including the + liquidation penalty) for the trade + example: '0.45' + integratorFeeTokenAmount: + type: + - string + - 'null' + description: The fee token amount collected by the integrator + integratorFeeTokenMint: + type: + - string + - 'null' description: >- - Tokens locked by the JLP pool for trader's - collateral and leverage scaled to the token's mint - decimals - example: '123456789' - guaranteedUsd: + The mint address for the fee token collected by the + integrator + mint: type: string + enum: + - So11111111111111111111111111111111111111112 + - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs + - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh description: >- - Current long sizes for the token scaled to the USDC - decimals (6) - example: '123456789' - globalShortSizes: + Mint address for the underlying position of the + trade + orderType: type: string + enum: + - Market + - Trigger + - Liquidation description: >- - Current short sizes for the token scaled to the USDC - decimals (6) - example: '123456789' - globalShortAveragePrice: + 'Market' orders are orders placed by the trader. + 'Trigger' orders are orders executed by the keeper + for TP/SL requests. 'Liquidation' orders are also + executed by keeper when a position reaches its + liquidation price + owner: type: string + description: The public key / address for the owner + pnl: + type: + - string + - 'null' description: >- - Average price of all short positions for the token - scaled to the USDC decimals (6) - example: '123456789' - shortPnlDelta: - type: string - description: Short PnL delta scaled to the USDC decimals (6) - example: '123456789' - shortTradersHasProfit: - type: boolean + USD value of the trade profit / loss. The PNL value + shown is before fees (i.e. it does not minus + opening, closing, borrowing, and price impact fees). + 'pnlUsd' is null for collateral deposits and + withdrawals as the realised PNL is unchanged + example: '24.13' + pnlPercentage: + type: + - string + - 'null' description: >- - Boolean to indicate whether short traders are in - profit - example: true - totalStakedAmountLamports: + PNL percentage of the trade profit / loss. The PNL + percentage shown is before fees (i.e. it does not + minus opening, closing, borrowing, and price impact + fees). 'pnlPercentage' is null for collateral + deposits and withdrawals as the realised PNL is + unchanged + example: '24.13' + positionName: + type: string + enum: + - SOL-PERP + - ETH-PERP + - BTC-PERP + positionPubkey: type: string - description: Total staked SOL lamports (zero for other assets) - example: '123456789' - totalStakedAmountUsd: + description: The public key / address for the position + price: type: string - description: >- - Total staked SOL lamports in USD scaled to 6 decimal - places as per the USDC mint (zero for other assets) - example: '123456789' - totalStakedAmountUsdFormatted: + description: USD value of the position's entry price + example: '123.45' + side: + type: string + enum: + - long + - short + size: type: string description: >- - Formatted total staked SOL lamports in USD scaled to - 6 decimal places as per the USDC mint (zero for - other assets) - example: '123456789' + USD value of the position's trade size (including + leverage) + example: '12345.68' + transactionFeeLamports: + type: + - string + - 'null' + description: >- + The total transaction fee (lamports) paid for the + transaction + example: '5000' + priorityFeeLamports: + type: + - string + - 'null' + description: The priority fee (lamports) paid for the transaction + example: '2000' + swapFeeBps: + type: + - string + - 'null' + description: The swap fee (BPS) paid for the trade + example: '30' + swapFeeUsd: + type: + - string + - 'null' + description: The estimated swap fee ($) paid for the trade + example: '30' + swapFeeTokenAmount: + type: + - string + - 'null' + description: >- + The estimated swap fee (in the token amount) paid + for the trade + example: '100000' + swapFeeTokenMint: + type: + - string + - 'null' + description: The token mint address for the swap fee + txHash: + type: string + description: Transaction ID for the trade + example: >- + 4sjjb5kKAWAtXg1MQausgyqDx1Q5mU79a6EigxjjLYmCqBrNUE123XuoKr7Qir6ahBbLoSLLzT8gznxC2cgss5gR + updatedTime: + type: number + example: 1722851463 required: - - pubkey - - symbol - - name + - action + - collateralUsdDelta + - createdTime + - baseFee + - borrowFee + - liquidationFee + - priceImpactFee + - fee - mint - - aumUsd - - aumUsdFormatted - - aumTokenAmount - - aumTokenAmountFormatted - - currentWeightagePct - - targetWeightagePct - - utilizationPct - - owned - - locked - - guaranteedUsd - - globalShortSizes - - globalShortAveragePrice - - shortPnlDelta - - shortTradersHasProfit - - totalStakedAmountLamports - - totalStakedAmountUsd - - totalStakedAmountUsdFormatted - description: List of custody information + - orderType + - owner + - positionName + - positionPubkey + - price + - side + - size + - txHash + - updatedTime required: - - aumUsd - - aumUsdFormatted - - aumLimitUsd - - aumLimitUsdFormatted - - jlpPriceUsd - - jlpPriceUsdFormatted - - jlpTotalSupply - - jlpTotalSupplyFormatted - - jlpAprBps - - jlpAprPct - - jlpApyBps - - jlpApyPct - - jlpAprLastUpdatedTimestamp - - jlpRealizedFeeUsd - - custodies + - count + - dataList + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /transaction/execute: + description: >- + Executes the serialized transaction passed to the endpoint which requires + the keeper to sign the and execute the transaction. + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + action: + type: string + enum: + - tpsl + - tpsl-with-fee + - limit-order + - increase-position + - increase-position-with-fee + - decrease-position + - decrease-position-with-fee + description: The action for the serialized transaction to be executed + serializedTxBase64: + type: string + description: Serialise signed transaction from user. + required: + - action + - serializedTxBase64 + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + action: + type: string + description: The action for the serialized transaction to be executed + txid: + type: string + description: The transaction id of the request + required: + - action + - txid + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + /tpsl: + description: Returns a serialized transaction to create a TP/SL + delete: + requestBody: + content: + application/json: + schema: + type: object + properties: + positionRequestPubkey: + type: string + description: The public key for the TP / SL request + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + required: + - positionRequestPubkey + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + requireKeeperSignature: + type: boolean + description: >- + When `requireKeeperSignature` is true, the transaction + must be signed, serialized, and sent to the the `POST + /transaction/execute` endpoint to execute the transaction. + When `requireKeeperSignature` is `false`, the transaction + can be submitted through the `sendTransaction` RPC call as + usual + serializedTxBase64: + type: string + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the decrease + position request. The transaction can be deserialized, + signed by the owner of `walletAddress` and submitted + onchain to execute the decrease position request + transactionType: + type: string + enum: + - legacy + description: >- + Returns the type of serialized transaction to execute the + action. If the transaction type is `legacy`, the + transaction must be submitted by the client itself through + the RPC. If the transaction type is `instant`, the + transaction must be sent to the `POST + /transaction/execute` endpoint. + txMetadata: + type: object + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + decrease position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed decrease position transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: Contains relevant metadata for the serialized transaction. + required: + - requireKeeperSignature + - serializedTxBase64 + - transactionType + - txMetadata '400': description: 400 Bad Request content: @@ -1829,90 +3884,261 @@ paths: application/json: schema: $ref: '#/components/schemas/errorSchema' - /trades: - description: Fetches the trade history for the given wallet address - get: - parameters: - - in: query - name: action - schema: - type: string - enum: - - Increase - - Decrease - - in: query - name: createdAtAfter - description: >- - Fetches trades with a 'createdAt' date that is greater or equal to - the given 'createdAtAfter' UNIX timestamp' - schema: - type: string - description: >- - Fetches trades with a 'createdAt' date that is greater or equal to - the given 'createdAtAfter' UNIX timestamp' - - in: query - name: createdAtBefore - description: >- - Fetches trades with a 'createdAt' date that is less than the given - 'createdAtBefore' UNIX timestamp' - schema: - type: string - description: >- - Fetches trades with a 'createdAt' date that is less than the given - 'createdAtBefore' UNIX timestamp' - - in: query - name: end - description: >- - The index of the last row to retrieve. This parameter specifies the - ending point for fetching rows from the dataset. It is exclusive, - meaning that the row at this index will not be included in the - results. - schema: - type: number - default: 20 - description: >- - The index of the last row to retrieve. This parameter specifies - the ending point for fetching rows from the dataset. It is - exclusive, meaning that the row at this index will not be included - in the results. - - in: query - name: mint - description: Mint address for the underlying position of the trade - schema: - type: string - enum: - - So11111111111111111111111111111111111111112 - - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs - - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh - description: Mint address for the underlying position of the trade - - in: query - name: side - schema: - type: string - enum: - - long - - short - - in: query - name: start - description: >- - The index of the first row to retrieve. This parameter specifies the - starting point for fetching rows from the dataset. It is inclusive, - meaning that the row at this index will be included in the results - schema: - type: number - default: 0 - description: >- - The index of the first row to retrieve. This parameter specifies - the starting point for fetching rows from the dataset. It is - inclusive, meaning that the row at this index will be included in - the results - - in: query - name: walletAddress - description: Public key for the wallet to fetch trades - schema: - type: string - description: Public key for the wallet to fetch trades - required: true + post: + requestBody: + content: + application/json: + schema: + type: object + properties: + walletAddress: + type: string + description: The public key for owner of the position. + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + positionPubkey: + type: string + description: >- + The public key for the open position. Use the `GET + positions` endpoint to fetch the public key for the trader's + open positions. + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + tpsl: + type: array + items: + type: object + properties: + receiveToken: + type: string + enum: + - BTC + - ETH + - SOL + - USDC + description: >- + The token to receive when the TPSL is executed. Only + BTC, ETH, SOL, and USDC are currently supported. + entirePosition: + type: boolean + default: false + description: >- + Pass in `true` to close the entire position or `false` + to close a portion of the position (partial TPSL) + example: false + sizeUsdDelta: + type: + - string + - 'null' + description: >- + The amount in USD to decrease the position size by + (raw value with 6 decimal places). Required when + 'entirePosition' is false. + example: '10000000' + triggerPrice: + type: string + description: >- + Trigger price at which the TP / SL request will be + executed (raw value with 6 decimal places). For + example, to set a trigger price of $20, pass in + 20000000. + example: '20000000' + requestType: + type: string + enum: + - tp + - sl + description: >- + Pass in `tp` to set a take profit request or `sl` to + set a stop loss request + required: + - receiveToken + - triggerPrice + - requestType + maxItems: 20 + description: TPSL requests to set. + transactionType: + type: string + enum: + - instant + - mixed + default: instant + description: >- + Sets the type of serialized transaction to execute the + action. + required: + - walletAddress + - positionPubkey + - tpsl + responses: + '200': + description: 200 OK + content: + application/json: + schema: + type: object + properties: + tpslPubkeys: + type: array + items: + type: string + description: The position request account pubkeys for the TP / SL + requireKeeperSignature: + type: boolean + description: >- + When `requireKeeperSignature` is true, the transaction + must be signed, serialized, and sent to the the `POST + /transaction/execute` endpoint to execute the transaction. + When `requireKeeperSignature` is `false`, the transaction + can be submitted through the `sendTransaction` RPC call as + usual + serializedTxBase64: + type: string + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the decrease + position request. The transaction can be deserialized, + signed by the owner of `walletAddress` and submitted + onchain to execute the decrease position request + tpslRequests: + type: array + items: + type: object + properties: + estimatedPnlUsd: + type: string + description: The estimated PNL (USD) for the TPSL request + estimatedPnlPercent: + type: string + description: The estimated PNL percentage for the TPSL request + hasProfit: + type: boolean + description: Whether the TPSL request has profit + requestType: + type: string + enum: + - tp + - sl + description: The type of TPSL request + positionRequestPubkey: + type: string + description: >- + The unique identifier (i.e. a program derived + address) for the position request. Use this address + to find the position request account onchain + required: + - estimatedPnlUsd + - estimatedPnlPercent + - hasProfit + - requestType + - positionRequestPubkey + description: >- + TPSL requests created with the increase position. Only + returned when TPSL is requested. + transactionType: + type: string + enum: + - legacy + - instant + description: >- + Returns the type of serialized transaction to execute the + action. If the transaction type is `legacy`, the + transaction must be submitted by the client itself through + the RPC. If the transaction type is `instant`, the + transaction must be sent to the `POST + /transaction/execute` endpoint. + txMetadata: + type: object + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + decrease position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed decrease position transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: Contains relevant metadata for the serialized transaction. + required: + - tpslPubkeys + - requireKeeperSignature + - serializedTxBase64 + - tpslRequests + - transactionType + - txMetadata + '400': + description: 400 Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '404': + description: 404 Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '422': + description: 422 Unprocessable entity + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + '500': + description: 500 Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/errorSchema' + patch: + requestBody: + content: + application/json: + schema: + type: object + properties: + positionRequestPubkey: + type: string + description: The public key for the TP / SL request + example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + triggerPrice: + type: string + description: >- + Trigger price at which the TP / SL request will be executed + (raw value with 6 decimal places). For example, to set a + trigger price of $20, pass in 20000000. + example: '20000000' + transactionType: + type: string + enum: + - instant + - mixed + default: instant + description: >- + Sets the type of serialized transaction to execute the + action. If the transaction type is `instant`, the + transaction must be sent to the `POST /transaction/execute` + endpoint. If the transaction type is `mixed`, the + `transactionType` returned in the response will be either + `legacy` or `instant`. + required: + - positionRequestPubkey + - triggerPrice responses: '200': description: 200 OK @@ -1921,147 +4147,103 @@ paths: schema: type: object properties: - count: - type: number - dataList: + requireKeeperSignature: + type: boolean + description: >- + When `requireKeeperSignature` is true, the transaction + must be signed, serialized, and sent to the the `POST + /transaction/execute` endpoint to execute the transaction. + When `requireKeeperSignature` is `false`, the transaction + can be submitted through the `sendTransaction` RPC call as + usual + serializedTxBase64: + type: string + description: >- + The serialized transaction (base64 encoded) containing the + instructions and given parameters for the decrease + position request. The transaction can be deserialized, + signed by the owner of `walletAddress` and submitted + onchain to execute the decrease position request + tpslRequests: type: array items: type: object properties: - action: - type: string - enum: - - Increase - - Decrease - collateralUsdDelta: - type: string - description: >- - The collateral delta / change value (USD) for the - trade. `collateralUsdDelta` is negative for - collateral deposits and positive for collateral - withdrawals - example: '250.00' - createdTime: - type: number - description: UNIX timestamp of when the trade was created - example: 1722851463 - baseFee: - type: string - description: USD value of the base open / close fee for the trade - example: '0.45' - borrowFee: - type: string - description: USD value of the borrow fee for the trade - example: '0.45' - liquidationFee: - type: string - description: >- - USD value of the liquidation penalty for the - liquidation - example: '0.45' - priceImpactFee: - type: string - description: USD value of the price impact fee for the trade - example: '0.45' - fee: - type: string - description: >- - USD value of the fees paid (including the - liquidation penalty) for the trade - example: '0.45' - mint: - type: string - enum: - - So11111111111111111111111111111111111111112 - - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs - - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh - description: >- - Mint address for the underlying position of the - trade - orderType: - type: string - enum: - - Market - - Trigger - - Liquidation - description: >- - 'Market' orders are orders placed by the trader. - 'Trigger' orders are orders executed by the keeper - for TP/SL requests. 'Liquidation' orders are also - executed by keeper when a position reaches its - liquidation price - pnl: - type: - - string - - 'null' - description: >- - USD value of the trade profit / loss. The PNL value - shown is before fees (i.e. it does not minus - opening, closing, borrowing, and price impact fees). - 'pnlUsd' is null for collateral deposits and - withdrawals as the realised PNL is unchanged - example: '24.13' - pnlPercentage: - type: - - string - - 'null' - description: >- - PNL percentage of the trade profit / loss. The PNL - percentage shown is before fees (i.e. it does not - minus opening, closing, borrowing, and price impact - fees). 'pnlPercentage' is null for collateral - deposits and withdrawals as the realised PNL is - unchanged - example: '24.13' - positionName: + estimatedPnlUsd: type: string - enum: - - SOL-PERP - - ETH-PERP - - BTC-PERP - price: + description: The estimated PNL (USD) for the TPSL request + estimatedPnlPercent: type: string - description: USD value of the position's entry price - example: '123.45' - side: + description: The estimated PNL percentage for the TPSL request + hasProfit: + type: boolean + description: Whether the TPSL request has profit + requestType: type: string enum: - - long - - short - size: + - tp + - sl + description: The type of TPSL request + positionRequestPubkey: type: string description: >- - USD value of the position's trade size (including - leverage) - example: '12345.68' - txHash: - type: string - description: Transaction ID for the trade - example: >- - 4sjjb5kKAWAtXg1MQausgyqDx1Q5mU79a6EigxjjLYmCqBrNUE123XuoKr7Qir6ahBbLoSLLzT8gznxC2cgss5gR - updatedTime: - type: number - example: 1722851463 + The unique identifier (i.e. a program derived + address) for the position request. Use this address + to find the position request account onchain required: - - action - - collateralUsdDelta - - createdTime - - baseFee - - borrowFee - - liquidationFee - - priceImpactFee - - fee - - mint - - orderType - - positionName - - price - - side - - size - - txHash - - updatedTime + - estimatedPnlUsd + - estimatedPnlPercent + - hasProfit + - requestType + - positionRequestPubkey + description: TPSL requests updated + transactionType: + type: string + enum: + - legacy + - instant + description: >- + Returns the type of serialized transaction to execute the + action. If the transaction type is `legacy`, the + transaction must be submitted by the client itself through + the RPC. If the transaction type is `instant`, the + transaction must be sent to the `POST + /transaction/execute` endpoint. + txMetadata: + type: object + properties: + blockhash: + type: string + description: >- + The blockhash used for the serialized transaction. + This blockhash must be used when submitting the signed + decrease position transaction. + lastValidBlockHeight: + type: string + description: >- + The block height used for the serialized transaction. + This block height must be used when submitting the + signed decrease position transaction. + transactionFeeLamports: + type: string + description: The transaction fee (in lamports) in decimal format. + example: '0.5' + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0.5' + required: + - blockhash + - lastValidBlockHeight + - transactionFeeLamports + - accountRentLamports + description: Contains relevant metadata for the serialized transaction. required: - - count - - dataList + - requireKeeperSignature + - serializedTxBase64 + - tpslRequests + - transactionType + - txMetadata '400': description: 400 Bad Request content: @@ -2086,8 +4268,8 @@ paths: application/json: schema: $ref: '#/components/schemas/errorSchema' - /tpsl: - description: Returns a serialized transaction to create a TP/SL + /tpsl-with-fee: + description: Returns a serialized transaction to create a TP/SL and charge fees delete: requestBody: content: @@ -2095,12 +4277,37 @@ paths: schema: type: object properties: - positionRequestPubkey: + feeReceiver: type: string - description: The public key for the TP / SL request + description: >- + The token address (ATA) to receive the fee specified in + `feeTokenAmount`. The ATA must match the token mint + specified in `feeToken` + feeToken: + type: string + enum: + - USDC + description: >- + The token symbol for the fee token. Currently only USDC is + supported. + feeTokenAmount: + type: string + description: >- + The amount of fee tokens to send to `feeReceiver`. The value + must match the token mint decimals specified in `feeToken` + (e.g., for USDC with 6 decimals, 1000000 = 1 USDC) + example: '1000000' + tpslPubkey: + type: string + description: >- + The public key for the position request account (TPSL) to + cancel example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 required: - - positionRequestPubkey + - feeReceiver + - feeToken + - feeTokenAmount + - tpslPubkey responses: '200': description: 200 OK @@ -2109,65 +4316,62 @@ paths: schema: type: object properties: - requireKeeperSignature: - type: boolean + integratorFeeTokenMint: + type: string + description: The token mint for the integrator fee token + integratorFeeTokenAmount: + type: string + description: The amount of the integrator fee token + integratorFeeUsd: + type: string description: >- - When `requireKeeperSignature` is true, the transaction - must be signed, serialized, and sent to the the `POST - /transaction/execute` endpoint to execute the transaction. - When `requireKeeperSignature` is `false`, the transaction - can be submitted through the `sendTransaction` RPC call as - usual + The estimated integrator fee in USD (raw value with 6 + decimal places) + integratorFeeUsdFormatted: + type: string + description: >- + The estimated integrator fee in USD (human-readable + format) serializedTxBase64: type: string description: >- The serialized transaction (base64 encoded) containing the - instructions and given parameters for the decrease - position request. The transaction can be deserialized, - signed by the owner of `walletAddress` and submitted - onchain to execute the decrease position request + instructions to cancel the TPSL request transactionType: type: string enum: - legacy description: >- - Returns the type of serialized transaction to execute the - action. If the transaction type is `legacy`, the - transaction must be submitted by the client itself through - the RPC. If the transaction type is `instant`, the - transaction must be sent to the `POST - /transaction/execute` endpoint. + The transaction can be signed and submitted through the + RPC txMetadata: type: object properties: + accountRentLamports: + type: string + description: The account rent in lamports for the transaction + example: '0' blockhash: type: string - description: >- - The blockhash used for the serialized transaction. - This blockhash must be used when submitting the signed - decrease position transaction. + description: The blockhash used for the serialized transaction lastValidBlockHeight: type: string - description: >- - The block height used for the serialized transaction. - This block height must be used when submitting the - signed decrease position transaction. + description: The block height used for the serialized transaction transactionFeeLamports: type: string - description: The transaction fee (in lamports) in decimal format. - example: '0.5' - accountRentLamports: - type: string - description: The account rent (in lamports) for the transaction - example: '0.5' + description: The transaction fee in lamports + example: '5000' required: + - accountRentLamports - blockhash - lastValidBlockHeight - transactionFeeLamports - - accountRentLamports description: Contains relevant metadata for the serialized transaction. required: - - requireKeeperSignature + - integratorFeeTokenMint + - integratorFeeTokenAmount + - integratorFeeUsd + - integratorFeeUsdFormatted - serializedTxBase64 - transactionType - txMetadata @@ -2202,10 +4406,26 @@ paths: schema: type: object properties: - owner: + feeReceiver: type: string - description: The public key for owner of the position. - example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 + description: >- + The token address (ATA) to receive the fee specified in + `feeTokenAmount`. The ATA must match the token mint + specified in `feeToken` + feeToken: + type: string + enum: + - USDC + description: >- + The token symbol for the fee token. Currently only USDC is + supported. Must be the same as input token. + feeTokenAmount: + type: string + description: >- + The amount of fee tokens to send to `feeReceiver`. The value + must match the token mint decimals specified in `feeToken` + (e.g., for USDC with 6 decimals, 1000000 = 1 USDC) + example: '1000000' positionPubkey: type: string description: >- @@ -2213,99 +4433,46 @@ paths: positions` endpoint to fetch the public key for the trader's open positions. example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 - desiredMint: - type: - - string - - 'null' - enum: - - So11111111111111111111111111111111111111112 - - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs - - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh - - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v - - Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB - description: >- - The mint address for the token used when withdrawing - collateral or closing position when the TPSL is executed. - sizeUsdDelta: - type: - - string - - 'null' - description: >- - The amount in USD to decrease the position size by. Must be - an integer representing the USD amount multiplied by 10^6 (1 - million) to align with the 6 decimal places used for the - USDC mint on-chain. For example, to decrease by $10 USD, set - 'sizeUsdDelta' to 10000000; for $20.50 USD, set - 'sizeUsdDelta' to 20500000. - example: '10000000' - triggerPrice: - type: - - string - - 'null' - description: >- - Trigger price at which the TP / SL request will be executed. - The value must be an integer corresponding to 6 decimal - places. For example, to set a trigger price of $20, pass in - 20000000 - example: '20000000' - requestType: - type: - - string - - 'null' - enum: - - tp - - sl - description: >- - Pass in `tp` to set a take profit request or `sl` to set a - stop loss request - transactionType: - type: string - enum: - - legacy - - mixed - - instant - default: mixed - description: >- - Sets the type of serialized transaction to execute the - action. If the transaction type is `legacy`, the transaction - must be submitted by the client itself through the RPC. If - the transaction type is `instant`, the transaction must be - sent to the `POST /transaction/execute` endpoint. If the - transaction type is `mixed`, the `transactionType` returned - in the response will be either `legacy` or `instant`. tpsl: - type: - - array - - 'null' + type: array items: type: object properties: - desiredMint: - type: string - enum: - - So11111111111111111111111111111111111111112 - - 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs - - 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh - - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v - - Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB - description: >- - The mint address for the token used when withdrawing - collateral or closing position when the TPSL is - executed. entirePosition: type: boolean default: false description: >- - Pass in `true` to close the entire position or `false` - to close a portion of the position (partial TPSL) + When set to `true`, this will close the position and + transfer the remaining collateral and realised profits + (if the position is profitable) to the trader. example: false - sizeUsdDelta: + receiveToken: + type: string + enum: + - BTC + - ETH + - SOL + - USDC + description: >- + The token to receive when the TPSL is executed. Must + be the asset itself or USDC. + requestType: type: string + enum: + - tp + - sl + description: >- + Pass in `tp` to set a take profit request or `sl` to + set a stop loss request + sizeUsdDelta: + type: + - string + - 'null' description: >- The amount in USD to decrease the position size by. Must be an integer representing the USD amount multiplied by 10^6 (1 million) to align with the 6 - decimal places used for the USDC mint on-chain. For + decimal places used for USDC/USDT tokens on-chain. For example, to decrease by $10 USD, set 'sizeUsdDelta' to 10000000; for $20.50 USD, set 'sizeUsdDelta' to 20500000. @@ -2318,23 +4485,23 @@ paths: to 6 decimal places. For example, to set a trigger price of $20, pass in 20000000 example: '20000000' - requestType: - type: string - enum: - - tp - - sl - description: >- - Pass in `tp` to set a take profit request or `sl` to - set a stop loss request required: - - desiredMint - - sizeUsdDelta - - triggerPrice + - receiveToken - requestType + - triggerPrice description: TPSL requests to set + walletAddress: + type: string + description: >- + The wallet address / public key for the trader, Required + when opening a new position. required: - - owner + - feeReceiver + - feeToken + - feeTokenAmount - positionPubkey + - tpsl + - walletAddress responses: '200': description: 200 OK @@ -2343,20 +4510,22 @@ paths: schema: type: object properties: - tpslPubkeys: - type: array - items: - type: string - description: The position request account pubkeys for the TP / SL - requireKeeperSignature: - type: boolean + integratorFeeTokenMint: + type: string + description: The token mint for the integrator fee token + integratorFeeTokenAmount: + type: string + description: The amount of the integrator fee token + integratorFeeUsd: + type: string description: >- - When `requireKeeperSignature` is true, the transaction - must be signed, serialized, and sent to the the `POST - /transaction/execute` endpoint to execute the transaction. - When `requireKeeperSignature` is `false`, the transaction - can be submitted through the `sendTransaction` RPC call as - usual + The estimated integrator fee in USD (raw value with 6 + decimal places) + integratorFeeUsdFormatted: + type: string + description: >- + The estimated integrator fee in USD (human-readable + format) serializedTxBase64: type: string description: >- @@ -2365,10 +4534,14 @@ paths: position request. The transaction can be deserialized, signed by the owner of `walletAddress` and submitted onchain to execute the decrease position request + tpslPubkeys: + type: array + items: + type: string + description: The position request account pubkeys for the TP / SL transactionType: type: string enum: - - legacy - instant description: >- Returns the type of serialized transaction to execute the @@ -2380,6 +4553,10 @@ paths: txMetadata: type: object properties: + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0' blockhash: type: string description: >- @@ -2396,20 +4573,19 @@ paths: type: string description: The transaction fee (in lamports) in decimal format. example: '0.5' - accountRentLamports: - type: string - description: The account rent (in lamports) for the transaction - example: '0.5' required: + - accountRentLamports - blockhash - lastValidBlockHeight - transactionFeeLamports - - accountRentLamports description: Contains relevant metadata for the serialized transaction. required: - - tpslPubkeys - - requireKeeperSignature + - integratorFeeTokenMint + - integratorFeeTokenAmount + - integratorFeeUsd + - integratorFeeUsdFormatted - serializedTxBase64 + - tpslPubkeys - transactionType - txMetadata '400': @@ -2443,35 +4619,43 @@ paths: schema: type: object properties: - positionRequestPubkey: + feeReceiver: type: string - description: The public key for the TP / SL request + description: >- + The token address (ATA) to receive the fee specified in + `feeTokenAmount`. The ATA must match the token mint + specified in `feeToken` + feeToken: + type: string + enum: + - USDC + description: >- + The token symbol for the fee token. Currently only USDC is + supported. + feeTokenAmount: + type: string + description: >- + The amount of fee tokens to send to `feeReceiver`. The value + must match the token mint decimals specified in `feeToken` + (e.g., for USDC with 6 decimals, 1000000 = 1 USDC) + example: '1000000' + tpslPubkey: + type: string + description: The public key for the position request account (TPSL) example: 5HHB8sCKjWPU2zr3p4Lg49mQiaPQiHbCjHW7jgVzp583 triggerPrice: type: string description: >- - Trigger price at which the TP / SL request will be executed. - The value must be an integer corresponding to 6 decimal - places. For example, to set a trigger price of $20, pass in - 20000000 + New trigger price at which the TP / SL request will be + executed. The value must be an integer corresponding to 6 + decimal places. For example, to set a trigger price of $20, + pass in 20000000 example: '20000000' - transactionType: - type: string - enum: - - legacy - - mixed - - instant - default: mixed - description: >- - Sets the type of serialized transaction to execute the - action. If the transaction type is `legacy`, the transaction - must be submitted by the client itself through the RPC. If - the transaction type is `instant`, the transaction must be - sent to the `POST /transaction/execute` endpoint. If the - transaction type is `mixed`, the `transactionType` returned - in the response will be either `legacy` or `instant`. required: - - positionRequestPubkey + - feeReceiver + - feeToken + - feeTokenAmount + - tpslPubkey - triggerPrice responses: '200': @@ -2481,66 +4665,60 @@ paths: schema: type: object properties: - requireKeeperSignature: - type: boolean + integratorFeeTokenMint: + type: string + description: The token mint for the integrator fee token + integratorFeeTokenAmount: + type: string + description: The amount of the integrator fee token + integratorFeeUsd: + type: string description: >- - When `requireKeeperSignature` is true, the transaction - must be signed, serialized, and sent to the the `POST - /transaction/execute` endpoint to execute the transaction. - When `requireKeeperSignature` is `false`, the transaction - can be submitted through the `sendTransaction` RPC call as - usual + The estimated integrator fee in USD (raw value with 6 + decimal places) + integratorFeeUsdFormatted: + type: string + description: >- + The estimated integrator fee in USD (human-readable + format) serializedTxBase64: type: string description: >- The serialized transaction (base64 encoded) containing the - instructions and given parameters for the decrease - position request. The transaction can be deserialized, - signed by the owner of `walletAddress` and submitted - onchain to execute the decrease position request + instructions to update the TPSL request transactionType: type: string enum: - - legacy - instant - description: >- - Returns the type of serialized transaction to execute the - action. If the transaction type is `legacy`, the - transaction must be submitted by the client itself through - the RPC. If the transaction type is `instant`, the - transaction must be sent to the `POST - /transaction/execute` endpoint. + description: Always returns `instant` for fee-based transactions txMetadata: type: object properties: + accountRentLamports: + type: string + description: The account rent (in lamports) for the transaction + example: '0' blockhash: type: string - description: >- - The blockhash used for the serialized transaction. - This blockhash must be used when submitting the signed - decrease position transaction. + description: The blockhash used for the serialized transaction lastValidBlockHeight: type: string - description: >- - The block height used for the serialized transaction. - This block height must be used when submitting the - signed decrease position transaction. + description: The block height used for the serialized transaction transactionFeeLamports: type: string - description: The transaction fee (in lamports) in decimal format. - example: '0.5' - accountRentLamports: - type: string - description: The account rent (in lamports) for the transaction - example: '0.5' + description: The transaction fee in lamports + example: '5000' required: + - accountRentLamports - blockhash - lastValidBlockHeight - transactionFeeLamports - - accountRentLamports description: Contains relevant metadata for the serialized transaction. required: - - requireKeeperSignature + - integratorFeeTokenMint + - integratorFeeTokenAmount + - integratorFeeUsd + - integratorFeeUsdFormatted - serializedTxBase64 - transactionType - txMetadata From 5832e4dd181fcacb30b5daaba95f55f6056c08d7 Mon Sep 17 00:00:00 2001 From: YY Date: Wed, 5 Nov 2025 16:29:03 +0800 Subject: [PATCH 03/10] chore: update --- .DS_Store | Bin 0 -> 8196 bytes api-reference/perps.mdx | 9 ++++++--- api-reference/perps/jlp-lending-overview.mdx | 17 ----------------- api-reference/perps/jlp-overview.mdx | 17 ----------------- api-reference/perps/trading-overview.mdx | 13 ++++++++----- docs.json | 10 ++++------ 6 files changed, 18 insertions(+), 48 deletions(-) create mode 100644 .DS_Store delete mode 100644 api-reference/perps/jlp-lending-overview.mdx delete mode 100644 api-reference/perps/jlp-overview.mdx diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c6519f756119f0dd20bcae5213eea563f0c97116 GIT binary patch literal 8196 zcmeHMTWl0n7(U;$zzh>$T3aaC>8`9mEi^6_@Pd}@Ew<27u&v#eOWEBS+KJPdvNOA- z8clstK}~$osHks7eL#$ssIN-Y#P~oeQC`HD_{57hd@wQoXU;6R+}dF^CDm4-WRh`8$}?Bz%3a8{(gv4<(LX_R$%bzpe9HG2rFqgDD;`~ zfWRjnVk*R0fq^TnDY6HIt_V{M2zQ!~b92H}h_eEPJA-g%2zN%9p&;0u{NjN*LrP%O zMiGc2aAgE|?!JU&*c7u^b6NiGupBdOuh@~b-7I4j1KBCt^894-EToFc1q&C+%3@Vr zq7SD>M)&L;)3kzTK4RJ#-zu7&8Q=8Av}N9eJKd9Won3jeXqnT)IoB>sIy6(2%hZlJ?ERKA+6#sH3=RjN^}fjoJb`_zos-CBEK4RmSpX0JKIl0onc4W%j_-o z5u0Nt*(vr7JHyVgpV=?$SN0pb!2Uud7NZ9BSc7$F#9e5?J=laT=s+*}uoI)m!GMWz z*eIZgY0Tg$JcDQP9FF28yoT3t3~%CXypI$30H5MBe2!E20%!08&f!O##~-+WKP5$~ zmg*&4YLM1RjZ%}eUTT%LN!`+JX;d1MCd3J(@XliU%1L^232E<=(NW=V;WbR{9p0@D|VWFN4!5zy#E^&kg)=B ztVNP|-ij33(1|YM`Y!Co00yxSV>o~;G2ey*7l)9?6L^w%KZ~bv1kd9IyoguuDzX0< z-XQM3gLm;BKExbO;$wUgsNidSi?jIYGG6zU^BTWjpV!5Kykoo0I9ZjHQNBRbyCD(a zcR!Unp8t1U`}hCAC~BezL=pIZMgWza1D)-3wrjnOd9EF&dVne~+-_E2;6hE1juQsy kIN`-V4C!;6Ou0`g#94tfLgj}45D?w}(fuDV@78Yq0c^km@&Et; literal 0 HcmV?d00001 diff --git a/api-reference/perps.mdx b/api-reference/perps.mdx index f1d66d4a..6b3db716 100644 --- a/api-reference/perps.mdx +++ b/api-reference/perps.mdx @@ -5,13 +5,16 @@ description: "Overview of Jupiter Perps API" --- + + 1 item + - 24 items + 23 items - + 3 items - + 5 items diff --git a/api-reference/perps/jlp-lending-overview.mdx b/api-reference/perps/jlp-lending-overview.mdx deleted file mode 100644 index 553c58d8..00000000 --- a/api-reference/perps/jlp-lending-overview.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: "JLP Lending Overview" -sidebarTitle: "Overview" -description: "Overview of JLP LendingEndpoints in Jupiter Perps API" ---- - - - - 24 items - - - 3 items - - - 5 items - - diff --git a/api-reference/perps/jlp-overview.mdx b/api-reference/perps/jlp-overview.mdx deleted file mode 100644 index bf4a0172..00000000 --- a/api-reference/perps/jlp-overview.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: "JLP Overview" -sidebarTitle: "Overview" -description: "Overview of JLP Endpoints in Jupiter Perps API" ---- - - - - 24 items - - - 3 items - - - 5 items - - diff --git a/api-reference/perps/trading-overview.mdx b/api-reference/perps/trading-overview.mdx index 3acfb9d4..3e49ce55 100644 --- a/api-reference/perps/trading-overview.mdx +++ b/api-reference/perps/trading-overview.mdx @@ -5,13 +5,16 @@ description: "Overview of Trading Endpoints in Jupiter Perps API" --- - - 24 items + + 9 items - + + 5 items + + 3 items - - 5 items + + 6 items diff --git a/docs.json b/docs.json index 77768a63..7e0cbaee 100644 --- a/docs.json +++ b/docs.json @@ -467,7 +467,6 @@ { "group": "JLP", "pages": [ - "api-reference/perps/jlp-overview", "api-reference/perps/get-jlp-info", "api-reference/perps/post-jlp-mint", "api-reference/perps/post-jlp-burn" @@ -476,12 +475,11 @@ { "group": "JLP Lending", "pages": [ - "api-reference/perps/jlp-lending-overview", - "api-reference/perps/post-lending-deposit-borrow", - "api-reference/perps/post-lending-pay-withdraw", - "api-reference/perps/get-lending-positions", "api-reference/perps/get-lending-info", - "api-reference/perps/get-lending-history" + "api-reference/perps/get-lending-positions", + "api-reference/perps/get-lending-history", + "api-reference/perps/post-lending-deposit-borrow", + "api-reference/perps/post-lending-pay-withdraw" ] } ] From bbfb2c2dc5077a7fe1e319942964e97d28ae1300 Mon Sep 17 00:00:00 2001 From: YY Date: Wed, 5 Nov 2025 18:42:44 +0800 Subject: [PATCH 04/10] chore: fix copy --- openapi-spec/perps/perps.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi-spec/perps/perps.yaml b/openapi-spec/perps/perps.yaml index 7b87cbb2..5c28666c 100644 --- a/openapi-spec/perps/perps.yaml +++ b/openapi-spec/perps/perps.yaml @@ -300,7 +300,7 @@ paths: properties: walletAddress: type: string - description: Public key for the wallet to fetch expired orders + description: Public key for the wallet to limit orders required: - walletAddress responses: From 11c79a14b7caa81d873e1e0d30b56d8426047ccd Mon Sep 17 00:00:00 2001 From: YY Date: Tue, 25 Nov 2025 17:10:35 +0800 Subject: [PATCH 05/10] chore: update --- api-reference/index.mdx | 3 + docs.json | 39 +++- docs/perps/fees.mdx | 5 + docs/perps/get-started.mdx | 54 +++-- docs/perps/jlp.mdx | 4 + docs/perps/jlp/getting-jlp.mdx | 5 + docs/perps/lending/position-data.mdx | 5 + docs/perps/lending/position-management.mdx | 5 + docs/perps/liquidation.mdx | 4 + docs/perps/oracles.mdx | 4 + docs/perps/{ => program}/custody-account.mdx | 0 docs/perps/program/index.mdx | 0 docs/perps/{ => program}/pool-account.mdx | 0 docs/perps/{ => program}/position-account.mdx | 0 .../position-request-account.mdx | 0 docs/perps/trading/limit-orders.mdx | 4 + docs/perps/trading/position-data.mdx | 5 + docs/perps/trading/position-management.mdx | 4 + docs/perps/trading/tpsl-orders.mdx | 4 + docs/perps/transaction-execution.mdx | 188 ++++++++++++++++++ 20 files changed, 307 insertions(+), 26 deletions(-) create mode 100644 docs/perps/jlp/getting-jlp.mdx create mode 100644 docs/perps/lending/position-data.mdx create mode 100644 docs/perps/lending/position-management.mdx rename docs/perps/{ => program}/custody-account.mdx (100%) create mode 100644 docs/perps/program/index.mdx rename docs/perps/{ => program}/pool-account.mdx (100%) rename docs/perps/{ => program}/position-account.mdx (100%) rename docs/perps/{ => program}/position-request-account.mdx (100%) create mode 100644 docs/perps/trading/limit-orders.mdx create mode 100644 docs/perps/trading/position-data.mdx create mode 100644 docs/perps/trading/position-management.mdx create mode 100644 docs/perps/trading/tpsl-orders.mdx create mode 100644 docs/perps/transaction-execution.mdx diff --git a/api-reference/index.mdx b/api-reference/index.mdx index 4357e065..ec9e423c 100644 --- a/api-reference/index.mdx +++ b/api-reference/index.mdx @@ -14,6 +14,9 @@ description: "Overview of Jupiter API Reference" 1 item + + 4 items + 5 items diff --git a/docs.json b/docs.json index e665d60a..67c9c249 100644 --- a/docs.json +++ b/docs.json @@ -167,20 +167,49 @@ "group": "About Perps", "pages": [ "docs/perps/index", - "docs/perps/get-started", + "docs/perps/get-started" + ] + }, + { + "group": "Architecture", + "pages": [ "docs/perps/jlp", "docs/perps/oracles", "docs/perps/fees", "docs/perps/liquidation" ] }, + { + "group": "Perps API", + "pages": [ + "docs/perps/transaction-execution", + { + "group": "Trading", + "pages": [ + "docs/perps/trading/position-data", + "docs/perps/trading/position-management", + "docs/perps/trading/limit-orders", + "docs/perps/trading/tpsl-orders" + ] + }, + { + "group": "JLP", + "pages": [ + "docs/perps/jlp/getting-jlp", + "docs/perps/lending/position-data", + "docs/perps/lending/position-management" + ] + } + ] + }, { "group": "Perps Program", "pages": [ - "docs/perps/position-account", - "docs/perps/position-request-account", - "docs/perps/pool-account", - "docs/perps/custody-account" + "docs/perps/program/index", + "docs/perps/program/position-account", + "docs/perps/program/position-request-account", + "docs/perps/program/pool-account", + "docs/perps/program/custody-account" ] } ] diff --git a/docs/perps/fees.mdx b/docs/perps/fees.mdx index e69de29b..aef4e384 100644 --- a/docs/perps/fees.mdx +++ b/docs/perps/fees.mdx @@ -0,0 +1,5 @@ +--- +title: "Fees" +description: "Fees for the trading operations." +sidebarTitle: "Fees" +--- \ No newline at end of file diff --git a/docs/perps/get-started.mdx b/docs/perps/get-started.mdx index 225ebea6..b4a09de2 100644 --- a/docs/perps/get-started.mdx +++ b/docs/perps/get-started.mdx @@ -8,39 +8,51 @@ description: "Get started to develop with Jupiter Perpetuals." Refer to the [Perps API Reference](/api-reference/perps) for the complete API documentation. -## Swap Endpoints +## Architecture +| Component | Description | +| :-------- | :---------- | +| [**JLP**](/docs/perps/jlp) | Jupiter Liquidity Providers | +| [**Oracles**](/docs/perps/oracles) | Price oracles for the markets | +| [**Fees**](/docs/perps/fees) | Fees for the trading operations | +| [**Liquidation**](/docs/perps/liquidation) | How liquidations are handled | +| [**Perps Program**](/docs/perps/program) | The smart contract/program of Jupiter Perpetuals | + +## Transaction Execution +Refer to the [Transaction Execution](/docs/perps/transaction-execution) guide to understand how to execute transactions for both trading, mint/burn of JLP and lending/borrowing. + +## Trading Endpoints | Endpoint | Description | | :------- | :---------- | -| [**Get Order**](/docs/ultra/get-order) | Request for a quote and swap transaction. | -| [**Execute Order**](/docs/ultra/execute-order) | Sign and execute the swap transaction. | +| [**Position Data**](/docs/perps/trading/position-data) | Get information and data on positions. | +| [**Position Management**](/docs/perps/trading/position-management) | Manage positions by increasing, decreasing, closing, or closing all positions. | +| [**Limit Orders**](/docs/perps/trading/limit-orders) | Create, update, or cancel limit orders. | +| [**TPSL Orders**](/docs/perps/trading/tpsl-orders) | Create, update, or cancel TPSL orders. | -## Data Endpoints +## JLP Endpoints | Endpoint | Description | | :------- | :---------- | -| [**Search Token**](/docs/ultra/search-token) | Search for a token by its symbol, name or mint address. | -| [**Get Holdings**](/docs/ultra/get-holdings) | Request for token balances of an account. | -| [**Get Shield**](/docs/ultra/get-shield) | Enhanced security feature to provide critical token information contributing to better informed trading decisions. | +| [**JLP Info**](/docs/perps/jlp/getting-jlp) | Get information on JLP tokens. | +| [**Mint JLP**](/docs/perps/jlp/getting-jlp) | Mint JLP tokens. | +| [**Burn JLP**](/docs/perps/jlp/getting-jlp) | Burn JLP tokens. | + +## JLP Lending Endpoints +| Endpoint | Description | +| :------- | :---------- | +| [**Position Data**](/docs/perps/lending/position-data) | Get information and data on lending positions. | +| [**Position Management**](/docs/perps/lending/position-management) | Manage lending positions by depositing, borrowing, repaying, withdrawing. | ## FAQ - - -* **Integrator without custom fees**: Do note that when your users swap using Ultra Swap, we take 5 to 10 bps of the swap amount as a fee. -* **Integrator with custom fees**: If you are an integrator, you can add custom integrator fees via Ultra Swap API and Jupiter will take 20% of the integrator fees. Please refer to the [Add Fees To Ultra Swap](/docs/ultra/add-fees-to-ultra) guide for more information. + +Test - -* No, you cannot modify Ultra Swap transactions. -* Ultra Swap is intended to use as is, without any modifications. + +Test - -* Dynamic Rate Limits are now applied to Ultra Swap API. - - * No Pro plans or payment needed. - * Simply generate the universal API Key via [Portal](https://portal.jup.ag) - * Rate limits scale together with your swap volume. - * [Read more about Ultra Swap API Dynamic Rate Limit](/portal/rate-limit). + +Test diff --git a/docs/perps/jlp.mdx b/docs/perps/jlp.mdx index e69de29b..125bf290 100644 --- a/docs/perps/jlp.mdx +++ b/docs/perps/jlp.mdx @@ -0,0 +1,4 @@ +--- +title: "JLP" +description: "Understand Jupiter Liquidity Providers and how they work." +--- \ No newline at end of file diff --git a/docs/perps/jlp/getting-jlp.mdx b/docs/perps/jlp/getting-jlp.mdx new file mode 100644 index 00000000..666ae69e --- /dev/null +++ b/docs/perps/jlp/getting-jlp.mdx @@ -0,0 +1,5 @@ +--- +title: "Getting JLP" +description: "Get information, mint and burn JLP tokens." +sidebarTitle: "Getting JLP" +--- \ No newline at end of file diff --git a/docs/perps/lending/position-data.mdx b/docs/perps/lending/position-data.mdx new file mode 100644 index 00000000..dd1428ef --- /dev/null +++ b/docs/perps/lending/position-data.mdx @@ -0,0 +1,5 @@ +--- +title: "Position Data" +description: "Get information and data on JLP lending positions." +sidebarTitle: "Lending Position Data" +--- \ No newline at end of file diff --git a/docs/perps/lending/position-management.mdx b/docs/perps/lending/position-management.mdx new file mode 100644 index 00000000..7aa9fcbb --- /dev/null +++ b/docs/perps/lending/position-management.mdx @@ -0,0 +1,5 @@ +--- +title: "Position Management" +description: "Manage JLP lending positions by depositing, borrowing, repaying, withdrawing." +sidebarTitle: "Lending Position Management" +--- \ No newline at end of file diff --git a/docs/perps/liquidation.mdx b/docs/perps/liquidation.mdx index e69de29b..366d492c 100644 --- a/docs/perps/liquidation.mdx +++ b/docs/perps/liquidation.mdx @@ -0,0 +1,4 @@ +--- +title: "Liquidation" +description: "How liquidations are handled." +--- \ No newline at end of file diff --git a/docs/perps/oracles.mdx b/docs/perps/oracles.mdx index e69de29b..afdbb1a6 100644 --- a/docs/perps/oracles.mdx +++ b/docs/perps/oracles.mdx @@ -0,0 +1,4 @@ +--- +title: "Oracles" +description: "Understand the oracles used for the pricing of the markets." +--- \ No newline at end of file diff --git a/docs/perps/custody-account.mdx b/docs/perps/program/custody-account.mdx similarity index 100% rename from docs/perps/custody-account.mdx rename to docs/perps/program/custody-account.mdx diff --git a/docs/perps/program/index.mdx b/docs/perps/program/index.mdx new file mode 100644 index 00000000..e69de29b diff --git a/docs/perps/pool-account.mdx b/docs/perps/program/pool-account.mdx similarity index 100% rename from docs/perps/pool-account.mdx rename to docs/perps/program/pool-account.mdx diff --git a/docs/perps/position-account.mdx b/docs/perps/program/position-account.mdx similarity index 100% rename from docs/perps/position-account.mdx rename to docs/perps/program/position-account.mdx diff --git a/docs/perps/position-request-account.mdx b/docs/perps/program/position-request-account.mdx similarity index 100% rename from docs/perps/position-request-account.mdx rename to docs/perps/program/position-request-account.mdx diff --git a/docs/perps/trading/limit-orders.mdx b/docs/perps/trading/limit-orders.mdx new file mode 100644 index 00000000..b47fa0a9 --- /dev/null +++ b/docs/perps/trading/limit-orders.mdx @@ -0,0 +1,4 @@ +--- +title: "Limit Orders" +description: "Create, update, or cancel limit orders." +--- \ No newline at end of file diff --git a/docs/perps/trading/position-data.mdx b/docs/perps/trading/position-data.mdx new file mode 100644 index 00000000..be3df75d --- /dev/null +++ b/docs/perps/trading/position-data.mdx @@ -0,0 +1,5 @@ +--- +title: "Position Data" +description: "Get information and data on trading positions." +sidebarTitle: "Trading Position Data" +--- \ No newline at end of file diff --git a/docs/perps/trading/position-management.mdx b/docs/perps/trading/position-management.mdx new file mode 100644 index 00000000..db74839d --- /dev/null +++ b/docs/perps/trading/position-management.mdx @@ -0,0 +1,4 @@ +--- +title: "Position Management" +description: "Manage trading positions by increasing, decreasing, closing, or closing all positions." +--- \ No newline at end of file diff --git a/docs/perps/trading/tpsl-orders.mdx b/docs/perps/trading/tpsl-orders.mdx new file mode 100644 index 00000000..2df23250 --- /dev/null +++ b/docs/perps/trading/tpsl-orders.mdx @@ -0,0 +1,4 @@ +--- +title: "TPSL Orders" +description: "Create, update, or cancel TPSL orders." +--- \ No newline at end of file diff --git a/docs/perps/transaction-execution.mdx b/docs/perps/transaction-execution.mdx new file mode 100644 index 00000000..6197a102 --- /dev/null +++ b/docs/perps/transaction-execution.mdx @@ -0,0 +1,188 @@ +--- +title: "Transaction Execution" +description: "Understand how to execute transactions for both trading, mint/burn of JLP and lending/borrowing." +--- + +## Overview + +Many operations in the Jupiter Perps API require **keeper-signed transactions** to be executed. These transactions cannot be submitted directly through standard Solana RPC calls. Instead, they must be sent to the `/transaction/execute` endpoint, where a keeper will sign and execute them on your behalf. + + +Refer to the [Transaction Execution](/api-reference/perps/post-transaction-execute) endpoint for the complete API documentation. + + +## When to Use Transaction Execution + +All transactional operations in the Jupiter Perps API require the transaction execution endpoint. The following operations may require the transaction execution endpoint: + +- **Position Management** (`increase-position`, `decrease-position`) +- **Limit Orders** (`limit-order`) +- **TPSL Orders** (`tpsl`, `tpsl-with-fee`) +- And others + +When you call any of these operation endpoints, the response will include: + +- `serializedTxBase64`: The serialized transaction ready to be signed +- `transactionType`: Either `"legacy"` or `"instant"` +- `requireKeeperSignature`: Boolean indicating if keeper signature is required + +## Transaction Types + +### Instant Transactions + +When `transactionType` is `"instant"` or `requireKeeperSignature` is `true`, you **must** use the `/transaction/execute` endpoint. These transactions require a keeper to sign and execute them. + +### Legacy Transactions + +When `transactionType` is `"legacy"` and `requireKeeperSignature` is `false`, you can submit the transaction directly through standard Solana RPC methods (e.g., `sendTransaction`). + +## Workflow + +### Step 1: Create the Transaction + +Call the appropriate operation endpoint (e.g., `POST /tpsl`, `POST /positions/increase`) with your parameters: + +```typescript +const response = await fetch('https://api.jup.ag/perps/v1/tpsl', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + walletAddress: 'YOUR_WALLET_ADDRESS', + positionPubkey: 'POSITION_PUBKEY', + tpsl: [/* your TPSL config */], + transactionType: 'instant' // or 'mixed' + }) +}); + +const data = await response.json(); +``` + +### Step 2: Check Transaction Type + +Examine the response to determine how to proceed: + +```typescript +if (data.transactionType === 'instant' || data.requireKeeperSignature) { + // Proceed to Step 3 - use transaction execution endpoint +} else { + // Submit directly via RPC + await connection.sendRawTransaction(transaction.serialize()); +} +``` + +### Step 3: Sign the Transaction + +Deserialize and sign the transaction with your wallet: + +```typescript +import { Transaction } from '@solana/web3.js'; + +const transaction = Transaction.from( + Buffer.from(data.serializedTxBase64, 'base64') +); + +// Sign with your wallet +transaction.sign(wallet); + +// Serialize the signed transaction +const signedSerializedTx = transaction.serialize({ + requireAllSignatures: false, + verifySignatures: false +}); + +const signedTxBase64 = Buffer.from(signedSerializedTx).toString('base64'); +``` + +### Step 4: Execute via Transaction Endpoint + +Send the signed transaction to the `/transaction/execute` endpoint with the appropriate `action`: + +```typescript +const executeResponse = await fetch('https://api.jup.ag/perps/v1/transaction/execute', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + action: 'tpsl', // or 'limit-order', 'increase-position', etc. + serializedTxBase64: signedTxBase64 + }) +}); + +const result = await executeResponse.json(); +// result.txid contains the transaction ID +``` + +## Supported Actions + +The `action` parameter in `/transaction/execute` must match one of these values: + +- `tpsl` - Take profit / Stop loss orders +- `tpsl-with-fee` - TPSL orders with integrator fees +- `limit-order` - Limit orders +- `increase-position` - Increase position size +- `increase-position-with-fee` - Increase position with integrator fees +- `decrease-position` - Decrease position size +- `decrease-position-with-fee` - Decrease position with integrator fees + +## Important Notes + +1. **Transaction Expiry**: Transactions include blockhash metadata (`txMetadata`) that expires. Ensure you execute the transaction promptly after receiving it. + +2. **Serializing Transaction**: When serializing transactions for the execution endpoint, use `requireAllSignatures: false` since the keeper will add its signature. + +3. **Error Handling**: The execution endpoint may return errors if: + - The transaction is invalid or expired + - The keeper cannot execute the transaction + - The action type doesn't match the transaction + +4. **Transaction ID**: Upon successful execution, you'll receive a `txid` that you can use to track the transaction on-chain. + +## Example: Complete TPSL Workflow + +```typescript expandable +// 1. Create TPSL request +const createResponse = await fetch('https://api.jup.ag/perps/v1/tpsl', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + walletAddress: wallet.publicKey.toString(), + positionPubkey: positionPubkey, + tpsl: [{ + requestType: 'tp', + triggerPrice: '20000000', // $20.00 + receiveToken: 'USDC', + entirePosition: true + }], + transactionType: 'instant' + }) +}); + +const createData = await createResponse.json(); + +// 2. Check if execution endpoint is needed +if (createData.requireKeeperSignature) { + // 3. Deserialize and sign + const transaction = Transaction.from( + Buffer.from(createData.serializedTxBase64, 'base64') + ); + transaction.sign(wallet); + + const signedTxBase64 = Buffer.from( + transaction.serialize({ requireAllSignatures: false }) + ).toString('base64'); + + // 4. Execute via transaction endpoint + const executeResponse = await fetch('https://api.jup.ag/perps/v1/transaction/execute', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + action: 'tpsl', + serializedTxBase64: signedTxBase64 + }) + }); + + const executeResult = await executeResponse.json(); + console.log('Transaction ID:', executeResult.txid); +} else { + // Submit directly via RPC +} +``` From 368a965dc2dafded557d8671ffe4a79edf706e79 Mon Sep 17 00:00:00 2001 From: YY Date: Mon, 8 Dec 2025 17:24:50 +0800 Subject: [PATCH 06/10] chore: add api key auth --- openapi-spec/perps/perps.yaml | 81 ++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/openapi-spec/perps/perps.yaml b/openapi-spec/perps/perps.yaml index 5c28666c..decb4358 100644 --- a/openapi-spec/perps/perps.yaml +++ b/openapi-spec/perps/perps.yaml @@ -1,19 +1,20 @@ openapi: 3.1.0 - info: - title: Jupiter Perpetuals API Specification + title: Jupiter Perpetuals API version: 1.0.0 - + description: | + Jupiter Perpetuals API Schema servers: - - url: https://lite-api.jup.ag/perps/v1 - description: Free tier API endpoint with rate limits - url: https://api.jup.ag/perps/v1 - description: Paid tier API endpoint with higher rate limits to be used with an API Key + description: Jupiter Perpetuals API endpoint + paths: /market-stats: description: Fetches 24-hour market stats for the given market get: + security: + - ApiKeyAuth: [] parameters: - in: query name: mint @@ -89,6 +90,8 @@ paths: /orders/expired: description: Fetches expired orders for the wallet address get: + security: + - ApiKeyAuth: [] parameters: - in: query name: walletAddress @@ -182,6 +185,8 @@ paths: /orders/limit: description: Returns a serialized transaction to create a limit order. delete: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -292,6 +297,8 @@ paths: schema: $ref: '#/components/schemas/errorSchema' get: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -467,6 +474,8 @@ paths: schema: $ref: '#/components/schemas/errorSchema' post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -738,6 +747,8 @@ paths: schema: $ref: '#/components/schemas/errorSchema' patch: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -960,6 +971,8 @@ paths: /positions: description: Fetches the open positions for the given wallet address get: + security: + - ApiKeyAuth: [] parameters: - in: query name: includeClosedPositions @@ -1273,6 +1286,8 @@ paths: Returns an array of serialized transactions to close all open positions for the given wallet address. post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -1375,6 +1390,8 @@ paths: Returns the minimum and maximum token amounts for collateral deposits, as well as the maximum token amount for collateral withdrawals. get: + security: + - ApiKeyAuth: [] parameters: - in: query name: inputMint @@ -1496,6 +1513,8 @@ paths: the request, the position request PDA, and the position PDA that acts as the unique identifier for the position. post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -1801,6 +1820,8 @@ paths: the request, the position request PDA, and the position PDA that acts as the unique identifier for the position. post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -2155,6 +2176,8 @@ paths: the request, the position request PDA, and the position PDA that acts as the unique identifier for the position. post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -2616,6 +2639,8 @@ paths: the request, the position request PDA, and the position PDA that acts as the unique identifier for the position. post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -3042,6 +3067,8 @@ paths: /pool-info: description: Fetches the perpetuals base pool config info for the given market get: + security: + - ApiKeyAuth: [] parameters: - in: query name: mint @@ -3145,6 +3172,8 @@ paths: /jlp-info: description: Fetches the JLP token info get: + security: + - ApiKeyAuth: [] responses: '200': description: 200 OK @@ -3384,6 +3413,8 @@ paths: /trades: description: Fetches the trade history for the given wallet address get: + security: + - ApiKeyAuth: [] parameters: - in: query name: action @@ -3711,6 +3742,8 @@ paths: Executes the serialized transaction passed to the endpoint which requires the keeper to sign the and execute the transaction. post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -3778,6 +3811,8 @@ paths: /tpsl: description: Returns a serialized transaction to create a TP/SL delete: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -3885,6 +3920,8 @@ paths: schema: $ref: '#/components/schemas/errorSchema' post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -4106,6 +4143,8 @@ paths: schema: $ref: '#/components/schemas/errorSchema' patch: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -4271,6 +4310,8 @@ paths: /tpsl-with-fee: description: Returns a serialized transaction to create a TP/SL and charge fees delete: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -4400,6 +4441,8 @@ paths: schema: $ref: '#/components/schemas/errorSchema' post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -4613,6 +4656,8 @@ paths: schema: $ref: '#/components/schemas/errorSchema' patch: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -4749,6 +4794,8 @@ paths: /lending/deposit-borrow: description: Endpoint to deposit JLP and borrow USDC post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -4949,6 +4996,8 @@ paths: /lending/pay-withdraw: description: Endpoint to repay debt with USDC and withdraw JLP post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -5141,6 +5190,8 @@ paths: /lending/positions: description: Fetches the borrow lending positions for the given wallet address get: + security: + - ApiKeyAuth: [] parameters: - in: query name: walletAddress @@ -5280,6 +5331,8 @@ paths: /lending/info: description: Fetches global stats and info for the borrow lending pool get: + security: + - ApiKeyAuth: [] responses: '200': description: 200 OK @@ -5382,6 +5435,8 @@ paths: /lending/history: description: Fetches borrow lending history for the given wallet address get: + security: + - ApiKeyAuth: [] parameters: - in: query name: walletAddress @@ -5542,6 +5597,8 @@ paths: /top-traders: description: Returns traders by top PNL and top volume according to the given period. get: + security: + - ApiKeyAuth: [] parameters: - in: query name: marketMint @@ -5667,6 +5724,8 @@ paths: /trader-stats: description: Returns stats for the given trader get: + security: + - ApiKeyAuth: [] parameters: - in: query name: walletAddress @@ -5759,6 +5818,8 @@ paths: /jlp/burn: description: Endpoint to burn JLP post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -5902,6 +5963,8 @@ paths: /jlp/mint: description: Endpoint to mint JLP post: + security: + - ApiKeyAuth: [] requestBody: content: application/json: @@ -6023,6 +6086,12 @@ paths: schema: $ref: '#/components/schemas/errorSchema' components: + securitySchemes: + ApiKeyAuth: + type: apiKey + in: header + name: x-api-key + description: Get API key via https://portal.jup.ag schemas: errorSchema: type: object From 4534d07b2d36ae0df98bccff397a2a2f0ba89bb1 Mon Sep 17 00:00:00 2001 From: YY Date: Mon, 8 Dec 2025 17:29:02 +0800 Subject: [PATCH 07/10] chore: fix perps nav --- docs/perps/lending/position-data.mdx | 2 +- docs/perps/lending/position-management.mdx | 2 +- docs/perps/program/index.mdx | 4 ++++ docs/perps/trading/position-data.mdx | 1 - 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/perps/lending/position-data.mdx b/docs/perps/lending/position-data.mdx index dd1428ef..9ab4f4a8 100644 --- a/docs/perps/lending/position-data.mdx +++ b/docs/perps/lending/position-data.mdx @@ -1,5 +1,5 @@ --- title: "Position Data" description: "Get information and data on JLP lending positions." -sidebarTitle: "Lending Position Data" +sidebarTitle: "JLP Lend Position Data" --- \ No newline at end of file diff --git a/docs/perps/lending/position-management.mdx b/docs/perps/lending/position-management.mdx index 7aa9fcbb..6bc602c0 100644 --- a/docs/perps/lending/position-management.mdx +++ b/docs/perps/lending/position-management.mdx @@ -1,5 +1,5 @@ --- title: "Position Management" description: "Manage JLP lending positions by depositing, borrowing, repaying, withdrawing." -sidebarTitle: "Lending Position Management" +sidebarTitle: "JLP Lend Position Management" --- \ No newline at end of file diff --git a/docs/perps/program/index.mdx b/docs/perps/program/index.mdx index e69de29b..cdc9de35 100644 --- a/docs/perps/program/index.mdx +++ b/docs/perps/program/index.mdx @@ -0,0 +1,4 @@ +--- +title: "Overview" +description: "Overview of the Jupiter Perps Program." +--- \ No newline at end of file diff --git a/docs/perps/trading/position-data.mdx b/docs/perps/trading/position-data.mdx index be3df75d..11cd4ab4 100644 --- a/docs/perps/trading/position-data.mdx +++ b/docs/perps/trading/position-data.mdx @@ -1,5 +1,4 @@ --- title: "Position Data" description: "Get information and data on trading positions." -sidebarTitle: "Trading Position Data" --- \ No newline at end of file From cf2c4698cfb45e893e611b432bb586f8b71da80d Mon Sep 17 00:00:00 2001 From: YY Date: Tue, 9 Dec 2025 21:18:14 +0800 Subject: [PATCH 08/10] chore: jlp checkpoint --- docs.json | 7 +- docs/perps/jlp-lend.mdx | 0 .../{lending => jlp-lend}/position-data.mdx | 0 .../position-management.mdx | 0 docs/perps/jlp.mdx | 305 +++++++++++++++++- 5 files changed, 308 insertions(+), 4 deletions(-) create mode 100644 docs/perps/jlp-lend.mdx rename docs/perps/{lending => jlp-lend}/position-data.mdx (100%) rename docs/perps/{lending => jlp-lend}/position-management.mdx (100%) diff --git a/docs.json b/docs.json index 920af310..a41218bd 100644 --- a/docs.json +++ b/docs.json @@ -181,7 +181,8 @@ "docs/perps/jlp", "docs/perps/oracles", "docs/perps/fees", - "docs/perps/liquidation" + "docs/perps/liquidation", + "docs/perps/jlp-lend" ] }, { @@ -201,8 +202,8 @@ "group": "JLP", "pages": [ "docs/perps/jlp/getting-jlp", - "docs/perps/lending/position-data", - "docs/perps/lending/position-management" + "docs/perps/jlp-lend/position-data", + "docs/perps/jlp-lend/position-management" ] } ] diff --git a/docs/perps/jlp-lend.mdx b/docs/perps/jlp-lend.mdx new file mode 100644 index 00000000..e69de29b diff --git a/docs/perps/lending/position-data.mdx b/docs/perps/jlp-lend/position-data.mdx similarity index 100% rename from docs/perps/lending/position-data.mdx rename to docs/perps/jlp-lend/position-data.mdx diff --git a/docs/perps/lending/position-management.mdx b/docs/perps/jlp-lend/position-management.mdx similarity index 100% rename from docs/perps/lending/position-management.mdx rename to docs/perps/jlp-lend/position-management.mdx diff --git a/docs/perps/jlp.mdx b/docs/perps/jlp.mdx index 125bf290..f9171196 100644 --- a/docs/perps/jlp.mdx +++ b/docs/perps/jlp.mdx @@ -1,4 +1,307 @@ --- title: "JLP" description: "Understand Jupiter Liquidity Providers and how they work." ---- \ No newline at end of file +--- + +## What is JLP? + +JLP (Jupiter Liquidity Provider) is the liquidity pool token that powers Jupiter Perpetuals. The JLP pool serves as the counterparty for all perpetual trades, providing liquidity for traders to open highly-leveraged positions up to 250x on SOL, WETH, and WBTC. + +When you deposit assets into the JLP pool, you receive JLP tokens representing your share of the pool. As a liquidity provider, you earn 75% of fees generated by the perpetuals exchange, these fees are automatically and directly accrued into the JLP pool. + +## How JLP Works with Perps + +The JLP pool operates as a **trader-to-LP exchange model**, where: + +### Pool-Based Liquidity +- **Single Liquidity Pool**: All liquidity comes from the JLP pool, not from resting orders or order books +- **Direct Trading**: Traders open and close positions directly against the pool +- **Unlimited Size**: Trade size is limited only by available pool liquidity and position-level constraints +- **Oracle-Based Pricing**: All trades execute at oracle prices, ensuring large trades don't affect prices for others + +### Pool Composition +The JLP pool manages several custodies (tokens) for liquidity providers: + +| Token | Custody Address | +|-------|----------------| +| **SOL** (Wrapped SOL) | [`7xS2gz2bTp3fwCC7knJvUWTEU9Tycczu6VhJYKgi1wdz`](https://solscan.io/account/7xS2gz2bTp3fwCC7knJvUWTEU9Tycczu6VhJYKgi1wdz) | +| **WWETH** (Wrapped WETHereum) | [`AQCGyheWPLeo6Qp9WpYS9m3Qj479t7R636N9ey1rEjEn`](https://solscan.io/account/AQCGyheWPLeo6Qp9WpYS9m3Qj479t7R636N9ey1rEjEn) | +| **WBTC** (Wrapped Bitcoin) | [`5Pv3gM9JrFFH883SWAhvJC9RPYmo8UNxuFtv5bMMALkm`](https://solscan.io/account/5Pv3gM9JrFFH883SWAhvJC9RPYmo8UNxuFtv5bMMALkm) | +| **USDC** (USD Coin) | [`G18jKKXQwBbrHeiK3C9MRXhkHsLHf7XgCSisykV46EZa`](https://solscan.io/account/G18jKKXQwBbrHeiK3C9MRXhkHsLHf7XgCSisykV46EZa) | + +Each asset has a **target weightage** that the pool maintains through rebalancing mechanisms. The pool uses these assets to: +- Provide collateral backing for long positions (SOL, WWETH, WBTC) +- Provide collateral backing for short positions (USDC) +- Cover trader profits when positions are closed +- Earn fees for liquidity providers through trading and borrowing + +### How Traders Interact with JLP +1. **Opening Positions**: When a trader opens a leveraged position, they deposit collateral and borrow the remaining position size from the JLP pool +2. **Closing Positions**: When positions are closed, profits are paid from the pool's assets, while losses are added to the pool +3. **Borrow Fees**: Traders pay continuous borrow fees to the pool based on their position size and the pool's utilization rate +4. **Trading Fees**: All open/close fees flow into the pool (with 25% going to the protocol) + +The pool's AUM (Assets Under Management) represents the total value of assets in the pool, calculated as: + +$$ +\text{AUM} = \text{USD value of owned tokens} - \text{USD value reserved for trader profits} +$$ + +--- + +## Becoming a Liquidity Provider + +To become a JLP liquidity provider, you need to mint JLP tokens by depositing one of the supported assets (SOL, WETH, WBTC, USDC) into the pool. +- JLP can be acquired through swapping on jup.ag which finds the best price either by other DEXes or the pool itself. +- Or through the [JLP Earn](https://jup.ag/perps/jlp-earn), which mints or burns JLP tokens directly from the pool. + + + For detailed instructions on minting and burning JLP tokens, refer to the [Getting JLP](/docs/perps/jlp/getting-jlp) guide. + + + + The pool has the following limits: + + - **AUM Limit**: The pool has a maximum AUM limit, preventing more deposits when the limit is hit. + - **Token Weightage**: The pool maintains target weightages for each asset. Deposits/withdrawals that would push a token outside its target range (±20%) are restricted to maintain balance. + + +--- + +## JLP Lending + +JLP tokens can be used as collateral to borrow USDC from the pool, creating additional utility and yield opportunities for liquidity providers. + +This feature allows liquidity providers to: +- Access liquidity without selling their JLP position +- Potentially increase their yield through leverage +- Maintain exposure to JLP returns while borrowing for other purposes + + + For detailed information on JLP lending mechanics, position management, and borrowing limits, refer to the [JLP Lend](/docs/perps/jlp-lend) documentation. + + +--- + +## Economics + +### Key Concepts + +With the introduction of USDC lending from the JLP, the following definitions represent the true state of the custody accounts: + +**Debt** + +$$ +\text{debt} = \frac{\max\left(\text{custody.debt} - \text{custody.borrowLendInterestsAccrued},\ 0\right)}{1{,}000{,}000{,}000} +$$ + +The custody account's `debt` field represents the tokens borrowed from the custody. +This gives the pure debt amount without accumulated interests. + + +**Theoretically Owned** + +$$ +\text{theoreticallyOwned} = \text{custody.assets.owned} + \text{debt}(\text{custody}) +$$ + +This represents the "true" owned token amount by the custody. +Borrowed tokens are not stored in `custody.assets.owned`, so this calculation provides the actual value of assets owned by the pool. + + +**Total Locked** + +$$ +totalLocked = custody.assets.locked + debt(custody) +$$ + +This represents the "true" locked token amount by the custody, including borrowed tokens: +Similar to the theoretically owned value above, this returns the actual locked token amount by the custody. + + +--- + +### Assets Under Management + +The AUM for each custody account in the pool is calculated as follows. + +**Stablecoins (USDC)** + +$$ +\text{aumUsd} = \text{theoreticallyOwned} \times \text{currentTokenPrice} +$$ + + +**Non-stablecoins (SOL, WETH, WBTC)** +1. First, calculate the global short position profit/loss (Unrealized PNL in USD). +2. Second, check if the short traders are in profit. +3. Finally, calculate the assets under management. + +$$ +\text{unrealizedShortPNL} = \frac{\text{shortSize} \times \left| \text{shortAvgPrice} - \text{currentTokenPrice} \right|}{\text{shortAvgPrice}} +$$ + +1. Global short position profit/loss (Unrealized PNL in USD): + - shortSize = `custody.assets.globalShortSizes` + - shortAvgPrice = `custody.assets.globalShortAveragePrices` + + + +2. Check if `shortAvgPrice > currentTokenPrice`. If true, short traders are in profit, otherwise they are in loss. + + + +$$ +\text{aumUsd} = \text{custody.assets.guaranteedUsd} \pm \text{unrealizedShortPNL} +$$ + +3. Assets under management for each asset: + + - If the short traders are in profit, subtract `unrealizedShortPNL` from `aumUsd`. + - Otherwise, add `unrealizedShortPNL` to `aumUsd`. + + +- The `guaranteed_usd` value in each custody account represents an estimate of the total size of all long positions. It is only an estimate as `guaranteed_usd` is only updated when positions are updated (i.e. opening / closing positions, updating collateral). It does not update in real-time when asset prices change. + +- The `guaranteed_usd` value is used to calculate the pool's AUM as well as the overall PNL for all long positions efficiently. + + + +**Total AUM** + +The Total AUM is then calculated as the sum of all the custodies' AUM. + +$$ +\text{totalAumUsd} = \sum \text{aumUsd} +$$ + +--- + +### Virtual Price and Market Price + +**Virtual Price** + +$$ +\text{virtualPrice} = \frac{\text{totalAumUsd}}{\text{jlpTotalSupply}} +$$ + +The virtual price represents the intrinsic value of each JLP token based on the pool's underlying assets. + + +**Market Price** + +$$ +\text{marketPrice} = \text{virtualPrice} + \text{marketAssignedPremium} +$$ + +The market price of JLP is determined by supply and demand on the open market (e.g., through DEX swaps). It can differ from the virtual price depending on market conditions. + +When the AUM limit is hit and deposits are restricted, liquidity providers will seek for circulating JLP in the open market, causing demand for JLP to exceed supply, leading to a market price premium above the virtual price. + + +You may sell your JLP at market price any time (by swapping it with other tokens on DEXes). However, if Market Price is below the Virtual Price, your JLP will be redeemed (burned) at the virtual price instead. + + + +--- + +### Global Realized PNL + +1. Longs: uses locked tokens value minus guaranteed USD (collateral-based). +2. Shorts: uses size × absolute price difference divided by average entry price (price-difference-based). + + +Most accurate way to calculate the unrealized PNL for all open long/short positions is to loop through all open positions (by fetching them from onchain accounts) and use the unrealized PNL calculation shown below. + + +**Calculating Global Unrealized PNL for Longs** + +To get an estimate of the global unrealized PNL for longs: + + + + +$$ +\text{guaranteedUsd} = \text{custody.assets.guaranteedUsd} +$$ + +- [Using the custody account](/docs/perps/program/custody-account) +- Get the `assets.guaranteedUsd` field which stores the value of + `position.sizeUsd - position.collateralUsd` for all open long positions for the custody. +- Note that a position's `sizeUsd` value is only updated when a trade is made, which is the + same for `guaranteedUsd` as well. It does *not* update in real-time when the custody's price changes. + + + + + +$$ +\text{lockedTokensUsd} = \text{custody.assets.locked} \times \text{currentTokenPriceUsd} +$$ + +- Multiply `custody.assets.locked` by the custody's current price to get the USD value of the tokens locked + by the pool to pay off traders' profits + + + + + +$$ +\text{globalUnrealizedLongPNL} = \text{lockedTokensUsd} - \text{guaranteedUsd} +$$ + +- Subtract `guaranteedUsd` from `lockedTokensUsd` to get the estimate of unrealized PNL for all open long positions. +- Note that the final value is greater than the actual unrealized PNL as it includes traders' collateral + + + + + +**Calculating Global Unrealized PNL for Shorts** + +To get an estimate of the global unrealized PNL for shorts: + + + + +$$ +\text{globalShortSizes} = \text{custody.assets.globalShortSizes} +$$ + +$$ +\text{globalShortAveragePrices} = \text{custody.assets.globalShortAveragePrices} +$$ + +- [Using the custody account](/docs/perps/program/custody-account) +- Get the `assets.globalShortSizes` field which represents the total USD value of all open short positions. +- Get the `assets.globalShortAveragePrices` field which represents the average entry price (in USD) of all open short positions. + + + + + +$$ +\text{priceDifferenceRatio} = \frac{ + \left| \text{globalShortAveragePrices} - \text{currentTokenPriceUsd} \right| +}{ + \text{globalShortAveragePrices} +} +$$ + +- Calculate the absolute price difference ratio between the average entry price and the current token price. +- This represents the percentage change in price since the average entry. + + + + + +$$ +\text{globalUnrealizedShortPNL} = \text{globalShortSizes} \times \text{priceDifferenceRatio} +$$ + +- Multiply `globalShortSizes` by `priceDifferenceRatio` to get the estimate of unrealized PNL for all open short positions. + + + + +--- From 678b342cd4d673a637dfca158ab0a9b4a1a859e6 Mon Sep 17 00:00:00 2001 From: YY Date: Wed, 10 Dec 2025 15:28:23 +0800 Subject: [PATCH 09/10] chore: complete jlp doc --- docs/perps/jlp.mdx | 104 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 91 insertions(+), 13 deletions(-) diff --git a/docs/perps/jlp.mdx b/docs/perps/jlp.mdx index f9171196..60ca4e4d 100644 --- a/docs/perps/jlp.mdx +++ b/docs/perps/jlp.mdx @@ -51,25 +51,19 @@ $$ ## Becoming a Liquidity Provider + To become a JLP liquidity provider, you need to mint JLP tokens by depositing one of the supported assets (SOL, WETH, WBTC, USDC) into the pool. - JLP can be acquired through swapping on jup.ag which finds the best price either by other DEXes or the pool itself. - Or through the [JLP Earn](https://jup.ag/perps/jlp-earn), which mints or burns JLP tokens directly from the pool. - - For detailed instructions on minting and burning JLP tokens, refer to the [Getting JLP](/docs/perps/jlp/getting-jlp) guide. - - - - The pool has the following limits: - - - **AUM Limit**: The pool has a maximum AUM limit, preventing more deposits when the limit is hit. - - **Token Weightage**: The pool maintains target weightages for each asset. Deposits/withdrawals that would push a token outside its target range (±20%) are restricted to maintain balance. - +For detailed instructions on minting and burning JLP tokens, refer to the [Getting JLP](/docs/perps/jlp/getting-jlp) guide. + --- ## JLP Lending + JLP tokens can be used as collateral to borrow USDC from the pool, creating additional utility and yield opportunities for liquidity providers. This feature allows liquidity providers to: @@ -77,9 +71,8 @@ This feature allows liquidity providers to: - Potentially increase their yield through leverage - Maintain exposure to JLP returns while borrowing for other purposes - - For detailed information on JLP lending mechanics, position management, and borrowing limits, refer to the [JLP Lend](/docs/perps/jlp-lend) documentation. - +For detailed information on JLP lending mechanics, position management, and borrowing limits, refer to the [JLP Lend](/docs/perps/jlp-lend) documentation. + --- @@ -171,9 +164,11 @@ $$ The Total AUM is then calculated as the sum of all the custodies' AUM. + $$ \text{totalAumUsd} = \sum \text{aumUsd} $$ + --- @@ -205,6 +200,53 @@ You may sell your JLP at market price any time (by swapping it with other tokens --- +### APR/APY Calculation + +The APR and APY for JLP are updated weekly based on the fees generated by the pool (in USD) from perps trading activities. 75% of these fees are distributed to JLP holders, excluding asset appreciation and traders' PnL. Fees are reinvested by being redeposited into the pool every hour. You can refer to [JLP Earn](https://jup.ag/perps/jlp-earn) page for more details. + +**APR Formula** + + +$$ +\text{APR} = \frac{\text{feesDistributedToJLP}}{\text{totalAumUsd}} +$$ + +- $\text{feesDistributedToJLP}$ = total USD value of 75% of perps trading fees generated over the last 7 days (excluding protocol share). +- $\text{totalAumUsd}$ = current total AUM of the pool. +- The APR is expressed as an annualized rate, updated weekly based on the prior week's fees. + + +**APY Formula** + + +$$ +\text{APY} = \left(1 + \frac{\text{APR}}{52}\right)^{52} - 1 +$$ + +- Fees are automatically compounded every hour, but the website calculates APY with a weekly compounding interval ($n = 52$). +- This APY is denominated in USD and reflects only the compounded yield from 75% of perps trading fees, not asset price appreciation or trader PnL. +- $\text{APR}$ is taken from the previous formula. +- $52$ is the number of compounding periods per year (weekly). + + +### Pool Rebalancing + +The JLP pool maintains target weightages for each asset to ensure balanced exposure and optimal risk management. Each asset has a **target weightage**—the ideal proportion relative to the pool's total AUM—and a **current weightage** that reflects the actual proportion at any given time. + +When swaps occur between JLP assets, they affect each asset's weightage: + +- **Swapping into the pool** (e.g., depositing SOL) increases that asset's current weightage +- **Swapping out of the pool** (e.g., withdrawing SOL) decreases that asset's current weightage + +For example, swapping 100 SOL for 100 USDC reduces SOL's pool size (and current weightage) while increasing USDC's pool size (and current weightage). + +The pool uses dynamic fee adjustments to incentivize swaps that move assets toward their target weightages, while discouraging swaps that move them further away. This mechanism protects JLP holders by maintaining pool balance and rewards them when swaps help rebalance the pool. For details on how fees adjust, see the [Fees](/docs/perps/fees) documentation. +- **Risk Management**: Balanced exposure prevents over-concentration in any single asset, reducing vulnerability to extreme price movements +- **Liquidity Optimization**: Proper asset distribution ensures the pool can efficiently serve both long and short traders +- **Fee Generation**: Rebalanced pools can better accommodate trading activity, leading to more consistent fee generation + +--- + ### Global Realized PNL 1. Longs: uses locked tokens value minus guaranteed USD (collateral-based). @@ -305,3 +347,39 @@ $$ --- + +### Yield + +The JLP token adopts a growth-focused approach, similar to accumulating ETFs like VWRA or ARKK. Rather than distributing yield through airdrops or additional token mints, the JLP token's value is designed to appreciate over time. This appreciation is driven by the growth of the JLP pool's AUM, which is used to derive the virtual price as shown above. + +**75% of all fees generated** from Jupiter Perpetuals trading, token swaps, and JLP minting/burning are reinvested directly into the JLP pool. This mechanism continuously enhances the pool's liquidity and value for token holders. + +**The remaining 25% of fees** is allocated to Jupiter as protocol fees, supporting ongoing development and maintenance. + +For example, if trading activities generate 10 SOL in fees, 7.5 SOL would be added to the JLP pool, increasing its SOL holdings and AUM. + +Fees generated by the pool are reinvested directly back into the JLP pool, mirroring how accumulating ETFs reinvest dividends. This reinvestment strategy compounds the pool's growth, steadily increasing the JLP token's price and intrinsic value. + +--- + +### Exposure + +The intrinsic value of the JLP token is linked to the price movements of the liquidity pool's underlying tokens (SOL, WETH, BTC, USDC). + +As a JLP holder, your portfolio is exposed to market movements, particularly to the performance of the non-stablecoin tokens: SOL, WETH, and BTC. If these tokens decrease in price, the value of your JLP position will likely decrease as well. + +That said, JLP holders earn yield from fees generated by trading activities. When traders incur losses, these are reinvested into the JLP pool, benefiting JLP holders. Conversely, when traders profit, it comes at the expense of the JLP pool. + +The JLP usually outperforms its underlying assets during sideways or bearish market conditions since traders often struggle to be profitable in bear markets. However, during strong bull markets, the situation can reverse. Traders may open more long positions which can lead to trader profitability at the expense of JLP holders. + +--- + +### Risk Considerations + +JLP holders are exposed to risks that can impact their portfolio: + +| **Risk** | **Description** | +|---------------------------|-----------------| +| **Market Volatility** | Rapid price movements can negatively impact the JLP. Extreme market events or black swan scenarios may cause correlations between assets to break down, potentially amplifying losses instead of mitigating them. | +| **Counterparty Risk** | The JLP pool poses a counterparty risk to JLP holders, as smart contract vulnerabilities or platform issues could potentially impact the ability to maintain or close hedge positions. That said, Jupiter is working with leading firms in the field to audit and maintain our contracts to protect the Jupiter Perpetuals exchange and JLP holders. | +| **Opportunity Cost** | Capital allocated to acquiring JLP could potentially earn higher returns if allocated elsewhere. In bull markets for example, JLP may underperform compared to simply holding the underlying assets. JLP holders should thoroughly research and understand the benefits and risks of the JLP token before acquiring them. | From d1d94ba10226ed7d8539eb0596ee177821609116 Mon Sep 17 00:00:00 2001 From: YY Date: Wed, 10 Dec 2025 17:50:57 +0800 Subject: [PATCH 10/10] chore: fees doc checkpoint --- docs/perps/fees.mdx | 131 +++++++++++++++++++++- docs/perps/jlp.mdx | 4 +- static/images/linear-price-impact-fee.png | Bin 0 -> 164389 bytes 3 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 static/images/linear-price-impact-fee.png diff --git a/docs/perps/fees.mdx b/docs/perps/fees.mdx index aef4e384..ab42a68a 100644 --- a/docs/perps/fees.mdx +++ b/docs/perps/fees.mdx @@ -1,5 +1,130 @@ --- title: "Fees" -description: "Fees for the trading operations." -sidebarTitle: "Fees" ---- \ No newline at end of file +description: "Understand fees involved in Jupiter Perps and JLP pool." +--- + +Jupiter Perpetuals operates on a **trader-to-LP exchange model** where the Jupiter Liquidity Pool (JLP) serves as the counterparty for all perpetual trades. The fee structure is designed to balance the interests of traders and liquidity providers while managing risk and maintaining pool stability. + +**How Fees Flow Between Traders and JLP:** + +1. **Traders pay fees** when opening/closing positions, borrowing assets, and swapping tokens. +2. **Fees are collected** by the protocol and accumulate in `feesReserves` for each custody. +3. **Fee distribution**: 75% of all fees go to JLP holders, 25% to the protocol. +4. **Reinvestment**: Fees are periodically reinvested into the pool, increasing the pool's AUM and benefiting all JLP holders through price appreciation. + +This fee model ensures that liquidity providers are compensated for providing capital and taking on the risk of being the counterparty to leveraged positions, while traders pay competitive fees for access to high-leverage trading with zero slippage execution. + +--- + +## Fee Overview + +The following table summarizes all fee types in Jupiter Perpetuals. + + +Fee parameters are subject to change, as Jupiter and third party risk auditors continue to monitor market conditions, protocol performance, pool utilization, and other factors to ensure competitive and sustainable fees. + + +| Fee Type | Rate | When Charged | Who Pays | Who Receives | +|----------|------|--------------|----------|--------------| +| **Base Fee** | 0.06% (6 BPS) | Opening/closing positions, liquidations, TP/SL, limit orders | Traders | JLP Pool (75%) + Protocol (25%) | +| **Price Impact Fee (Linear)** | Variable | Based on trade size relative to pool liquidity | Traders | JLP Pool (75%) + Protocol (25%) | +| **Price Impact Fee (Additive)** | Variable | When OI imbalance exceeds threshold | Traders | JLP Pool (75%) + Protocol (25%) | +| **Borrow Fee** | Variable (hourly) | Continuously on open positions | Traders | JLP Pool (75%) + Protocol (25%) | +| **Swap Fee** | 0.02% (2 BPS) for stables; 0.1% (10 BPS) for non-stables; Dynamic adjustment based on weightage | Swapping between JLP assets | Traders/LPs | JLP Pool (75%) + Protocol (25%) | +| **JLP Mint/Burn Fee** | Variable | Minting or burning JLP tokens | LPs | JLP Pool (75%) + Protocol (25%) | +| **Liquidation Penalty** | 100% of remaining collateral | When position is liquidated | Liquidated traders | JLP Pool (100%) | +| **Transaction Fees** | Variable | Submitting transactions | Traders | Solana Network | + +--- + +## Base Fee + +A flat rate of **0.06% (6 BPS)** is charged when performing these actions on the protocol: + +1. **Opening/Closing Positions**: When opening or closing a position +2. **Liquidations**: When positions are liquidated +3. **Take Profit / Stop Loss Orders**: When TP/SL orders execute +4. **Limit Orders**: When limit orders are filled + + +**Example Base Fee Calculation** + +$$ +\text{baseFee} = \text{tradeSize} \times \text{baseFeeRate} +$$ + +- $\text{tradeSize}$ = the size of the trade in USD, e.g. 10,000 USD +- $\text{baseFeeRate}$ = the base fee rate in BPS (0.06% = 6 BPS) +- $\text{baseFee}$ = 10,000 * 0.06% = **$6** + + +--- + +## Price Impact Fees + +1. **Linear Price Impact Fee**: Scales with trade size +2. **Additive Price Impact Fee**: Additional penalty when open interest imbalance is high + +### Rationale + +When trading on Jupiter Perpetuals, large trades don't incur price impact due to the use of oracle prices. This means the price shown to the trader is the price the trade is executed at—providing zero-slippage execution. + +This is different from orderbook exchanges where large trades consume liquidity at various price levels, resulting in worse execution prices (slippage). While this benefits traders, it creates risks for JLP holders who are exposed to potential losses from large trades. It also opens the possibility for attackers to move prices on other exchanges and profit from opening positions in Jupiter Perpetuals. + +To address this, Jupiter Perpetuals implements a **price impact fee** that simulates the price impact on traditional exchanges. The price impact fee consists of two components: a linear price impact fee and an additive price impact fee. + + +### Linear Price Impact Fee + + +$$ +\text{Linear price impact fee coefficient} = \frac{\text{trade size}}{\text{price impact fee scalar constant}} +$$ + +$$ +\text{Final linear price impact fee} = \text{trade size} \times \text{linear price impact fee coefficient} +$$ + +
+ Linear Price Impact Fee +
+ +- The linear price impact fee scales with trade size. +- The fee increases proportionally as the trade size increases. +- Each custody (SOL, ETH, BTC) has a fixed constant value (the price impact fee scalar or `pricing.tradeImpactFeeScalar` to be exact) that determines the final linear price impact fee coefficient when calculating the linear price impact fee. + - **SOL**: [`7xS2gz2bTp3fwCC7knJvUWTEU9Tycczu6VhJYKgi1wdz`](https://solscan.io/account/7xS2gz2bTp3fwCC7knJvUWTEU9Tycczu6VhJYKgi1wdz#accountData) + - **BTC**: [`5Pv3gM9JrFFH883SWAhvJC9RPYmo8UNxuFtv5bMMALkm`](https://solscan.io/account/5Pv3gM9JrFFH883SWAhvJC9RPYmo8UNxuFtv5bMMALkm#accountData) + - **ETH**: [`AQCGyheWPLeo6Qp9WpYS9m3Qj479t7R636N9ey1rEjEn`](https://solscan.io/account/AQCGyheWPLeo6Qp9WpYS9m3Qj479t7R636N9ey1rEjEn#accountData) + + +The `pricing.tradeImpactFeeScalar` value is scaled to BPS format in the custody accounts. To calculate against the trade size in dollar amounts, divide the scalar value by 10,000 to match the dollar amount. + +
+ + +**Example: Linear Price Impact Fee Calculation** + +**Position**: SOL long +**Trade size**: $10,000 +**Calculation:** + +Linear price impact fee scalar constant, normalized for dollar amounts (refer to above): +$$ +\frac{3{,}750{,}000{,}000{,}000{,}000}{10{,}000} = 375{,}000{,}000{,}000 +$$ + +Linear price impact fee coefficient: +$$ +\frac{10{,}000}{375{,}000{,}000{,}000} = 0.000000026666667 +$$ + +Final linear price impact fee: +$$ +10{,}000 \times 0.000000026666667 = \$0.00026666667 +$$ + diff --git a/docs/perps/jlp.mdx b/docs/perps/jlp.mdx index 60ca4e4d..04cc061c 100644 --- a/docs/perps/jlp.mdx +++ b/docs/perps/jlp.mdx @@ -1,10 +1,8 @@ --- title: "JLP" -description: "Understand Jupiter Liquidity Providers and how they work." +description: "Understand Jupiter Liquidity Providers (JLP) and how they work." --- -## What is JLP? - JLP (Jupiter Liquidity Provider) is the liquidity pool token that powers Jupiter Perpetuals. The JLP pool serves as the counterparty for all perpetual trades, providing liquidity for traders to open highly-leveraged positions up to 250x on SOL, WETH, and WBTC. When you deposit assets into the JLP pool, you receive JLP tokens representing your share of the pool. As a liquidity provider, you earn 75% of fees generated by the perpetuals exchange, these fees are automatically and directly accrued into the JLP pool. diff --git a/static/images/linear-price-impact-fee.png b/static/images/linear-price-impact-fee.png new file mode 100644 index 0000000000000000000000000000000000000000..df52c9d5a6f003d6d92c8bb5ae56ca29030d3561 GIT binary patch literal 164389 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 z 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

%eA-l3&(*%2wC(h( zzF(&;i5J#kz=vonCgQvc`{?;E}j^9shk)I?Fm1J zL$YobGpPaI*+lE`53l@FU?Ud?fZ!K()T5H{WwPgqTh~0$YKE3Z*_8x1_1d zg8L*4*s1)DzD*AmB4pmyJiTbq4xp`r&#krut+sCy#AM)nAe58)ExP)j+V5YbGb~xl zJG9G7x>nG}`CROI%7k2rs>ZOtG6nYh1B+M8w~YcQ=jjm`omWc18F8c0zbpn%eM;$; zjyzN%?0@r5Fa1Nsgz_K0=^=MH%>lm4^Gn~?e|kCa^gjpgzck9mc%Xc}*20tjr~Uxb zQVFO=x$i}>yG#F4Wjl+h_g$#`UkvN12Map%beQ<7oB4Xa%=SI6Yn}_;&0>AkiWh}_F5AJX zNDzEVJt<;^&-hm&aH|*~9OaoENizGVH=oD&JTY^up0>O$L@aSqMEs1Zd##UR?PVqi z_oc%*pJui9eHWFW@F&GEW3OkQWyOZXn}a`xg@*jc>wrWPpd3g0>T~|FiimkX2MVK~ zrn_Xgez>ric+ggj5+v_qtYTRa-`qXYxiQ4PyK)Obn91PNm-&imIz$?aW2Gdg=v#rhvCURAPG>zR5|)|yLL`e^(Hlf|?@}NqlDgD6!WnCK z*@GRELex?qabbRkR|f$VuAW@4e^sdR3jeCwXY$FDaVg2p!ty*@ou!|K4ot}|g3cX5 zHg~>9UAgGhi|rT~6n@>F0Dp;xICO49>}slj0sv3X4y+o*5jL zw80;$K6Xl~l)NriNcQ>l?amI4e2M2NDp_>x-1`8Yw3H^(tzkx@1lR=9!<2_ zl|08s!X=CmCuO3iFa9j(v>HX!-8b^Xf7T&3A7E!7Z}o@d|FI7HHZctEov(x>>^sgECpls(e9TJ`DzdDeK~XTq|d?$+{B>DA@tf$+bcIfr^weo(W9F&DYFm@mRA^;bH_U3am-Xkj)h&sqmfRPh7p@ z%g5cZ+*ze1?fy2_F-sPlsYVl=dyfgzmX6uFrVyhu^&ufACw5(*a&so_%!xIYV$+t; zSmz^Eyq=*G5$(Kth2Reuo)M(uSlP9%Y(VYE zdubDif;;D$^Y+l=hP3ggEmdPJH3Jp$Nx|Ccc^F2J@E$h$mD`C7PE%nCAwX=we=GCu zeL)`}z9PRMx`s<%{??VL4a!%5#0jBYHlb4hAEm2oRlR4nA2iB0r4Z$iE|cxzs)dE8 zebc$`lqs2;Fh!VM2Q$m|bc^afLQk15+Xc~eyI>5-bOu5qIxwrNfog1W13QA;pW1|| zK%DIQ;y>%Pn6LQDcUnqOedIbJ@-*^TqxKZCAAvNdfRo)y1yb#gU&ai8Anc@I@^R-o9EMMZTOY+P%OZ$lX`R^?WDYc375& z(^qSxbsl?`Z+b}{fWMH~6AX+?(_b3%+|$Su{Xe-K4jxAadWoxCyrxf>{))Zy=+ zpTC+!Cod`f(O$)KKN4x|&k4%}0>%Yw?u|bSAM6wrvVOl>Tw%mG2PH`hQ!y0PA?26L zDkR({rVR_*;m}FEgI4At>%{3p>u+G*<+eqV$e7pbU4c!Yao+mnn3Qv}rpnx#*$?|& z#9@6$SE}3`1|KJP5{WC_9P`VVgeiB$EcWKq`ZN>2!|wMpkX%%ZuE0aTYTlM3z`gZ( zhwTrku;8?wmYU(-gBGZ>{_9r(~-G(GbiS8Mh4HE3U7i}OL8jr;a*VH;nX!Z z6Rn>$nrL}u8+6Ey&#Kr^xHqFCpGpj|;7PUz=&5AAd$uQHl?jREP64PVTq?8vTTaG_ zy!XgI)a*8E4hZH&^R-pgYFzbO#)2S6>}-n_&Sv{PhL zS>V^P)fhv79|S3venW65uk8=7IG`B@PU~GB)l6;}MD9={XsWDqS%-Ah2uYwv7=Kz_{H~gFs(vQ`o@QMF6+!8 zih6OsEC!{sx4e!POLF;Y_Ff_c_&k3O_e$*PQ(x>?Vgcvaeo9X;|MmZ4N(zL4)~qNo zFEg~e!*P|pQa#RB&n9Im8u!!7KzjXc`bKDoN0ZGxtx3f%f4F?n={NDVce?Kg{VF9R zu`X9I%zkYk^Z4b<-FHfw5mg$3mI|x_juEK2@6fQOwUm&zQ{NTaHxi2H5b^AoMtt-W z1oJn|hU$^iS&P)M(xUBu1@{;NC)KL6ob@@=tPU1r^CGVU-6vN%f=${kSX0kR0?v^Z zE^$TkX7%y~VPz<8pN@|Xq}&=J&0EU7KaUHR z$klCZnOHjg^2B(=WI9L~cBtq|Pk)hJ)83<&BA~_2{wygovwI~3OaGooQ^E?~+RF-? z;~63G>USv+I5Nb0JY9ip|{Cx&O=FH5$Yek34b4DE!e884a~GPk9xPP{1Z zMPey?sw9i~`3dihhmaO2Rye!o3${jQ`mcV(^M_Ina~szO45b~X-Zbw`o!k3OZco37 z%?Vn-?zC$+RF*pO_@_W)y)DR2A}8O)Oaoe`1HHAP1K4i`-Wtr^)~p5o&zwD`JaT{j zJm>Zzn+1aNmsunC5$igz*E&&twqyE4Rp!USmOo>cBT!U?utyr`c3(E1^t0CKA2b4| z!}@agWrj#MqKJp~5y{I}odb$DLUuW1p~G~u@2t=ApZ8(wPjF!i`KmQOdc-C1_Kmno z4l&y94hf)=@w&cgq)EXpBa46@cA0$E@4-X)vXdB7+!*FwKOz`(FhgmF6k_cz`@O=& z5zoAo=QH|Ad;HiFsKC9z*OK(=kFAOtHHa112#j5+wF3vqmlf`9CPv#N8sY@TzG_d7@ETkqxxi6>( zj%r{7R}_EQ)dN(^&n1VFpBwJ6bcrr%MF}S~hbK_Vl1U9gnjHc#S+#iyV#KY=#rQ@~ zx`D!+grc>Nzr$F#K)P@@`F%3`adtVYRzlx6cl}hRDlm8b)|+I;JOfRR=2-dRUxaro zM7JIt2mLW~6bO+qK2P@{PZgSJ5&rZ-Q9<8wufcXsUE>agB=&IzqRs)3o*G}7U^QdL z0yE;NN@xm(7l>4%SGdG^SiH9|=KYLyz|V%xpsMd~l8VDo3gRNsel8yIhvFk-XyKu* zHron~)m&-Tj$}!$LuAZueuL_gDq`Hd-?qw*Qyg)+8r~$c3sELV$TNSIxMr7{2_JrB z1G_Gi4ogJzGiZ|H=`vcY+BU#VvlW;QSK|JHcEXzrk9fN}-}~LNu*{)##p;zy^dS`8 zS#Gi1pzHi>=-#LQ6@KHph=u~R&dyK5QD!9_o(#fusJt!ph#$^yruRQCy!bi85Pbzh z(3if@OXp55+vQ>k?T%H@NrZ*TSvb%C1djh2kIN5kZ z!XaEhK*&!+|FRr_Z0MN0@B$E#zUp37V3U>pO8=1oNgXnQfo;yK$cr#g!xi1ue~R?0 zVwg40Vm9eid$N)N4B?k09_RE97ZGT!xk(q|h7}TFk*?8DS;ksThMM9J)E;=QO#TZ4 zw|)fNxDiU89hju{9)9khBuMi`GG%fysymb-WV-^Eg2IA-xZUAew*U0;yB3tS*K@9X z3XyXrk3*Tv9Kjvy0{^%ob$$Qz>AzOdhb4Aj9#~z^X_;10{`l$D5{8W4An`7=ulCuq zSQ!-)TU07u1zFTit4*4Bpz|5;35B1Z@k@HUs&x%JvDjs7D?sb4LjM?j|ta@Lz zub^E{DXB%J5+UtOcMr>9E)LCxl{wf@e`aGB6()+I1oV;1XTWIG=;&!nYkl=ga+;G4j%aOYNARjmSaYI+6qi+l_(ZYD!COi5vdwo zJHvtdvY4XXlSoRwIs~ap!JI+PW>+%BEeQs5vn8O~xx}(r;3AomcVl{b>>WO41ziS) zSzC#MKcKp}<7ZQv8Yskp#}r{n=h$8OIWL{>OnE*?gKnTUm31;0aRtvXw0YnRo{(fU z+`NN0v*B%Ztm8-!UbktY@mXq&bmpE=YGS|OpM28g%4YYDT9VdLruxOYr67T?@V?*bj#+iRE;P zjVd!^o;agDvf1TiIcnNv_xdx}5&QeVvKY_yqhEVo*Hoq)CohkVq|z#@rN^6oVG)cY zB=`vyWU!)0YUlb-ck(2k@CSvf9|;68D@s6wn$VpZ9!t8zXPt;?c|)^bM}E62YdpF{ zXVQBAsNnm^5na1(6q502*HS>mYcEBSfA7%$G8{2?%;z~xP2IhqhfVu`YzYRBT`|$X zw%TLJgKzi-1uVW!GRe-8?;Os1&=N4+ALDgBwD8deBCBiFq1rR9GVLQie`_adKof7e z;K8UraovJ{U>Ic2E%W_5eY?`7a>|^!N9cyk@WoL}(^L%?M`t)?6En!(gEwF-LPvA6 z)7z`J)!Vx#zxyzFS-72{(J3e^=`kWM&(H1mO6oSh0?yM0zl7EJA7WT)X>cL#EfJ_P)slEF%YL3|c00_<0^;w*D<7|?;e4^ybm*K@^`v54 zaQX8tLCC9^xlYCQA)k4=IB(h(# zcQaS6Y%7jcWK1fXn51L5!xK0OCJ^7dH0(1_i+1Y+eE;w>s*m(WuYAg0AuMI{h)d334t3>ITW=x%NYMq#iO z;4iQ5U2k7*1{rll^R#GLIj*cD3LXtydF-dW8`3W)&=nG5geE^jw<41h`D>u@>FJkY zF9NaS%D-%D3X*Ur6FAHDtmm!ya5Ii*IAPoG@}|g)q5rSFvx;iF`}#bEQd+bW_X5Q= zP!cpav^b@>OVQu~f)olA_qG)GA}tWSxD#B9yA^^5mjYpUX6AkVedlKGXHD+1)=sj{ z{_U*&Ip4j{J}Z62I63M`3a)y_*9U9V3nwPjp5(&pDnPS8b;Fm}zhOKK#_yM;t8j=$iCrbrJXGf6 zQqY~yD$kow(-bthPBqv}np`VLnzkLH^ms%97Z-Y%ltoW;LLAvYCo*T;%LAWGUp8jq z;St!v<9P1>lZhy+j5|0csfbiBV|bWB)N`_c$pOYgPZ6NitA)UfTf&gsIk1U)+>;NT z4&yk>Ftj$II=EuT^UjCN^)DPcuzFc;z6b4bmbBA37cjN{dQ$s2hIUec*S=}|S*Hu? zR1S9lM~C?30mgCpdM6o`ULBC;C$$8Lm|jVC??Fyumg#2PAIA?NtZQO?JAtmZOfW~K zhmO9*`J-U(;X)UxpcUupwWDH13n`iVA+}IVaB0PC1-A!Z%d%dq<187J@5Cr^s}v?^ zW7vEyG|osz)@GZ_4y?nM&34`;+*Sf&4sjGs%y>l#ugKMkiC>OXE^_0)%L_lFr$7SP z3mWN2FX*_ZUY;?mT>l8qIleoCloz92KO?{Si;DYc?R*K;t8%D6H#9eG1zkMv&+UPAKgf`%B+-4MSN+{*)U4Ip(p`-JetV%q&aQW3Honer z``(2@*MQbZOTJUYIse%I(E3DQBLPSeyZwP?_+YqWyuDb75R~c1`|v;1Wy$hf=DOn3 zXVjCwva`BUo2m_J5oKd>^#~Wri@WE8+X?~y`1mfkJ;nwNe%k4)V5?hbp{3)*)tQ0X zpLl5D{GLvJ6`cI?Ti$tn=XQJHfcxQ&m$%ucU|?wf$Y}i+jFK>hs&bq&{C8Riv(3h7 z3!yaKuak9DqS6#4&n~Xi6|KdV0YZe#KA}g~IAUga{q`=PG(Z8_n6xv0BQc(t9-nQ+#Pt7o{>PhTNV)zLPh}lQ^j4PR>q3EX?^IEhymACGsZp8 zY+s5V3!k7J*&QE9$S{qf?(Tp=#evuc%!pOj2z1>$duQC1mQ)%vI?nUCyR*=smG{_I zY#qcxmt5$lxuzSSRZ%kuz}L@#GMAPiqtC^J)?KfGDVG`(?8d7(^TV%hlF}+5hTpAQ zHeE<%G7j@)4TUaWCKsJ*EpV542z)}6Am)w0Em*u%(;*gi^A^5&qiCv-bBu?+(-n0B z1`aRgpnK;xrJJUSlYtW@O5CqG+6%b3en1ADK=Bf&M4fC+h^h(Y7#pRaT8vcd^6yyP zvA&zNq7-ve2>G(>>8-xqM&7O$Vkvrsa>jA0X(;O|LafF|W&&AH60x!x zsxVEjTI<^KgZ-;{5Mj0uBA!u`c06b*)%%$f^lD*?bgyl_3MbFE zusbvg7#R`gmmbPc%kLRn$;5qrIBNP%tKkNLcV zVQVpBdYKPbqTyquX1-*kchjz^lDu8%n^pa~?91zOp3XWZ#%i7y(K{9E(ITeh7bTKR ze!E9qlX=3{R`=JW#}R$+d2qv$QR`Gizs*_>wjq?p}suHh};w=#`s@)ZF?%b|R_ zNfqGkAgm}!0Hf$&;|1yPa`&#?#wgDcCwpo4C+)^^HwP+D-QC&Kuj_|Y$A|iFYL!RU z5Ck@!T@#ua)iQEXe4y*N$?e3t+o7Qw!!F-`(W#GJ7=sx?)wA@Dt$raD+9f168)+OgL^0C1@hWYew+As66(>W{kg%O7>JYcbor9EKDz#lioL9&GNJ?| zb29`(&&eH6tS(*r92+x{&C%5VmIxbo7TO#tj~}3idE>gB%2}Y z$J8gW3Y-ToSylRP6!SpwihVn7+<>73c!&HHtvI3R?srWhjnvaEb<#EYzY{3UW!Mg> zZm|G1bNuAb2=^~_Q!Wda&xEl3Ha{6|?X-I0ujS5@BMsMGn3lP$q&FO_f0u3c2ReG& znhz&=a2f*i zh|bR9I>rXEmJ0yzSfr&gFuzk|aq{6wjG~^wNQwEVcy`)DqKm&|`pu!m*`e(7_<#!v zN5qIuIw!N{d;5{K`1QpDMbi9R8~2s!2CC!+p?0Sgak*k&`^^5 zVLUm(+F>*74B~Fy&**a;jD?ury7Kl=-5c3*X70 zELM|-j$==$vy+ShoInj2^iuzZ%w1a8y$%(u(bhb9K?xjcHtiG--d4T}WLf3ax4*~Tqi@$l3Jq`S#*115JVn%d_Q=g1l)M+kTjIN}d zaYB#@uOh{&%MCRhdQvWUCKp;VurgpfbDH515TpFjwdbv!0YyxR>t$4zx*=z>ms7z& z>J^d|WSvPJ!iAoSx{x2SZuDHZI`=%*3Th&}Fq$E=$;zc3|LNZ$pLnKM$4c}AB>g=R z6O4+m-~66>>I1O1l4*UafFW;2X&Gzaz+RkM4^{wOSE`aC>1xE;$P@Kwk1ac=>evIw zWtu1#Ev39`uxRR1b23vl=$A;E$D$83ABjWlo>>r$o7J2NN}e|Um^qwb6DyA$6XX12 zC-aHnASDypyEZD#?7HTklpe*lSsX-^a)=59olIuc{oqo2z2`D|p!g@$0Q+R4-{>YR zCI+v5O{NB7W-B3j^d~E05gD(4)=0T6xVx?0gj~pIrnF#IfuT{sPst``?p9oS)EBk; zUX{@K70{7R2QvB%XVo_>n_GS%1i}9sA~XMk$O)f5-Tp-vF3+CoRY_2c_+@q!q@T{c z=}H$B$Q(YQ*DLqo%QP&9mJNed&_D!;SsqmP7|)E!Q^0L>w^J*tK1X)gD} z8(mUTkEO>app_7ZXT;0x9Ysk#3+V1g-!^{b>_MbRPxLce;S30^Wow(+KgujEY7GG) zyx#RX*vV5I|R?z=O5Hjo^OllwSJ4peJ*PG0U)|SODE-8TW5a z%z)DaNKVmAmj0nalhlzvdZbZ=SMcC{40Ot?BgAr@9asx3DjYv6T{!U_*kRxKHLiBf z2{A&9MQ;%+xhAb&{j{2ZvgA(^2uC5|)Qa5?=Z+?X3bWncUO(Pqy zvJMjxPU#yz=06DZo-mN*blr^#mMspF;kp-|A-2FdihG0LH!6uWgiSXd^yF~Mgs5UF zOh03olc)NNZu;5xMm44J(_e}=Qhnd5W1Ea5x3s`c`{}P~h#io*+Mh0W9%tG(-o3w@ ztFC$)cjramrhK*+u+nLfN)>1N^+Uz20madzQtUXATP9;ZE3Q7`mS_Ryr=uRNDylK# z0QNtb*2kWNownM|bO)vE2<7NRL|csgj^O&^P}^|Ta%}Jy8SKmdBf&Cpt>gZ+$s>AY zw)E?5)5WdM46Su!78rsrih<00hD8?T+EYxUiFid!gl%Xl+Ny2Y^QJ+z#t72gu0l;2 ziDUEP=TrQ|QS>nAUN_b)XDp=gpYT9sE#Vc?%cwZSzHo46fd{-3<8)w;P8lK9gC}7ndWBEXdL58)nu%?b_jA9hY@(#a}wpl&CS7)J9+jKg8cAR>*0NC4SM@%MBC&b`C#^&w*lJe3PvQP#4>RDh~J zZ;Z{o8_(J>bB*i=cvbe5(jns_t-D)rl!2t3!`gJIb;Bc<0dT#SYdlDGxp;al#hwaA zCtaSC)|!eqqyzBK-OX)s{qH)#_EtYA{Ml> zg%l$TbBlQcAOHd7n-%NjM-uLT?!cKNM<3xhx2m?(*`G#c zdp$;%eG;xyY7D<#zRXN6zgur5rc(n;D&0W1t}Z>Cwv1lQow=Pemuw9F=SXF6M_| zx*~IlD=HPJSog*?+Q^H3ZJ#1XUo{SNGe6F**RQ}Isqt?XByC`d3-4XCf?IM0Dojn1 z1No+kDRFUfG527%1&pNHM0LXh#k)s)$Zfr!8SrQX;fBN8^^%X|5EVDUn4YEM zQBGDMCsAhH@t%tnkLmR(T^+`}XiOgLomgpWaj%%jTH%$syZtA#bZUOB{veYp)?iFt zgkda&)p-F-60`n(rr=uD%ZZ74_CI5Nsvuu{U5tBfVnQrpA&a|J`q07n^c^suK6H$82{LH+ zZe5qUw`T8b=BWgIW@7lq_eaLgmKnQn2=gBgI?XA=ZPsOWe_=I>p~`;Zr~|{c3h^ zzRlYv9Qnx~3bJSO?^ZtVngidH7N~~LXW5w;JFMRtMi6*ggXh5pf#w!>7%K1N)KR>v zr39^a5-h1@uerLE@qU#zekr!;H9^_6bqY3`ufzYa`$?XcqnX zE5*M6{o$#w+CLjYHmR$IzgQd1{qW1~bygW)&mX!o7t!tKD6&wtGOD&m>5p(xyneS@ zqM3IBcm$6WK(^A9*YIc=CyNrI&Ec((So4@6_B8mctOvw<$4Oiu0LOkGvhdm*Jkc|B z8G(KkjaM+!;;hbT)*oo7+H(^maJRrKCHuqpnn9?|(y{4&Zz?t#VLd`ch?xvnRvZ zQTknQr0e(2S*#{kTyq=UeYTH&P#&j2k7D^Uv5_1yweZF~HN8`*lghiroDbZ#zWp}khQU2t&b1hS3 zRT8)b9~j4g@L^aONk7v1+>x@_LbWSkUo8_B(y=dZnFp}+<1Qf}ESb>>WdM>{(1gI) z5Y`*nn~RoUZ=BQnaw^SoeqJ(QjW>>B_XYiFIB=zaW0AjH@nu;W$Zfgc;~vLF>B?0j zC8dm~E@AuDx0(A&e=kbNjwO2RwRA?*)iSBQ2mBF?hHmiiLJ|2YpiALefGvw^Pn?e} zL6OY37?~`*m?=}fiGO{ z|7a#VAMPG@A7_qVgNI1&h|l|KaWNmj z*szNQ9l0_2D?_>1-x`e0eB-}ybWtRy$E>%P?&*lbT87U@CC(4b7S%og0y(u^1?`=D zj~FumKwLp}-JtV8^kXvZXo!zH$Is2Qlr$&v_89jV8GpI>*bDv-nr|M=Ig?}&pF!sJ zet+L^Jsxm0SPl^V8o6N+zjyisl8EjxQC7$2wP98-jOXA-NlQ zc`B_LU0ZQXRkk`q0P);e^LK(PJa~JDjTPnl$XFuFSOLGHr|U3t74l<&h;eWzN%b#U zx>LUYFWvFk4OIMBqPed&9*R9<=PvHZDD#g?e}-#$c&`*%y3S8z8d%qfmIi&|Y-pJ_ zx2cclm<6{dSd@Z7_Gb&dtVu>b>Ws8RI~`wxRiu>&S)9no)P#PixI(R*@j{_QRzHP% zcxx=g(n<@gKy3#A09i;bP;f2gzy}&txnA(SnZF2`V@cnVBYZc5tS3#{HRDe?EaURE zcqNm}dPt@-v3`b{5qGD_C@0OpYL-YAlOXQ&RXpIMfQ*!OG@}YFiK@2GprfY36BHoz z{jv?W!UJ{-zd_C+{R8vCs7&JLnk{F-F++gH?uS|$UQA)bTZt*Wq;FH~{L0qrqKnL? zYHQp3Uu9qz1#DtG1b~o<@?uA0kpj3q&|Z@6nWdIwu_|9YMJJLjYK7tj^c*f^FsCM2 zRnR7bTv@Xv>FWskIEXef%?Eda6vSag9YcD3HHUC_*Lta=f0k{ylt!SzMugiX$$L=t zq&4gA(`#~(B72QkKbGhz=8ln&0XCMEXmi)pwvyPghhyU?Bh12K9M;Y75fMp3Ewu=3 zhK%yk?C6A-gF_~1`RU!i3mR(Q#B1Bvs6ClWrx2CMi-4)pXND;v^GmZwADU@TYUnc$ zZUd7gD6=R(q>bzaAGUQTK2nPnx=RulZw)6FgNx#xw=Ghzm_e6anxs5W{CUSL7<`|@iGoA__KL43^o5>#^MrEt&1E`wv(ntq>*z`aCol2@uR5WWj zT6HNO$~#P-Br_6DNrWUYb#0khbtvkYB(Zcs&(NpS@T^CW)>25ChFlf*n@@+>*TybE z{c9^CziAblz)WjwIhNE)x4-}TlcMQtCHF}y%5_zIL*%2|QJXQ+t2^0Wb58I(b-`Ed zX*)^CsAn5L2_Id8!``|4#br0Hk6$>Cv}ZVT=c#NeW&kmgqIY8* z*u3WXs=3;CJ5l3D-JgsH33NNyvBgB?K3j0Z%vkdbWQc@&4UNcJYgzM>Ev%@Sx!L)- zYU0{Qd|1A`5g-33?BCv5@m4N64DQO3eDwxQ^As6FL+LSAV>v&&*jnkjo_-;)0x24Q z2%L;R8_c2Ga`Le7@S$?sb~zhuhJ4c#Zi$oJG>Y%Fjl()vXohxy&+S;J_TO~Cu|O)g zo%tlsUe=bCF2!C@2Amx6VMqS}I;g(#fDnG)Zn{Y_eDa=@Z4vVA$Aq~A9+8V7@$kaY zcj$tNo4t6`TcN=D$_c-wa$CMgdp|RP$l=x?FLZ`}@0ad1XT>ER?m8d$TuyXvG)=`y zg?{kryNT5-=PK!4`tCN3H>X9L8Jw`xGLOidxfyPOnURktVPWRy%WLf1^e*bHRl-;d z+{uT$q%M`PczLd`N8 z$&bb~avq+4f&iO5_@_cCzIW-fP3oD1g%R4((ftw~CevQgI0>Rqc%3LCZYlL8dv~`~ zu@z3fASCo8ArL3mM0lgz>OGhy*IG-;`nP&=$}N`9^8}|eJ{_{vzALesS5!*1ay?Ag z`VIv8lN=hbDVSTd!fJA>NT{Na(*2R1df)040u^R{b19teIF}lPm|+D=ZQy#H-sR}( zCqPd0%h#j0LTn!lQ&y?qX}X5yBFc+MLR-BgqE29UYIQU0^J*lh(GmH*Xy< z1&%Gs9uzhP4rV}eoUW+Zl8`+MQ|^V+_wX1X<|LCU2?MK011p)}@eUTOco!ha<|;eKa*M`bS( z{}*@pn__YStpS*pJlJ}XDb@iCz>S10R8aU5gpWmw+= zgB_(_Fv$`!u7JdToiCC>=h^ZWetZ<(aUp%@p@6$g+93f&6sy{t$|rkC&^L-lBvA1n z99isJuRD3I`*b<%o)Vcn4S5nwXrx8uUT1pwl4|>El9X%vPDsJUh)hD7F`hI3zL`f9 zqq&)!j`?P^CYT~mqyx}k`ciW8t;#{+OIafDwGh#ADPO@B%?Fx-a$;*5Vy2Ld=ziFh zF6kr=6K`*zB7AG4APcQm!$QRO{wJBY&|uHh_`a&9mVEox4mDOY02d~VB)X$giK!7~~}^sSYA4RV)Eh2`Y#k_*uNcGL!Zs>IvCE(Ca@r;Ue-t-*uE(X9{f24n@ABRUAiiSyRf`kNS5g(` zZQ_sAxN2b&_;hUZgK`NI%*jvJlwztv5oS^#a)U3hrEVQZ2PsZp+Hd@E;Fu9}O>dze zCETJee$5HRPro!8#guIp1s^~au`sckiMy|-%MAHX4jWyD>B6HlV}ek3>{xxXehsvH zW7%KZ55b2V>v0BsZEN9`Ke&1tBAwn`1YZmrn|A8aV+Bz?A?dn$+H;v2c$DKe6oy70{T2IY;fFd-b0ODYC25H~Lwu-ztJ|4I!9KX$@}=!*bd-o~mTYrEqHd7YW)h0iUaCHZkw;CmJ@H{rXif{5@S_1OG|N-! z4TLgdQiIjvS{H>EXOsPf@&`$@kMIuTm{yROy>l-vg*VfPep@s5zQMhCz|Br;pH*X{e=#1JrfFA#_g04^l!*-MU}j~YdVS)YHqMz36rLg78vhDSqurHIWz%r81qfU?#H zXVDv)2rO-x(Ol!EA;|q?aIkBR(ZriOkmNE*x6G^RL-#S z&@OIwGo+8xEFgq)AFa*Ro-qLU60h!&RSbxZUIZ|I?eJNKCm3OO+U$X3T56U;C|ZWw zgGkBswo0bQuHcch_Gb@f_$LQ?FWDr4W}E2*Ic6wz*TpXOAMBMky-i#?zH za$S6=z#YlCbJ*Ks_o}aCl6Idyj(|?q7>eB4_KP(idyYHCS#r&v z78SI*YSd)^7zg|Pl?|A7AM>}C4lqNUd@%a_C)1tHpF80+pplrvK)2Zm#%d@11Sym%DHXtI@Hib$ z4f2esv?UOB6xX50!)=UmWdEVj%5g|DtMbL7dDuzT4~J;U*UW9aeSW`|Q|Y3vhU<~325GCIHHWVxds+JJ z{;NszUX+vmXG?|c++bAs?~^#3ev!>2Ux`<|HRqA%UdNE;b#Q+_EL%rKaa-hB3K{e< z=s8nwbeEoK?BQpCK;7nwB-4 zRu;hq@Nxi`$=_hRqONkE*(HyLK5PA5sWeUa@EO2Bh-UYytuwxh6kNGzwBC5S+?{?5 zYMBk1*rQe;7g8A7qI8tmpz}%UCjqtPTiBg)IyA*5tV6N~HXFzph>+FO_HX;2~u2>&WU({6*3?MoV>U%TVgk(NU?=4D9C( zbIpE!tLu(tB)ZJqEC`E-c`@A4GDj!C3Mr@`vC_W3s~g5&q5e3~lIgyp1u*~2_ZQ0i zPYv}@mo57keVMFgx%;OzdNs4_Qf52HNkM2L5W>f57PCMsj}; z<9AD|o5x>*)L)Ie|8>shz9(n+pNwJCCeZY66#Pfc{ckHyU%0oFtVfj@W&Gbvs|Ej2 zfvL*z`TiA#|Jzsn=M5X^-ctSGnoF1M|7N=X&(rsO#NGK<)B4{k^S>)?>-(p@{qr@t zfAary=Kr}gDY1J;HD^2+IQ;k1|8dQKGyeZB{eRG