# Welcome to Kana Labs

A brief intro to Kana Labs

## Kana Labs Overview

Kana Labs is transforming the Web3 space by providing accessible solutions for a wide range of dApps and developers across DeFi, GameFi, and SocialFi. We have unified nine different blockchains from both EVM and non-EVM backgrounds under one platform to address liquidity and interoperability challenges effectively. Our focus is on offering diverse products that enable developers and end users to navigate a more user-friendly, tech-abstracted Web3 ecosystem.

This vision is brought to life through a suite of popular DeFi trading products and innovative blockchain infrastructure solutions, including cross-chain bridging, liquidity aggregation, and Paymaster SDKs. These tools simplify blockchain integration for developers while enhancing accessibility and functionality for end users, making blockchain technology more practical for everyday use.

### Evolving to Serve Better

As Kana Labs grows, we are refining our offerings to better meet the needs of our users. To provide more targeted support, our products will now operate under two distinct brands:

1. **Kana Labs**: Focused on the DeFi trading suite, catering to traders seeking intuitive solutions for managing their digital assets.
2. **Kana Labs Build**: Dedicated to blockchain infrastructure products, offering SDKs for cross-chain bridging, liquidity aggregation, and smart wallets. This division is tailored for developers and businesses looking for efficient blockchain integration to enhance user onboarding and retention.

This change allows us to specialize further, ensuring that both individual users and enterprises receive tailored solutions. Our goal remains the same: to democratize blockchain access and accelerate the adoption of Web3 technologies.


# AMM DEX Aggregator

AMM DEX Aggregator: The Aggregator of DeFi Aggregators & Bridges. Effortlessly swap tokens with the best rates, low slippage, and unparalleled speed—all in one place.

Kana Labs AMM DEX Aggregator combines speed, efficiency, and security. It simplifies token swaps while delivering advanced cross-chain functionality. Built on the Web3 Aggregator SDK, the platform unites cross-chain messaging protocols, asset bridges, and liquidity sources from nine major blockchains into one seamless solution.

**Key Features**

1. Multi-Chain Trading\
   Trade across nine major chains, including EVM and non-EVM ecosystems like Aptos, Sui, Solana, Ethereum, and more, all in one platform.
2. Simplified Interface\
   Execute swaps in just three steps: select your source and destination chains and tokens, choose the best route, and complete your transaction.
3. Comprehensive Liquidity Access\
   Access liquidity from platforms like 1inch, OKX, and Jupiter and proprietary liquidity aggregators for Aptos and Sui.
4. Fast and Reliable Swaps\
   Complete cross-chain swaps in 5 to 15 minutes, supported by fail-safe mechanisms for reliability.
5. Optimized Routing\
   Use advanced algorithms to secure the best quotes and fastest routes, or choose a specific route to fit your needs.
6. Gas-Free Trading\
   Trade on Aptos with zero gas fees, powered by Kana Labs’ Paymaster infrastructure.

<figure><img src="/files/F1Knsm3mDXB525mZB6TA" alt=""><figcaption><p>Cross Chain Transaction Execution Workflow</p></figcaption></figure>

**Supported Blockchain Networks**

* Non-EVM Chains: Aptos, Solana, Sui
* EVM Chains: Ethereum, Binance, Polygon, Arbitrum, Avalanche, zkSync

**Your Gateway to Efficient Trading**

\
Kana Labs AMM DEX Aggregator delivers fast, secure, and user-friendly trading for all levels of users. With cross-chain capabilities and reliable performance, it simplifies DeFi trading.&#x20;

Check out our DEX aggregator at the link below ->

{% embed url="<https://app.kanalabs.io/swap>" %}

If you are looking to integrate our cross chain swap widget into your application, please check out the link below ->

{% content-ref url="/pages/ZKLmXkKJjFX5PrVYFkwx" %}
[Kana Widget](/integrate-kana-widget/kana-widget)
{% endcontent-ref %}

If you are looking to integrate our crosschain aggregator SDK into your dApp, please check out the link below ->

{% content-ref url="/pages/22nmi7cXB8RIp5M5RZ1w" %}
[Web3 Aggregator SDK](/web3-aggregator-sdk/web3-aggregator-sdk)
{% endcontent-ref %}


# Kana Widget

Kana Widget: Simplified Cross-Chain Integration

The Kana Widget aka Kana Crosschain widget simplifies cross-chain swaps and transactions for developers. It is a lightweight plug-and-play tool that can be directly integrated into your platform.

#### **Key Features**

1. Quick Setup\
   Integrate the Widget with a straightforward, plug-and-play process, saving development time.
2. Customizable Design\
   Adapt the widget to match your platform’s branding and style.
3. Simplified User Experience\
   Allow users to execute token swaps in three steps, supporting both same-chain and cross-chain transactions.
4. Keyless Wallet Support\
   Enable users to create wallets using Google or Apple IDs, eliminating the need for seed phrases.
5. Real-Time Token Swaps\
   Provide seamless token swaps across 9+ blockchain networks.

#### **Supported Chains**

Our widget supports nine different blockchain networks, enabling applications to efficiently serve users from various ecosystems.&#x20;

The supported chains include:

| **Name**  | **ID** |
| --------- | ------ |
| solana    | 1      |
| aptos     | 2      |
| polygon   | 3      |
| bsc       | 4      |
| sui       | 5      |
| ethereum  | 6      |
| zkSync    | 9      |
| Avalanche | 10     |
| Arbitrum  | 11     |

**Benefits**

* Enhanced User Experience: Retain users by enabling direct swaps within your application.
* Revenue Opportunities: Earn platform fees on transactions with customizable settings.
* Increased Engagement: Foster loyalty with smooth cross-chain swaps integrated into your platform.

#### Why Choose the Kana Widget?

\
The Kana Crosschain Widget reduces development complexity while providing a feature-rich, user-friendly interface. It empowers your platform with advanced cross-chain capabilities to enhance user satisfaction and engagement.

#### Get Started

\
Simplify cross-chain integration and elevate your platform with the Kana Widget. Follow our step-by-step guide to get started in minutes.

<br>


# Install Widget

The widget can be installed on any web page with just a few lines of code. This will help to bring cross-chain swaps across multiple chains with the most efficient pricing to your website.

Install the widget via npm or yarn or pnpm

```
npm i @kanalabs/kana-widget-v2
```

or

```
yarn add @kanalabs/kana-widget-v2
```

or

```
pnpm install @kanalabs/kana-widget-v2
```

### Basic example

Here is an example of a basic app using **Kana Widget**.&#x20;

```typescript
import { KanaWidget, WidgetConfig } from "@kanalabs/kana-widget-v2";

const widgetConfig: WidgetConfig= {
    // Required: The unique SDK key provided by the developer. This key is essential for the widget to function properly.
    // If you haven't received a key yet, please contact the development team to obtain one.
    sdkKey: "Your dApp/company SDK key"
  };

export const WidgetPage = () => {
  return (
    <KanaWidget config={widgetConfig} />
  );
};
```

### Troubleshooting

If you are facing any issue like .

```
// BREAKING CHANGE: webpack<5 used to include polyfills for node.js core modules by default.
```

Please add custom webpack settings to \*\*config-overrides.js\*\*. For further details regarding custom webpack settings refer \[[here](https://www.alchemy.com/blog/how-to-polyfill-node-core-modules-in-webpack-5)] .


# Configure Widget

The Kana Widget streamlines user interactions by allowing the selection of default source and destination blockchain chains and supports custom RPC endpoints for efficient network communication.

The example below shows how to preconfigure default chains and RPC endpoints .

```typescript
import { KanaWidget, AptosDexsFilter, BridgeOption, Chain, WidgetConfig, ModalType } from "@kanalabs/kana-widget-v2";

const widgetConfig: WidgetConfig= {
  // Required: The unique SDK key provided by the development team. This key is essential for the widget to function properly.
  // If you haven't received a key yet, please contact the development team to obtain one.
  sdkKey: "Your dApp/company SDK key",
  
  //Optional: The name of your dApp or company using this widget.
  integrator:"Your dApp/company name",
  
  //Optional: Configures the blockchain chains that will be used as source and target for transactions.
  chains: {
    sourceChain: [Chain.Aptos, Chain.Solana, Chain.Ethereum],
    targetChain: [Chain.Aptos, Chain.Solana, Chain.Ethereum],
  },
  
  //Optional: Configuration for decentralized exchanges (DEXs) to be used within the widget, 
  // categorized by blockchain.
  dexs: {
    aptos: [AptosDexsFilter.Pontem], // List of DEXs to be used on the Aptos blockchain.
  },
  
  //Optional: Configuration for bridges that are supported by the widget for cross-chain transactions.
  bridges: [BridgeOption.CCTP, BridgeOption.Wormhole], // List of bridge options.
  
  //Optional: Determines whether a guided tour or walkthrough is available for users of the widget. 
  // Set to 'false' to disable the tour.
  tour: false, 
  
  // Optional: Defines the mode of the widget as SameChain, CrossChain, or Redeem.
  model: ModalType.SameChain,
  
   // Optional: Configure custom blockchain network providers if you wish to use your own instead of default settings.
  Provider: {
    aptosProvider: `https://aptos-mainnet.nodereal.io/v1/${NODEREAL_KEY}/v1`,
    solanaProvider: `https://greatest-frequent-owl.solana-mainnet.quiknode.pro/${SOLANA_QUICKNODE_KEY}`,
    polygonProvider: `https://polygon-mainnet.nodereal.io/v1/${NODEREAL_KEY}`,
    binanceProvider: `https://bsc-mainnet.nodereal.io/v1/${NODEREAL_KEY}`,
    ethereumProvider: `https://eth-mainnet.nodereal.io/v1/${NODEREAL_KEY}`,
    arbitrumProvider: `https://open-platform.nodereal.io/${NODEREAL_KEY}/arbitrum-nitro/`,
    avalancheProvider: `https://open-platform.nodereal.io/${NODEREAL_KEY}/avalanche-c/ext/bc/C/rpc`,
    zkSyncProvider: `https://open-platform.nodereal.io/${NODEREAL_KEY}/zksync`,
    suiProvider: "https://sui-mainnet-rpc.nodereal.io", 
  },
};

export const WidgetPage = () => {
  return <KanaWidget config={widgetConfig} />;
};
```

The tokens option allows for filtering, prominently displaying selected tokens in the list.

```typescript
import { KanaWidget, Chain, WidgetConfig } from "@kanalabs/kana-widget-v2";

const widgetConfig: WidgetConfig= {
  // Required: The unique SDK key provided by the development team. This key is essential for the widget to function properly.
  // If you haven't received a key yet, please contact the development team to obtain one.
    sdkKey: "Your dApp/company SDK key",
    tokens:{
        // Tokens configuration for Chain.Aptos
        [Chain.Aptos]:[
              // Example tokens for Chain.Aptos
                '0x1::aptos_coin::AptosCoin',
                '0x5e156f1207d0ebfa19a9eeff00d62a282278fb8719f4fab3a586a0a2c0fffbea::coin::T',
                '0xa2eda21a58856fda86451436513b867c97eecb4ba099da5775520e0f7492e852::coin::T',
                '0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC',
                '0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDT',
                '0x73eb84966be67e4697fc5ae75173ca6c35089e802650f75422ab49a8729704ec::coin::DooDoo',
                '0xc26a8eda1c3ab69a157815183ddda88c89d6758ee491dd1647a70af2907ce074::coin::Chewy',
                '0x4def3d3dee27308886f0a3611dd161ce34f977a9a5de4e80b237225923492a2a::coin::T'
            ]
        },
};

export const WidgetPage = () => {
  return <KanaWidget config={widgetConfig} />;
};
```


# Configure Aptos Keyless

Kana Widget Configuration for Aptos Keyless

To enable Aptos keyless functionality in the Kana Widget, follow the steps below:

1. ### Registering your dApp with Google

   #### Step 1: Sign in to Google Developer Console

   1. Navigate to the [Google Cloud Console](https://console.cloud.google.com/).
      1. Sign in with your Google account credentials.

   #### Step 2: Create a New Project

   1. If you don’t have an existing project, click on the “Select a project” dropdown menu at the top of the page and choose “New Project.”
   2. Enter a name for your project and click “Create.” Detailed instructions can be found [here](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project).

   Step 3: Configure Consent Screen

   1. In the left sidebar, navigate to “APIs & Services” > “OAuth consent screen.”
   2. Choose “External” user type and click “Create.”
   3. Enter the required details such as the application name, user support email, and developer contact information.
   4. Optionally, add additional details like the application logo and privacy policy URL.
   5. Click “Save and continue.” Detailed steps are available [here](https://developers.google.com/workspace/guides/create-credentials#configure_the_oauth_consent_screen).

   #### Step 4: Register Your Application

   1. In the left sidebar, navigate to “APIs & Services” > “Credentials.”![](/files/tP2z3nC5Gd641qWhDs8K)
   2. 2.Click on “Create Credentials” and select “OAuth client ID.”![](/files/lD4InwMbasTTrD6Vz3zr)
   3. Choose the application type (e.g., Web application, Desktop app, or Mobile app).
   4. Enter the necessary details such as the name of your application and the authorized redirect URIs. For OIDC, the redirect URIs should follow the format [https://your-app-domain.com](https://your-app-domain.com/auth/google/callback).
   5. Click “Create.”

   #### Step 5: Obtain Client ID and Client Secret

   1. After creating the OAuth client ID, Google will provide you with a client ID and client secret. These credentials are essential for authenticating your application.
   2. Note down the client ID and client secret securely. Do not expose them publicly.

   #### Step 6: Configure OIDC Integration in Your Application

   1. Integrate OIDC authentication into your application using a suitable OIDC library or framework (e.g., Passport.js for Node.js, Spring Security for Java, or Auth0 for various platforms).
   2. Use the client ID and client secret obtained from Google to configure OIDC authentication in your application settings.
   3. Set up the appropriate callback URL ([https://your-app-domain.com](https://your-app-domain.com/auth/google/callback)) for handling authentication responses from Google.
2. ### Example Implementaion

   Once you have obtained the **Client ID** and added the appropriate callback URL, you can use the Google **CLIENT\_ID** in your WidgetConfig

note

```
import { KanaWidget, AptosDexsFilter, BridgeOption, Chain, WidgetConfig } from "@kanalabs/kana-widget-v2";

const widgetConfig: WidgetConfig= {
  // Required: The unique SDK key provided by the development team. This key is essential for the widget to function properly.
  // If you haven't received a key yet, please contact the development team to obtain one.
  sdkKey: "Your dApp/company SDK key",
  
  //Optional: The name of your dApp or company using this widget.
  integrator:"Your dApp/company name",
  
  // Optional: Configure custom blockchain network providers if you wish to use your own instead of default settings.
  Provider: {
    aptosProvider: `https://aptos-mainnet.nodereal.io/v1/${NODEREAL_KEY}/v1`,
    solanaProvider: `https://greatest-frequent-owl.solana-mainnet.quiknode.pro/${SOLANA_QUICKNODE_KEY}`,
    polygonProvider: `https://polygon-mainnet.nodereal.io/v1/${NODEREAL_KEY}`,
    binanceProvider: `https://bsc-mainnet.nodereal.io/v1/${NODEREAL_KEY}`,
    ethereumProvider: `https://eth-mainnet.nodereal.io/v1/${NODEREAL_KEY}`,
    arbitrumProvider: `https://open-platform.nodereal.io/${NODEREAL_KEY}/arbitrum-nitro/`,
    avalancheProvider: `https://open-platform.nodereal.io/${NODEREAL_KEY}/avalanche-c/ext/bc/C/rpc`,
    zkSyncProvider: `https://open-platform.nodereal.io/${NODEREAL_KEY}/zksync`,
    suiProvider: "https://sui-mainnet-rpc.nodereal.io", 
  },
  
  // paymaster api key to enable paymaster 
  paymasterApikey: "Your Paymaster API key",
  
  // google client_id to enable Aptos Keyless 
  googleClientId: "your Google client_id',
  
  integratorFee:{
    // Fee range is 0.01% to 5%
    // Input should be between 1 to 500
    Fee: 1, 
    Address:"Your Integrator Address"
  }
};

export const WidgetPage = () => {
  return <KanaWidget config={widgetConfig} />;
};
```


# Web3 Aggregator SDK

Liquidity & Cross Chain Aggregator Layer SDK

The world of cryptocurrency and blockchain development is undeniably exciting, but it's also highly intensive, time-consuming, and often daunting for developers. Understanding the intricacies of different blockchain architectures, infrastructures, and coding languages can be a substantial barrier. Furthermore, the fragmentation of blockchain ecosystems, both public and private, has hindered the realization of a truly decentralized ecosystem and discouraged users and developers from fully embracing Web3. Kana Labs recognizes these challenges and presents a game-changing solution - Web3 Aggregator.

## What is Web3 Aggregator SDK?

Web3 aggregator SDK, also known as Kana Crosschain SDK, is Kana Labs' innovative Software Development Toolkit (SDK). It empowers crypto dApps to seamlessly transition from single-chain to multi-chain ecosystems. The SDK addresses the complexities and fragmentation inherent in blockchain development, making it accessible to developers and business entities, whether experienced or new to the crypto space.

## How does it work?

At its core, our SDK combines three key practices used by DeFi and DEX dapps in today’s market to provide a better transaction experience -

**Proprietary and Third-Party Liquidity Aggregator Engines**: To ensure ample liquidity for transactions.&#x20;

**Proprietary Cross-Chain Asset Bridges and Third-Party Messaging Protocols**: Facilitating cross-chain communication.&#x20;

**Smart Routing Algorithm**: Optimizing transaction pricing and processing.

By amalgamating these elements into a single SDK, Kana Labs simplifies the integration of multiple blockchain networks, each with its core infrastructure, architecture, and coding language. The supported blockchains form the foundation of the SDK, while crypto dApps' front-end interfaces sit atop this versatile framework.

### Seamless Multichain Deployment

The SDK has been meticulously crafted to break down barriers for both newcomers and experienced developers. The crypto and blockchain industry faces the challenge of onboarding the next billion users to Web3, and our SDK plays a pivotal role in achieving this goal.

Today's blockchain market is diverse, with various blockchains designed for specific purposes, each employing different coding languages like Rust, Solidity, and Move. Learning and working with these languages demands substantial time and resources. Even then, the resulting dApps are confined to their respective environments, perpetuating market fragmentation.

Kana Labs addresses this by enabling both established businesses and new developers to instantly deploy crypto dApps across multiple chains with true cross-chain capabilities. Minimal modifications to the front end are required, eliminating the need to master various coding languages or understand diverse blockchain infrastructures.

Developers can utilize their existing front-end coding languages to create applications on top of our SDK, providing immediate access to multiple blockchain networks, a wide range of similar dApps within our ecosystem, and a larger customer base, thus resolving liquidity issues in the fragmented DeFi market.

### Paving the Way for Real-Time Crypto Payments and true Mass Adoption

A major concern for new developers and businesses is the potential lack of mass adoption for their chosen blockchain given their need to do a deep study of the Web3 market space and tech. This necessitates the users and business entities to spend countless valuable resources ranging from money and time to human resources and man-hours dedicated to learning and understanding the market and choosing the right chain that fits their needs.

But even then there is fear of whether the selected blockchain network will gain true market share and mass adoption in today’s already huge and cluttered market or the decision to go with a popular blockchain which may not necessarily meet all their requirements both of which could result in a potential loss for the business entity/investor.

Our Aggregator SDK addresses these risks and concerns by enabling businesses to seamlessly integrate Web3 and crypto transaction/payment capabilities into their platforms or dApps. With minimal modifications to the application’s front end, businesses can instantly support cross-chain transactions. Users can transact using any tokens they hold, while our aggregator automatically converts them to the preferred tokens specified by the business and credits them to the designated wallet. This streamlined process also works in reverse, ensuring effortless and secure transactions.

This means that end users do not have to possess a popular cryptocurrency and can use any tokens in their possession to make transactions paving the way for true mass adoption of crypto payments and transactions. This will be easily reflected particularly on the payments side as any business be it large-scale sales chains or small brick-and-mortar firms, e-commerce websites etc., can now use our SDK to instantly gain multi-chain crypto payment capabilities.

Furthermore, existing dApps in the crypto space can quickly unlock multi-chain functionality by integrating our SDK with minimal adjustments to their front-end code. This integration also empowers DeFi platforms to design and develop tailored services and product offerings, enhancing their capabilities and expanding their reach.

### Kana Labs Liquidity Aggregation Solutions

Our Liquidity Aggregation Solutions combine both proprietary and third-party liquidity aggregation services. While liquidity aggregators pool resources from various dApps and liquidity pools, limitations often arise concerning the number of supported blockchain networks or the availability of tokens in their liquidity pool.

To ensure our users consistently enjoy ample liquidity and competitive pricing, we've integrated liquidity feeds from multiple sources, including our proprietary liquidity aggregator engine and partnered third-party liquidity aggregation protocols like 1inch and Jupiter aggregator. This approach empowers users to access various routes, each offering the best pricing for their transactions.

### Kana Labs Cross-Chain Aggregation Solutions

Kana Labs stands out as a true cross-chain solutions provider. While other cross-chain solutions typically offer asset bridges or messaging protocols, these solutions often cater to specific types of blockchains, such as EVM chains, or chains created using a common coding language. This has led to a fragmented ecosystem, despite efforts to address interoperability concerns.

In contrast, Kana Labs has developed asset bridges that facilitate communication between blockchains with varying backgrounds, including EVMs and non-EVMs, distinct core architectures, and coding languages. These bridges are complemented by third-party messaging protocols like Layer Zero, Wormhole, Axelar, Celer Network, and proprietary bridges from blockchain networks themselves, creating an all-encompassing omni-chain cross-chain experience.

### Smart Routing for Efficiency

While most DEX and dApps may allow users to choose the desired liquidity source in their routing algorithm, we further introduce cross-chain bridge aggregation capabilities. It means that we support multiple cross-chain bridges as some chains have a better affinity with a certain bridge while others have an affinity with another bridge.

We at Kana Labs support multiple cross-chain bridges, each of which has been tested against all supported blockchain networks. Our proprietary Smart Routing algorithm not only chooses the best rates for executing each transaction from the available liquidity sources but also chooses the right cross-chain bridge for each transaction, thereby optimizing each transaction & ensuring our clients enjoy competitive pricing and expedited transaction processing for every single transaction.

This becomes especially crucial for cross-chain transactions, where transaction times can vary significantly. Our algorithm selects the most efficient bridge, reducing transaction times from potentially 40 to 90 minutes to mere minutes.

#### Here is a list of Cross-Chain Bridges currently supported by our Aggregator SDK:

Wormhole Bridge &#x20;

Layer Zero&#x20;

Circle &#x20;

#### Transaction times for various cross-chain routes using Wormhole bridge:

Aptos-Solana: 2 to 4 minutes&#x20;

Aptos-Polygon: 2 to 4 minutes&#x20;

Polygon-Aptos: 40 to 90 minutes&#x20;

Solana-Polygon: 2 to 4 minutes&#x20;

Polygon-Solana: 40 to 90 minutes&#x20;

Solana-Aptos: 2 to 4 minutes

## The Futuristic Tool -

Kana Labs Web3 aggregator represents a monumental leap in simplifying and democratizing the Web3 space. With our Web3 aggregator SDK, we aim to make blockchain technology accessible to all. Barriers are dismantled, and the true potential of decentralized ecosystems is within reach. Join us on this transformative journey into the world of Web3 with Kana Labs.


# Installation

## Installation

### Using NPM: [click to redirect](https://www.npmjs.com/package/@kanalabs/aggregator)

```shell
 npm i @kanalabs/aggregator
```

### Using Yarn: [click to redirect](https://yarnpkg.com/package?q=kanalabs\&name=%40kanalabs%2Faggregator)

```shell
 yarn add @kanalabs/aggregator
```

## TypeDoc:

[kanalabs aggregator SDK type doc - click to redirect](https://kanalabs.github.io/kanalabs-aggregator-sdk-v2/)

## Supported Chains

1. Aptos
2. Arbitrum
3. Avalanche
4. BSC (Binance Smart Chain)
5. Ethereum
6. Polygon
7. Solana
8. Sui
9. zkSync Era
10. Base

## Supported Bridges

1. CCTP
2. CCTP V2


# SameChain

#### If reading docs isn't your thing, just check out our example code for integration

> We are currently updating the repository with more examples, so please hold on.

{% embed url="<https://github.com/kanalabs/aggregator-example>" %}

###

### Same Chain Swap

{% hint style="info" %}
If you wish to execute the transaction using your own logic that fits your use case, please refer to our [`aggregator-example`](https://github.com/kanalabs/aggregator-example) repository on Github
{% endhint %}

### **1. SwapQuotes function**

```typescript
 swapQuotes = async (params: SameChainSwapParams)
```

| **SameChainSwapParams** | **Description**                               |
| ----------------------- | --------------------------------------------- |
| inputToken              | The input token for the swap operation.       |
| outputToken             | The output token to receive after the swap.   |
| amountIn                | The amount of input tokens to be swapped.     |
| slippage                | The allowed slippage percentage for the swap. |
| network                 | The network ID for the swap operation.        |
| options                 | (Optional) Additional options for the swap.   |

### **2. ExecuteSwapInstruction**

```typescript
executeSwapInstruction = async (params: SameChainInstructionParams)
```

| **executeSwapInstruction** | **Description**                                                  |
| -------------------------- | ---------------------------------------------------------------- |
| quote                      | A `CommonRouteInterface` representing the quote response format. |
| address                    | The address related to the instruction.                          |
| options                    | (Optional) An object containing additional options.              |
| options.provider           | (Optional) The connection provider to use.                       |
| options.integrator         | (Optional) A string identifying the integrator.                  |
| options.recipient          | (Optional) Address of the recipient.                             |

#### 1 . APTOS :

**1.1 .Initialising The SDK**

```typescript
import { Account, AccountAddress, Aptos, AptosConfig, Ed25519PrivateKey, Network } from "@aptos-labs/ts-sdk";
import { SwapAggregator, Environment, NetworkId } from '@kanalabs/aggregator';

const aptosConfig = new AptosConfig({ network: Network.MAINNET });
const aptosProvider = new Aptos(aptosConfig)

const aptosSigner = Account.fromPrivateKey({
  privateKey: new Ed25519PrivateKey(process.env.APTOS_PRIVATEKEY || ''),
  address:  AccountAddress.from(process.env.APTOS_ADDRESS || ''),
  legacy: true,
});

const swap = new SwapAggregator(Environment.production, {
  providers: {
    aptos: aptosProvider,
  },
  signers: {
    aptos: aptosSigner,
  },
});
```

> NOTE : SIGNER CAN BE A APTOS ACCOUNT INSTANCE DERIVED FROM PRIVATE KEY OR A SIGN AND SUBMIT FUNCTION FROM APTOS WALLET ADAPTER

**1.2 .Getting Swap Quotes**

```typescript
const quote = await swap.swapQuotes({
  apiKey: APIKEY,
  inputToken: '0x1::aptos_coin::AptosCoin',
  outputToken: '0x6f986d146e4a90b828d8c12c14b6f4e003fdff11a8eecceceb63744363eaac01::mod_coin::MOD',
  amountIn: '100000',
  slippage: 0.5,
  network: NetworkId.aptos,
  options:{
      integratorAddress :'0x000...........', // if ur an integrator and want to collect fee then u can pass ur address here
      is_fee_coin_in: true , // u can pass this one as true if u want collect fee from input Token , but by Default it will be false (Output Token)
      isFeeReferrer:true, // this one should be true , if integrator wants to collect fee 
    }
});

const optimalQuote = quote.data[0];
```

{% hint style="info" %}
Please note that the feature of switching fee from output token to input token is only available in aptos chain only
{% endhint %}

**1.3 .Executing Swap Quotes**

```typescript
const executeSwap = await swap.executeSwapInstruction({
  apiKey: APIKEY,
  quote: optimalQuote,
  address: swap.signer?.aptos?.accountAddress.toString(),
});
```

#### 2 . SUI :

**2.1 .Initialising The SDK**\`\`\`typescript

```typescript
import { Ed25519Keypair, JsonRpcProvider, RawSigner, Connection as SuiConnection } from '@mysten/sui.js';
import { SwapAggregator, Environment, NetworkId } from '@kanalabs/aggregator';

const suiProvider = new JsonRpcProvider(new SuiConnection({ fullnode: 'SUI RPC NODE ' }));

const suiSigner = new RawSigner(Ed25519Keypair.deriveKeypair(process.env.SUIMNEMONICS || ''), suiProvider);

const swap = new SwapAggregator(Environment.production, {
  providers: {
    sui: suiProvider,
  },
  signers: {
    sui: suiSigner,
  },
});
```

**2.2 .Getting Swap Quotes**

```typescript
const quote = await swap.swapQuotes({
  apiKey: APIKEY,
  inputToken: '0x2::sui::SUI',
  outputToken: '0xf0fe2210b4f0c4e3aff7ed147f14980cf14f1114c6ad8fd531ab748ccf33373b::bswt::BSWT',
  amountIn: '10000',
  slippage: 1,
  network: NetworkId.sui,
});
const optimalQuote = quote.data[0];
```

**2.3 .Executing Swap Quotes**

```typescript
const executeSwap = await swap.executeSwapInstruction({
  apiKey: APIKEY,
  quote: optimalQuote,
  address: await swap.signer?.sui?.getAddress(),
});
```

#### 3 . SOLANA :

**3.1 .Initialising The SDK**\`\`\`typescript

```typescript
import { Connection, Keypair, clusterApiUrl } from '@solana/web3.js';
import { SwapAggregator, Environment, NetworkId } from '@kanalabs/aggregator';

const solanaProvider = new Connection(clusterApiUrl('mainnet-beta'));
const solanaSigner = Keypair.fromSecretKey(bs58.decode(process.env.SOLANAPAYER || ''));

const swap = new SwapAggregator(Environment.production, {
  providers: {
    solana: solanaProvider,
  },
  signers: {
    solana: solanaSigner,
  },
});
```

**3.2 .Getting Swap Quotes**

```typescript
const quote = await swap.swapQuotes({
  apiKey: APIKEY,
  inputToken: 'So11111111111111111111111111111111111111112',
  outputToken: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  amountIn: '1000',
  slippage: 1,
  network: NetworkId.solana,
});
const optimalQuote = quote.data[0];
```

**3.3 .Executing Swap Quotes**

```typescript
const executeSwap = await swap.executeSwapInstruction({
  apiKey: APIKEY,
  quote: optimalQuote,
  address: swap.signer?.solana?.publicKey.toString(),
});
```

#### 4 . EVM CHAINS :

**4.1 .Initialising The SDK**

```typescript
import { ethers, utils } from 'ethers';
import { SwapAggregator, Environment, NetworkId } from '@kanalabs/aggregator';

const polygonRpc = process.env.ETH_NODE_URI_POLYGON as string;
const polygonProvider = ethers.getDefaultProvider(polygonRpc);
const polygonSigner = new ethers.Wallet(privateKey, polygonProvider);

const swap = new SwapAggregator(Environment.production, {
  providers: {
    polygon: polygonProvider,
  },
  signers: {
    polygon: polygonSigner,
  },
});
```

**4.2 .Getting Swap Quotes**

```typescript
const quote = await swap.swapQuotes({
  apiKey: APIKEY,
  inputToken: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
  outputToken: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',
  amountIn: utils.parseEther('0.05').toString(),
  slippage: 1,
  network: NetworkId.polygon,
});
const optimalQuote = quote.data[0];
```

**4.3 .Executing Swap Quotes**

```typescript
const executeSwap = await swap.executeSwapInstruction({
  apiKey: APIKEY,
  quote: optimalQuote,
  address: await swap.signer?.polygon?.getAddress(),
});
```


# Cross Chain Swap

## **1. CrossChainQuote**

```typescript
crossChainQuote = async (params: CrossChainSwapParams)
```

| **CrossChainSwapParams** | **Description**                                      |
| ------------------------ | ---------------------------------------------------- |
| sourceToken              | The source token to be swapped.                      |
| targetToken              | The target token to receive after the swap.          |
| sourceChain              | The source network ID or chain for the swap.         |
| targetChain              | The target network ID or chain for the swap.         |
| amountIn                 | The amount of source tokens to be swapped.           |
| sourceSlippage           | The allowed slippage percentage on the source chain. |
| targetSlippage           | The allowed slippage percentage on the target chain. |
| options                  | (Optional) An object containing additional options.  |

## **2. Execute Cross Chain Transfer**

```typescript
executeTransfer = async (params: ExecuteCrossChainTransferParams)
```

| **CrossChainTransferParams** | **Description**                 |
| ---------------------------- | ------------------------------- |
| sourceProvider               | RPC Provider for source chain   |
| sourceSigner                 | Source chain signer             |
| quote                        | selected cross chain swap quote |
| sourceAddress                | source chain user address       |
| targetAddress                | Target chain user address       |
| targetSigner                 | target chain signer.            |
| targetProvider               | Rpc provider for target chain.  |

## **3. Execute Cross Chain Claim**

```typescript
executeClaim = async (params: ExecuteCrossChainClaimParams)
```

| **CrossChainSwapParams** | **Description**                                             |
| ------------------------ | ----------------------------------------------------------- |
| txHash                   | Transaction hash of the tranfer transaction in source chain |
| sourceProvider           | RPC Provider for source chain                               |
| targetProvider           | Rpc provider for target chain.                              |
| targetSigner             | target chain signer.                                        |
| quote                    | selected cross chain swap quote                             |
| sourceAddress            | source chain user address                                   |
| targetAddress            | Target chain user address                                   |

**A CrossChain swap consists of three steps**

> 1. Getting Swap Quotes: This step involves obtaining quotes for the selected chains and tokens.

> 2. Executing Transfer Instruction: In this phase, tokens are transferred across chains using a bridge to reach the selected destination chain.

> 3. Executing Claim Instruction: After the tokens have been successfully bridged to the destination chain, this step allows users to claim their tokens. It's worth noting that bridges utilizing a relayer may not require this specific claim step.

**What if the claim fails ?**

> In the event of a failure, users can redeem their tokens that were transferred via the bridge. Kanalabs exclusively transfers native stable coins / wrapped stable coins via the bridge. Therefore, users have the option to redeem their tokens and manually initiate the swap on the destination chain."

## 1 . POLYGON TO BSC

### 1.1 . Initialising SDK

```typescript
const polygonRpc = process.env.ETH_NODE_URI_POLYGON as string;
const polygonProvider = ethers.getDefaultProvider(polygonRpc);
const polygonSigner = new ethers.Wallet(privateKey, polygonProvider);

const bscRpc = process.env.ETH_NODE_URI_BSC as string;
const bscProvider = ethers.getDefaultProvider(bscRpc);
const bscSigner = new ethers.Wallet(privateKey, bscProvider);

const crossChainAggregator = new SwapAggregator(Environment.production);
```

### 1.2 . Getting Cross Chain Swap Quote

```typescript
const quotes = await crossChainAggregator.crossChainQuote({
  apiKey: APIKEY,
  sourceToken: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
  targetToken: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
  sourceChain: NetworkId.polygon,
  targetChain: NetworkId.bsc,
  amountIn: utils.parseUnits('0.01', 18).toString(),
  sourceSlippage: 0.1,
  targetSlippage: 0.1,
});

const optimalQuote = quotes.data[0];
```

### 1.3 . Executing Transfer Instruction

```typescript
const transfer = await crossChainAggregator.executeTransfer({
  apiKey: APIKEY,
  quote: optimalQuote,
  sourceAddress: polygonSigner.getAddress() as string,
  targetAddress: bscSigner.getAddress() as string,
  sourceProvider: polygonProvider as providers.BaseProvider,
  sourceSigner: polygonSigner as EvmSignerType,
});
```

> For Bridges using relayers there is no need to execute claim Instruction

### 1.4 . Execute Claim Instruction

```typescript
const claim = await crossChainAggregator.executeClaim({
  apiKey: APIKEY,
  txHash: transfer.txHash,
  sourceProvider: polygonProvider as providers.BaseProvider,
  targetProvider: bscProvider as providers.BaseProvider,
  targetSigner: bscSigner as EvmSignerType,
  quote: optimalQuote,
  sourceAddress: polygonSigner.getAddress() as string,
  targetAddress: bscSigner.getAddress() as string,
});
```

### 1.5 . Redeeming tokens in case of failure

```typescript
const redeem = await crossChainAggregator.redeem({
  apiKey: APIKEY,
  sourceChain: NetworkId.polygon,
  targetChain: NetworkId.bsc,
  sourceProvider: polygonProvider as providers.BaseProvider,
  targetProvider: bscProvider as providers.BaseProvider,
  targetSigner: bscSigner as EvmSignerType,
  SourceHash: transfer.txHash,
  targetAddress: bscSigner.getAddress() as string,
  BridgeId: BridgeId.wormhole,
});
```

## 2 . APTOS TO SUI

### 2.1 . Initialising SDK

```typescript
const suiProvider = new JsonRpcProvider(new SuiConnection({ fullnode: 'SUI RPC 
const aptosConfig = new AptosConfig({ network: Network.MAINNET });
const aptosProvider = new Aptos(aptosConfig)

const suiSigner = new RawSigner(Ed25519Keypair.deriveKeypair(process.env.SUIMNEMONICS || ''), suiProvider);
const aptosSigner = Account.fromPrivateKey({
  privateKey: new Ed25519PrivateKey(process.env.APTOS_PRIVATEKEY || ''),
  address:  AccountAddress.from(process.env.APTOS_ADDRESS || ''),
  legacy: true,
});

const crossChainAggregator = new SwapAggregator(Environment.production);
```

### 2.2 . Getting Cross Chain Swap Quote

```typescript
const crossChainQuotes = await crossChainAggregator.crossChainQuote({
  apiKey: APIKEY,
  sourceToken,
  targetToken,
  sourceChain: NetworkId.aptos,
  targetChain: NetworkId.sui,
  amountIn: '100000',
  sourceSlippage: 0.1,
  targetSlippage: 0.1,
});
const optimalRoute = crossChainQuotes.data[0];
```

### 2.3 . Executing Transfer Instruction

```typescript
const transfer = await crossChainAggregator.executeTransfer({
  apiKey: APIKEY,
  sourceProvider: aptosProvider,
  sourceAddress: aptosSigner.accountAddress.toString(),
  sourceSigner: aptosSigner,
  quote: optimalRoute,
  targetAddress: await suiSigner.getAddress(),
});
```

> For Bridges using relayers there is no need to execute claim Instruction

### 2.4 . Execute Claim Instruction

```typescript
const claim = await crossChainAggregator.executeClaim({
  apiKey: APIKEY,
  txHash: transfer.txHash,
  sourceProvider: aptosProvider,
  targetProvider: suiProvider,
  targetSigner: suiSigner,
  quote: optimalRoute,
  sourceAddress: aptosSigner.accountAddress.toString(),
  targetAddress: await suiSigner.getAddress(),
});
```

### 2.5 . Redeeming tokens in case of failure

```typescript
const redeem = await crossChainAggregator.redeem({
  apiKey: APIKEY,
  sourceChain: NetworkId.aptos,
  targetChain: NetworkId.sui,
  sourceProvider: aptosProvider,
  targetProvider: suiProvider,
  targetSigner: suiSigner,
  SourceHash: transfer.txHash,
  targetAddress: await suiSigner.getAddress(),
  BridgeId: BridgeId.wormhole,
});
```

## 3 . SOLANA TO APTOS

### 3.1 . Initialising SDK

<pre class="language-typescript"><code class="lang-typescript"><strong>const solanaProvider = new Connection('SOLANA RPC NODE);
</strong>const solanaSigner = Keypair.fromSecretKey(bs58.decode(process.env.SOLANAPAYER || ''));
const aptosConfig = new AptosConfig({ network: Network.MAINNET });
const aptosProvider = new Aptos(aptosConfig)

const aptosSigner = Account.fromPrivateKey({
  privateKey: new Ed25519PrivateKey(process.env.APTOS_PRIVATEKEY || ''),
  address:  AccountAddress.from(process.env.APTOS_ADDRESS || ''),
  legacy: true,
});

const crossChainAggregator = new SwapAggregator(Environment.production);
</code></pre>

### 3.2 . Getting Cross Chain Swap Quote

```typescript
const crossChainQuotes = await crossChainAggregator.crossChainQuote({
  apiKey: APIKEY,
  'So11111111111111111111111111111111111111112',
  '0x1::aptos_coin::AptosCoin',
  sourceChain: NetworkId.solana,
  targetChain: NetworkId.aptos,
  amountIn: '100000',
  sourceSlippage: 0.5,
  targetSlippage: 0.1,
});
const optimalRoute = crossChainQuotes.data[0];
```

### 3.3 . Executing Transfer Instruction

```typescript
const transfer = await crossChainAggregator.executeTransfer({
  apiKey: APIKEY,
  sourceProvider: solanaProvider,
  sourceAddress: solanaSigner.publicKey.toString(),
  sourceSigner: solanaSigner,
  quote: optimalRoute,
  targetAddress: aptosSigner.accountAddress.toString(),
});
```

> For Bridges using relayers there is no need to execute claim Instruction

### 3.4 . Execute Claim Instruction

```typescript
const claim = await crossChainAggregator.executeClaim({
  apiKey: APIKEY,
  txHash: transfer.txHash,
  sourceProvider: solanaProvider,
  targetProvider: aptosProvider,
  targetSigner: aptosSigner,
  quote: optimalRoute,
  sourceAddress: solanaSigner.publicKey.toString(),
  targetAddress: aptosSigner.accountAddress.toString(),
});
```

### 3.5 . Redeeming tokens in case of failure

```typescript
const redeem = await crossChainAggregator.redeem({
  apiKey: APIKEY,
  sourceChain: NetworkId.solana,
  targetChain: NetworkId.aptos,
  sourceProvider: solanaProvider,
  targetProvider: aptosProvider,
  targetSigner: aptosSigner,
  SourceHash: transfer.txHash,
  targetAddress: aptosSigner.accountAddress.toString(),
  BridgeId: BridgeId.wormhole,
});
```


# Aggregator API's

You can optionally use our API's to integrate Kanalabs with your application

SWAGGER LINK - <https://ag.kanalabs.io/swagger>

## TOKEN LIST API

you can use our token list api which also have current market price&#x20;

LINK - [https://ag.kanalabs.io/tokens](https://ag.kanalabs.io/tokens?chain=2)

Example code :<br>

```typescript
 const response = await axios.get('https://ag.kanalabs.io/tokens', {
    params: {
      chain: KanaChainID.aptos,
    },
    headers: {
      'Content-Type': 'application/json',
      'X-API-KEY': '//* YOUR API KEY *//',
    },
  });
```

NOTE: KanaChainID.aptos is enum of chains that maintained by kanalabs&#x20;

```typescript
enum KanaChainID {
  'solana' = 1,
  'aptos' = 2,
  'polygon' = 3,
  'bsc' = 4,
  'sui' = 5,
  'ethereum' = 6,
  'base' = 7,
  'zkSync' = 9,
  'Avalanche' = 10,
  'Arbitrum' = 11,
}
```

#### you can also pass an array of tokens if u want to get token details specifical

```typescript
const tokens  = ['0x1::aptos_coin::AptosCoin']  // u can add more tokens 
  
const response = await axios.get('https://ag.kanalabs.io/tokens', {
    params: {
      chain: KanaChainID.aptos,
      tokens: JSON.stringify(tokens), // pls note here , u need to stringify the array
    },
    headers: {
      'Content-Type': 'application/json',
      'X-API-KEY': '//* YOUR API KEY *//',
    },
  });
```

#### &#x20;


# Kana Trade

Kana Trade - CLOB-based spot trading platform for the ultimate CEX-like decentralized trading experience

Kana Trade combines blockchain technology with the speed and simplicity of traditional trading platforms. As a fully on-chain decentralized order book, it offers performance, transparency, and complete asset control for traders.

#### **Key Features**

1. User-Friendly Interface\
   Experience CEX-like trading with a familiar and intuitive platform that makes advanced trading accessible for all.
2. Full Asset Ownership\
   Retain full control of your assets with a non-custodial platform. Every trade is recorded on-chain, ensuring transparency and security.
3. Advanced Trading Tools\
   Execute market and limit orders with precision, supported by real-time liquidity and volume data.
4. Real-Time Charting and Insights\
   Analyze trading activity with tools powered by TradingView to strategize effectively.
5. High-Performance Infrastructure\
   Leverage Econia’s atomic order-matching engine and the Aptos blockchain for low-latency, high-speed transaction processing.
6. Gas-Free Market Orders\
   Save on costs with gas-free trading for market orders, sponsored by Kana Trade’s infrastructure.
7. Minimal Fees\
   Trade with platform fees as low as 0.05%, significantly lower than centralized exchanges.
8. Keyless Wallets\
   Create wallets with Google or Apple IDs through the Aptos keyless wallet, eliminating the need for seed phrases.

#### **Why Choose Kana Trade?**

Kana Trade delivers the speed and simplicity of traditional platforms while ensuring security and full asset control. It’s an ideal choice for traders seeking performance and transparency.

#### **Get Started**

Check out the link below to explore our decentralized spot trading platform today and experience secure, high-performance trading powered by blockchain technology.&#x20;

{% embed url="<https://tradebook.kanalabs.io/?market=APT-USDC>" %}


# API Docs

Link to Github Repo & Swagger for Kana Trade APIs

Here's an example implementation of trade book API using javascript/typescript

{% embed url="<https://github.com/kanalabs/trade-implementation>" %}

***

{% hint style="info" %}
Please note that an API Key is required to integrate your bots/trading tools with our API. To get the API key from us, reach out via email at <hello@kanalabs.io>&#x20;
{% endhint %}

For Swagger API Documentation, Please visit ->

{% embed url="<https://tradeapi.kanalabs.io/swagger/static/index.html#/>" %}

***


# Kana Perps

The 1st fully on-chain CLOB based decentralised perpetual futures on Aptos

## Introduction&#x20;

Kana Perps is a fully on-chain decentralised perpetual futures platform built on the Aptos network. We offer a secure, non-custodial trading experience where all trades and settlements are executed via smart contracts, eliminating counterparty risk.

Our platform is designed for seamless trading with a user-friendly UI/UX that feels just like Web2 platforms. With sponsored transactions and keyless wallet integration using Google or Apple IDs, you can trade effortlessly without worrying about seed phrases.

Enjoy advanced features like hedge mode for dual positioning, gas-free market orders, and minimal fees (0.05%). We provide deep liquidity sourced from top-tier market makers, ensuring smooth trade execution with low slippage through our CLOB mechanism and limit order capabilities.

<br>


# Getting Started

What do you need to trade on Kana Perps?

To trade on Kana Perps, you need:

* USDT tokens on Aptos - These tokens serve as both collateral and investment for your trades.
* APT tokens – While we offer gasless transactions on market orders, users still need APT tokens to place limit order trades.
* Once you have these tokens, you can choose between
* An EOA wallet (Normal DeFi Wallets) such as Pontem, Petra, or Martian Wallet.
* The Aptos keyless wallet features social login and one-click transaction signing features.

With your wallet set up and funded, you can connect to the Kana Perps and start trading.

{% embed url="<https://app.gitbook.com/o/LtMhWh0UxBSaETOW2n6T/s/maXag665v6LhjJH7XMxS/~/changes/106/products-and-features/kana-labs-defi-simplified/kana-perps/getting-started/mint-tokens-on-testnet>" %}


# Deposit & Withdrawal

Here's a step-by-step breakdown of how to deposit and withdraw funds to your Kana Perps trading account. Steps apply to both Testnet & Mainnet.

## For Wallets like Petra, Nightly & Martian Wallets, here's the flow&#x20;

### **To Deposit -**&#x20;

**Step 1 -** Click “Connect Wallet” and select your wallet (Please ensure your wallet is in Testnet mode).&#x20;

**Step 2** - Click “Faucet/Deposit” and select “Mint Now” to receive your testnet USDT tokens.&#x20;

**Step 3** - In the same window, under the “Amount to be deposited to trading account” box, please enter the number of tokens you want to transfer to the Kana Perps platform and click on the “Deposit to Trading Account” button

**Step 4** - You are now all set to start trading.

### **To Withdraw -**&#x20;

**Step 1** - Click “Faucet/Deposit”, and in the pop-up box that appears please select the “Withdraw” option in the header section.&#x20;

**Step 2 -** Please enter the number of tokens you wish to withdraw to your wallet and click the “Withdraw from Trading Account” button.&#x20;

***

## For Aptos Keyless Wallets (Google Wallet), here's the flow&#x20;

### To Deposit -&#x20;

**Step 1**—Click “Connect Wallet” and select “Google/Apple” to log in using your Gmail or Apple iCloud ID.&#x20;

**Step 2**—Click “Faucet/Deposit” and select “Mint Now” to receive your testnet USDT tokens.&#x20;

**Step 3**—In the same window, in the “Amount to be deposited to trading account” box, please enter the number of tokens you want to transfer to the trading platform and click on the “Deposit to Trading Account” button.

**Step 4** - You are now all set to start trading.

### **To Withdraw -**&#x20;

**Step 1**—Click on “Faucet/Deposit,” and in the pop-up box that appears, select the “Withdraw” option in the header section.&#x20;

**Step 2**—Please enter the number of tokens you wish to withdraw to your wallet and click on the “Withdraw from Trading Account” button.&#x20;

{% hint style="info" %}
Please note that there is an individual user withdrawal cap of $ 5,000 per 24 hours and an overall platform level cap at 10% TVL. Once the withdrawal limit is reached, no user can withdraw funds until it is reset.  The TVL is updated using the rolling window method once every 1 hour.&#x20;
{% endhint %}

<br>


# Mainnet Tutorials


# Getting Started

Here’s what you need to start your trading journey with our Kana Perps platform.

To trade on Kana Perps, you need:

* USDT tokens on Aptos - These tokens serve as both collateral and investment for your trades.
* Crypto wallets such as Pontem and Petra Wallet.
* The Aptos keyless wallet features social login and one-click transaction signing features.

With your wallet set up and funded, you can connect to the Kana Perps and start trading.

<br>


# Connecting Wallet & Enabling “One Click Transaction”

Once you have prepared everything you need to start your trading journey, the first step is to “Connect Your Wallet” to the platform and enable “One Click Transaction.”

## Why Enable One-Click Trading?

Most DeFi platforms require users to authenticate each transaction manually, which is cumbersome and increases transaction times. Kana Perps introduces one-click trading for popular crypto wallets like Petra and Nightly, streamlining the user experience. This not only shortens the transaction time but also improves the overall user experience on the platform, making it very similar to traditional fiat currency trading platforms.&#x20;

However, users who choose to connect using the “Google Wallet” feature will have one-click trading enabled by default.&#x20;

## Step-by-Step Guide

1. **Connect Wallet**

* Click "Connect Wallet" in the main UI or select the “Sign In” button on the top right corner of the perps platform header.

<figure><img src="/files/GBBMSF1lQcUbUVgDUmpe" alt=""><figcaption></figcaption></figure>

* Choose your wallet in the pop-up menu (e.g., Petra Wallet)

<figure><img src="/files/rs3JjNRXMftbqRRaKrbH" alt=""><figcaption></figcaption></figure>

* Ensure your wallet is set to Testnet mode.

<figure><img src="/files/gWvznk4HBldLduCmFzLx" alt=""><figcaption></figcaption></figure>

2. **Enable Trading**

* Click "Enable Trading" → Click "Sign Trading" → Approve the authentication pop-up from your wallet.

<figure><img src="/files/fYKbCOaKIPwYmtF8O7w4" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/p6oHyiIuROBSk5YCP7Qh" alt=""><figcaption></figcaption></figure>

* This enables one-click transactions on Kana Perps, making the trading experience seamless. Now your platform is fully set-up and once you deposit funds to your account you are all set to start your trading journey.

<figure><img src="/files/DbHyE1SrgALA0dlhgy72" alt=""><figcaption></figcaption></figure>

<br>


# Deposit & Withdraw Tokens

## To Deposit -

**Step 1** - Connect your wallet to the Perps trading platform, and click the “Deposit” button in the header bar.

<figure><img src="/files/KyXib3aOe3mp2xnsBXSp" alt=""><figcaption></figcaption></figure>

**Step 2** - In the same window, under the “Amount to be deposited to trading account” box, please enter the number of tokens you want to transfer to the Kana Perps platform and click on the “Deposit to Trading Account” button

<figure><img src="/files/hux10MeGIOR2k8xY8Xct" alt=""><figcaption></figcaption></figure>

**Step 3** - Once the deposit is transferred, you will receive a pop-up that says “Transaction Successful,” and your trading balance will be reflected in your profile info, which is right below the wallet address in the header section. You are now all set to start trading.

<figure><img src="/files/wIlTHmkI1KjdAZVF10LS" alt=""><figcaption></figcaption></figure>

**To Withdraw -**&#x20;

**Step 1** - Click on the “Withdraw” icon, and in the pop-up box that appears, please select the “Withdraw” option in the header section.

<figure><img src="/files/17hMKsKP81A42tEK5sgI" alt=""><figcaption></figcaption></figure>

**Step 2 -** Please enter the number of tokens you wish to withdraw to your wallet and click the “Withdraw from Trading Account” button.

<figure><img src="/files/rwAJVcrxBHd3Lcj3sGLI" alt=""><figcaption></figcaption></figure>


# Placing a Market Trade Order

Opening a short position on APT - PERP

On the Kana Perps platform, traders can place Market or Limit orders to open either Long or Short positions on supported assets. Order size can be specified in USDT or in units of the underlying asset, depending on user preference. Traders can go long if they anticipate that the price of an asset will rise, or go short if they expect the price to fall. To place an order in terms of asset value (APT/BTC/ETH), divide your order value by the current market price of the selected asset.&#x20;

For those new to Perpetual Futures trading, it’s crucial to understand how leverage influences the investment amount. Kana Perps offers leverage up to 20x. For example, with an order value of 100 USDT and 20x leverage, only 5 USDT is debited from the trading balance as margin. At 10x leverage, the margin is 10 USDT, and at 5x, it rises to 20 USDT. Higher leverage results in a lower margin requirement, while lower leverage increases it.&#x20;

It's important to note that if you place a trade order of 100 USDT with 20x leverage, you’re trading for that same value, not for 2000 USDT. To avoid liquidation, traders must maintain additional funds in their trading account to be used as margin when needed, approximately 2.5% of the position’s notional value, in their accounts, especially when multiple trades are open.

A Market Order is used when a trader wants to execute a trade immediately at the best available price in the orderbook. In this example, we’ll open a short position using a market order on the APT-PERP trading pair.

### Step-by-Step Guide -&#x20;

**Step 1** - In the Order Placement section, ensure the "Open" tab is selected. By default, the "Market" order type is active. Next, select your preferred leverage from the dropdown menu on the right of the order type selector. Kana Perps allows leverage from 1x (no leverage) up to 20x.

<figure><img src="/files/HFX4SRox0s43BQNdBD5r" alt=""><figcaption></figcaption></figure>

**Step 2** - Enter your order amount in the input box. You can toggle between USDT or APT as the base unit. Based on the toggle selection, the platform will display the notional value, along with the estimated liquidation price, initial margin required and slippage all of which are shown within the same order placement panel. The left-side toggle corresponds to a long position, and the right-side toggle corresponds to a short position. Click the "Short" button to open a Short position.

<figure><img src="/files/3wA7QKRZSQPgORXHXzHe" alt=""><figcaption></figcaption></figure>

**Step 3**— After confirming the order, a “Order Placed Successfully” pop-up will appear.

<figure><img src="/files/eHtHI9VHfX59VHS6cjzb" alt=""><figcaption></figcaption></figure>

**Step 4** - Because this is a market order, the trade is executed instantly and will be reflected under the “Positions” tab, where all active positions are tracked.

<figure><img src="/files/FCVTZkVkuom4LOgx7aB6" alt=""><figcaption></figcaption></figure>


# Placing a Limit Trade Order

Opening a Long Position on APT - PERP

A Limit Order is used when a trader wants to open a position at a specific price that differs from the current market price. On a CLOB (Central Limit Order Book) interface, the order book displays all outstanding buy (bid) and sell (ask) orders waiting to be matched. Typically, ask prices (sell orders) appear in red, while bid prices (buy orders) appear in green.

> **Key Takeaway**
>
> Limit orders below the current best ask price will sit in the Open Orders until matched, while the Limit orders at or above the best ask price execute immediately, behaving like market orders within price limits you define

### Step-by-Step Guide -

#### &#xD;Scenario 1: Placing a Limit Long Order Below Market Price&#xD;<br>

**Step 1** - Suppose the current market price of the APT-PERP pair is 6.001 USDT per APT. You wish to open a long position at a lower price, say 5.85 USDT, for an order size of 8 USDT.\
Select the "Limit" option under the "Open" tab in the order placement section. Enter your desired price and amount, then click "Open Long."

<figure><img src="/files/EM0W5eqLSZrWnIezjdbw" alt=""><figcaption></figcaption></figure>

**Step 2** - Upon submission, a confirmation message will appear: "Order Placed Successfully."

<figure><img src="/files/k6rsbAGZxNYwTp4hgoi2" alt=""><figcaption></figcaption></figure>

**Step 3** - Since the limit price is below the current best ask price and no existing sell orders match your bid, your order will be queued in the order book. You will find it listed in the "Open Orders" section. The order will remain there unless one of these 3 conditions are met - The market price reaches your limit price, A counterparty is willing to sell at your price, or You cancel the order manually.

<figure><img src="/files/F0ztD4jzkEHpzTaU4PeD" alt=""><figcaption></figcaption></figure>

#### Scenario 2: Placing a Limit Long Order That Executes Immediately

Sometimes, traders prefer that their order be filled immediately rather than waiting at a preferred price level. This is possible with a limit order if it is placed at a price equal to or higher than the best available ask on the order book.

**Step 1** - The APT-PERP chart shows the current market price as 6.036 USDT. After reviewing the order book's red section (ask prices) and identifying the lowest available sell price. A limit order is placed at 6.048 USDT for 8 USDT. Now click on "Open Long" to execute the limit order instantly.

<figure><img src="/files/ePIowLoTj8dxTqkHDoap" alt=""><figcaption></figcaption></figure>

**Step 2** - Once the order is placed successfully, a confirmation message will appear: "Order Placed Successfully."

<figure><img src="/files/k6rsbAGZxNYwTp4hgoi2" alt=""><figcaption></figcaption></figure>

**Step 3** - As the limit price is equal to or higher than the lowest ask, the system matches your order with one or more existing sell orders. The order is executed immediately, and the resulting position appears in the "Positions" tab instead of "Open Orders".

<figure><img src="/files/VvutmK8rTWWrjOqyV0OI" alt=""><figcaption></figcaption></figure>


# Partially & Fully Closing a Live Trade Order

Traders can fully or partially close an open position on the Kana Perps platform using either Market or Limit order types. Below is a step-by-step guide outlining the various methods to close a position. <br>

**Step 1**—To fully close a position instantly, navigate to the “Positions” tab. Locate the open position you wish to close and click on the “Quick Close” button located on the far right. This will immediately submit a market order to exit the entire position at the best available price.

<figure><img src="/files/uw44gZOe2tL5I9U5jb9p" alt=""><figcaption></figcaption></figure>

**Step 2**—To partially close a position at the current market price, select the desired position from the “Positions” tab. In the “Close” section, select the “Market” option, manually input the quantity you wish to close, and click “Confirm” to execute the trade.

<figure><img src="/files/9G60y3sXkfKQvlMKz81k" alt=""><figcaption></figcaption></figure>

**Step 3**— To partially close a position at a specific price level, select the open position in the “Positions” tab. Under the “Close” section, select the “Limit” option, enter your target price and the quantity to close, then click “Confirm”. The limit order will be submitted and remain open until it is matched and executed or canceled.

<figure><img src="/files/l5vLJz56L6kbXVLnlWjg" alt=""><figcaption></figcaption></figure>

**Step 4**— Upon successful closure of the position, a confirmation message will appear stating “Long Position Exited Successfully” or “Short Position Exited Successfully”, depending on the direction of the trade.

<figure><img src="/files/YK7TcCZvyXmgW4GpafHw" alt=""><figcaption></figcaption></figure>

**Step 5**— All closed positions are recorded in the “Order History” tab. The closed trade will appear with the action labeled as “Exit Long” or “Exit Short”, and the status will display “Filled” once execution is complete.

<figure><img src="/files/6EcnxgdIcpjQgSfGa73B" alt=""><figcaption></figcaption></figure>


# Adding Margin to an Open Position

Kana Labs’ perpetual futures trading platform uses the Isolated Margin system. This risk-managed approach ensures that only the margin allocated to a specific position is at risk, regardless of the total balance in the trader’s account. It protects users from losing their entire account balance due to adverse price movements in a single trade. However, traders must actively monitor their positions and add margin when necessary to prevent liquidation and maintain a healthy margin buffer

### Step by Step Guide -

**Step 1**— To add margin to an open position, navigate to the “Positions” tab. Locate the active trade for which you wish to increase margin and click the “Add” button, denoted by a pencil icon.

<figure><img src="/files/5aummgLLWPu7CrMMHH6N" alt=""><figcaption></figcaption></figure>

**Step 2**—A pop-up window will appear, allowing you to input the additional margin amount. Note that the additional margin must be less than or equal to the current margin amount displayed in the Positions tab. For example, if the current margin is $1.60, you may add up to $1.60 or any amount below it. In this case, $1.39 is added as additional margin. Once the margin has been updated a notification stating “Margin Added Successfully” will appear on the screen.

<figure><img src="/files/9YWbCHrCqHwHHsLqaabW" alt=""><figcaption></figcaption></figure>


# Defining Take Profit & Stop Loss

Traders can manage risk and lock in profits by assigning Take Profit (TP) and Stop Loss (SL) levels to their positions. These conditional orders can be configured either during order placement or added later to an active trade.

> **Note:** The Stop Loss value must be below the Liquidation Price (for long positions) or above the liquidation price (for short positions), as indicated in the trade summary details.

### Scenario 1: Setting TP/SL During Order Placement

Traders may predefine TP and SL levels while placing both Market and Limit order.

**Step 1**— In the Order Placement section, enable the “TP/SL” checkbox located just above the “Open Long” or “Open Short” button.

<figure><img src="/files/c8XUcUZbTzf5KAmItdpX" alt=""><figcaption></figcaption></figure>

**Step 2**— After entering the trade amount, a pop-up menu will appear prompting you to specify whether the position is **Long or Short**. Select the appropriate direction, then input your desired **Take Profit and Stop Loss prices**.

<figure><img src="/files/uSJ2XHl0K1gZjaLxpLL6" alt=""><figcaption></figcaption></figure>

The platform will display estimated profit/loss values in both absolute and percentage terms based on your TP and SL levels.

### Scenario 2: Modifying TP/SL on an Active Position

If TP/SL levels were not configured at the time of order placement, traders can add or edit them directly from the Positions tab.

**Step 1**—Navigate to the “Positions” tab and locate the active trade. Click the Edit icon (pencil) next to the TP/SL values.

<figure><img src="/files/GRxsR6Bb54yaLyUbdah7" alt=""><figcaption></figcaption></figure>

**Step 2**— A pop-up input field will appear. Enter the desired TP and SL price levels and click “Update” to confirm the changes.

<figure><img src="/files/n9k1ZVfXubvGfChwtv3K" alt=""><figcaption></figcaption></figure>

**Step 3**—Once submitted, a confirmation message will appear stating that the TP/SL levels have been successfully updated. The revised values will be visible in the respective position row.

<figure><img src="/files/OUEK7J8unFpCsCsOL5Pk" alt=""><figcaption></figcaption></figure>


# Breaking Down Kana Perps

{% content-ref url="/pages/3u0GNC0wvpCeRGu1Gwhs" %}
[Assets Supported](/perpetual-futures/kana-perps/breaking-down-kana-perps/assets-supported)
{% endcontent-ref %}

{% content-ref url="/pages/YFICHnySLuSsHzeImoyY" %}
[Order Types](/perpetual-futures/kana-perps/breaking-down-kana-perps/order-types)
{% endcontent-ref %}

{% content-ref url="/pages/LmIEvnNgeARB3GanSO6P" %}
[Orderbook](/perpetual-futures/kana-perps/breaking-down-kana-perps/orderbook)
{% endcontent-ref %}

{% content-ref url="/pages/5HC1oI6HZJ8hef00FCPo" %}
[Funding Rate](/perpetual-futures/kana-perps/breaking-down-kana-perps/funding-rate)
{% endcontent-ref %}

{% content-ref url="/pages/IRFqU9wLgLq7vjF5yXgV" %}
[Leverage](/perpetual-futures/kana-perps/breaking-down-kana-perps/leverage)
{% endcontent-ref %}

{% content-ref url="/pages/MDHv6J2vLAcoa8tmGOxc" %}
[Margin](/perpetual-futures/kana-perps/breaking-down-kana-perps/margin)
{% endcontent-ref %}

{% content-ref url="/pages/eoHbtGuXMFSneqhEOoss" %}
[Hedge Mode](/perpetual-futures/kana-perps/breaking-down-kana-perps/hedge-mode)
{% endcontent-ref %}

{% content-ref url="/pages/vZg3SDdUQ4lGgICgqI3S" %}
[Trading Fees](/perpetual-futures/kana-perps/breaking-down-kana-perps/trading-fees)
{% endcontent-ref %}


# Assets Supported

Kana Perps currently supports trading 3 assets - APT, BTC & ETH in the early beta testnet phase, with plans to add more tokens as we go live on Mainnet. Kana Perps will feature a decentralised and permissionless listing process.

We are currently working on adding meme coins, which have high demand and liquidity in the market, to our list of supported tokens, and we will announce the addition of each of such tokens in our official social media channels.

<br>


# Order Types

Kana Perps currently offers two straightforward order types - Market Orders and Limit Orders. All orders executed on the Kana Perps platform are fully on-chain, ensuring transparency and security.

* **Market Orders** - A market order refers to the purchase or sale of an asset immediately at the prevailing market price as depicted in the chart or the most recent transaction price in the order book. Although this order is executed without delay, traders may encounter slippage depending on the market's liquidity.
* **Limit Orders** - A limit order is the purchase or sale of an asset at a predetermined price or a more favourable one. This mechanism guarantees precise control over pricing; however, the orders will not be executed if the market fails to reach the specified price point.

**Take Profit (TP)** and **Stop Loss (SL)** give users more flexible control over managing and executing their trades. For example, they can decide how long an order should be kept open once it is executed and when to book profits or cut losses based on the price movement of the selected asset.&#x20;

Users can either define the TP/SL values when placing the trade order or after opening a new position. After opening a new position, a user can place the TP/SL for that position by going to the TP/SL column in the “Positions” tab and opening the TP/SL modal.&#x20;

However, the current version of the Kana Perps platform does not allow users to modify the order size once a trade order is placed.  Users can cancel the order before it is executed from the “Open Orders” tab, or the order will be executed and moved to the “Positions” tab.&#x20;

{% hint style="info" %}
Note—Work is in progress to enable modifying the order value of trades while they are still in the “Open Orders” tab, and it will be available shortly.&#x20;
{% endhint %}

And while Limit orders are technically considered maker orders as they sit on the orderbook providing liquidity when TP/SL is triggered, and the open position is closed, those trades would still be considered take orders. There would be no platform fee charged for maker orders, meaning when a limit order gets executed, there would be no platform fee, users would just be charged gas fees. But when TP/SL is triggered, they would be considered taker orders - hence, both platform and gas fees would be charged.&#x20;

###


# Orderbook

The Kana Perps orderbook and matching engine are powered by Econia, which is a high-performance on-chain order book built on the Aptos blockchain. This enables us to combine the benefits of CEXs (efficient price discovery and minimal slippage) with the strengths of DEXs (decentralisation, permissionless access, and user custody of assets), fostering a trading experience that combines efficiency, fairness, and decentralisation.

The order book aggregates liquidity from multiple sources, such as market makers, centralised exchanges and direct trades from the Kana Perps platform. It stores them all in a single digital on-chain marketplace. This helps greatly improve liquidity and price discovery, enabling traders to get better price quotes on their orders regardless of high or low volume.&#x20;

By **leveraging Aptos’ Block-STM engine**, which employs parallel execution and optimistic concurrency technology, **we provide our users with atomic order settlement**, meaning that the entire order execution process—from order placement to matching and settlement—happens in a single transaction.&#x20;

This enables the Kana Perps platform, which has a theoretical limit of over **500,000 transactions per second** owing to the Aptos network and atomic settlement, where price matching and order settlement are merged into a single transaction, to execute multiple trades simultaneously. This has enabled us to eliminate the multi-step delays common in other DEXs and enhance both speed and security.

We have previously built a spot trading exchange powered by Econia orderbook, which has been live on the mainnet for over a year. This demonstrates our ability to deliver transaction processing and trading speeds comparable to centralised exchanges, laying the foundation for the Kana Perps platform.

<br>


# 1-Click Trading in Kana Perps

&#x31;**-Click Trading** allows users to trade seamlessly on [Kana.trade](https://kana.trade/) **without repeated wallet popups**. By leveraging the [**delegation model**](/perpetual-futures/kana-perps/breaking-down-kana-perps/1-click-trading-in-kana-perps/delegation), users can authorize a delegate account to execute trades on their behalf — securely and efficiently.

***

#### 🚀 How It Works

When users connect a wallet (e.g., Petra, Martian, etc.) to the Kana Perps frontend, they are prompted to **enable 1-Click Trading**. Here’s what happens under the hood:

1. **User Signs a Message:**\
   The user signs a short message using their main wallet. This signature is used to verify ownership and generate a consistent, unique delegate key.
2. **Delegate Wallet Generation:**\
   On the frontend, a **delegate account** is created. This process uses:
   * A **server-side secure key (salt)**
   * The **signed message**\
     This ensures a **deterministic delegate address** that is unique to the user and can be regenerated whenever they reconnect.
3. **Enable Delegation On-Chain:**\
   The frontend triggers a transaction to **authorize the delegate account** on-chain. This allows the delegate to manage positions and place/cancel orders, but **not withdraw funds**.
4. **Persistent 1-Click Experience:**\
   Every time the user reconnects using the same wallet, the **same delegate address** is derived and re-enabled, enabling consistent, no-popup trading.

***

#### 🧠 Why It’s Secure

* The **delegate account** is **scoped by on-chain permissions** — it can only interact with trading functions, never withdrawals.
* Since delegation uses a **server-held salt** and signed message, only the original user can regenerate the same delegate.
* Users can **revoke or rotate delegates** at any time from the UI or by direct on-chain action.

***

#### 🔐 Requirements

To use 1-Click Trading:

* A supported wallet extension (e.g., Petra, Nightly)
* Sign a delegation-enabling message
* Approve the on-chain delegation transaction

***

#### ✅ Benefits

* **No repeated popups** when trading
* **Faster execution**, ideal for scalping or bot-assisted strategies
* Maintains **fund-level security** — delegate can’t touch deposits or withdrawals

***

#### 📌 Notes

* Delegation is optional, but **required** for 1-Click Trading.


# Delegation

In Kana Perps, we separate **fund management** from **trading execution** using a **delegation model** (optional). This architecture improves security, reduces wallet prompts, and enables features like one-click trading.

### Overview

There are two account roles in this model:

* **Main Wallet**: Custodian of funds. Only used for deposits and withdrawals.
* **Delegate Account**: Authorized to place/cancel orders and manage positions on behalf of the main wallet. Cannot withdraw funds.

The main wallet is only used for **deposits** and **withdrawals**, while the delegate account is used to **place/cancel orders** and **close positions**. This separation allows us to offer **one-click trading** in the frontend by avoiding repeated wallet confirmations for each trade action.

### Account Roles and Capabilities

<table><thead><tr><th width="299.5625">Action</th><th>Main Wallet</th><th>Delegate Account</th></tr></thead><tbody><tr><td>Deposit Funds</td><td>✅</td><td>❌</td></tr><tr><td>Withdraw Funds</td><td>✅</td><td>❌</td></tr><tr><td>Place Orders</td><td>❌</td><td>✅</td></tr><tr><td>Cancel Orders</td><td>❌</td><td>✅</td></tr><tr><td>Close/Update Positions</td><td>❌</td><td>✅</td></tr><tr><td>Transfer Between Profiles</td><td>✅</td><td>❌</td></tr></tbody></table>

> 💡 The delegate account **cannot withdraw funds**, ensuring user funds remain secure even if the delegate key is compromised.

### Use Cases

This delegation setup is ideal for:

* One-click trading (auto-signing trade ops)
* Enabling bots or trading assistants with limited permissions

#### 🆚 Delegated vs Non-Delegated Scripts

| Use Case                     | Script Module            |
| ---------------------------- | ------------------------ |
| Trading via delegate account | `delegated_scripts.move` |
| Direct control (no delegate) | `perpetual_scripts.move` |

### Security Benefits

* **Fine-grained control** (toggle, change, extend, remove)
* **Time-bounded delegation**
* Only **one proxy** per user
* **On-chain enforcement** of delegation permissions

### Implementation Notes

* Delegation is established by the main wallet via an on-chain transaction.
* Delegates can be added or removed at any time.
* Delegated function are available on `delegated_scripts` while non delegated functions available on `perpetual_scripts`
* All delegate actions are scoped and validated to ensure they cannot move funds.

> ⚠️ Always recommend users to review delegate permissions and rotate keys if suspicious activity is detected.


# Funding Rate

#### Calculation of Funding Rate (Platform Side):

The funding rate mechanism ensures price stability between perpetual contracts and spot markets by incentivising traders to balance long and short positions. Rates are typically recalculated once an hour and reflect market dynamics like demand, supply, and interest rates.

{% hint style="info" %}
**Note**: Traders should monitor funding rates closely, as frequent payments can significantly impact profitability, especially for high-leverage positions.0
{% endhint %}

#### Funding Rate Formula&#x20;

**Funding Rate (R)** = (Max(0, Impact Bid Price - Index Price) - Max(0, Index Price - Impact Ask Price)) / Index Price

The Impact Bid Price and Impact Ask Price are derived from the average execution prices of market orders for a specific "Impact Notional Amount." These values are designed to reflect the immediate liquidity and price impact of a trade of a certain size. Index Price is the oracle price

**Impact Bid Price:** The Impact Bid Price represents the average execution price for a market sell order of the Impact Notional Amount. This essentially simulates the price a large seller would receive when exiting their position.

**Impact Ask Price:** The Impact Ask Price represents the average execution price for a market buy order of the Impact Notional Amount. This simulates the price a large buyer would pay when entering a position.

**Impact Notional Amount:** The Impact Notional Amount is a standardized value used in the calculation of the Impact Bid and Ask Prices. It is defined as:

Impact Notional Amount = 500 USDC / Initial Margin Fraction

Initial margin fraction is the corresponding margin of the max leverage of a particular market. For e.g., in APT perps the max leverage that we offer is 20x, so corresponding margin is 5%.

Impact notional amount of APT market = 500/0.05 = $10,000

**Funding Rate calculation frequency:**&#x20;

The Funding Rate (R) is calculated every minute. At the end of each hour, the average of these 60 minute-by-minute calculations is computed to determine the final Funding Rate (R) for that hour.

**Funding Rate Application:**

The hourly average is applied to all open positions, credited or debited based on long/short exposure. A 1% per-minute cap is enforced to prevent abusive funding events and if any minute's funding exceeds this threshold, it is clamped to 0.

***

#### Calculation of Funding Payment (User side):&#x20;

\
The funding payment is a periodic payment exchanged between traders in perpetual futures markets to ensure the contract price aligns with the spot market price. Depending on whether the funding rate is positive or negative, payments flow from long to short traders or vice versa.

Funding Payment Formula:

<mark style="color:red;">**F = (−1) × S × P × R**</mark>

S: Position size (positive for long, negative for short)

P: Mark price of the asset (current fair price)

R: Funding rate (determined periodically based on market conditions)

***

#### Example:

Let us consider a scenario where the order value is $250 USDT and the current price of the selected asset - “APT-PERP”, is at US $7 per APT, then here’s how the funding rate would be calculated -&#x20;

Given Parameters:

* Order Value: $250
* Mark Price (P): $7
* Position Size (S):&#x20;

S = Order Value / Mark Price = 250 / 7 = 35.71 APT

* Funding Rate (R): Assume 0.02% (0.0002)

Funding Payment Calculation:

F = (−1) × S × P × R&#x20;

F = (-1) × 35.71 × 7 × 0.0002&#x20;

F = −0.05

Interpretation:

* If the funding rate is **positive** (0.02%), **long traders pay 0.05 USDT to short traders**.
* If the funding rate is **negative, short traders pay long traders**.
* **Payments happen once every hour** <br>


# Leverage

Leverage allows traders to place trades with a value much larger than their actual account balance. On Kana Perps, contracts can be traded with leverage of up to 20x.

<mark style="color:red;">**Leverage = Order Value / Margin Used**</mark>

Leverage greatly affects margin usage and requirements, increasing the risk of liquidation. Traders must understand how leverage works and the risks involved. To avoid falling below the maintenance margin (the margin requirement per your positions) and facing liquidation, ensure your positions have sufficient margin by regularly monitoring them and depositing additional funds when necessary. &#x20;

<br>


# Margin

## Isolated Margin Method

The Kana Perps Platform uses the Isolated Margin method, requiring traders to maintain sufficient margin to open and manage their positions effectively.  Under this system, traders need an initial margin amount to open a trade order and a maintenance margin amount to keep the order active/open in the orderbook.&#x20;

The initial margin requirement is calculated using the below formula:

<mark style="color:red;">**Margin= (Position Size X Mark Price) / Leverage**</mark>&#x20;

> &#x20;(in simpler words, Margin equals order value divided by leverage)

**Position Size**: The quantity of the asset being traded (e.g., 35.71 APT for a $250 trade order at $7 per APT).

**Mark Price**: A fair value price derived from market-wide data to calculate margin and prevent manipulation.

***

#### Example:

With a current asset trading price of $7 per APT and an order value of $250 USDT, the initial maintenance margin required to open a trade order would be -

If we take 10x leverage:

* Margin Used:  35.71 X 7 / 10 = 25 USDT&#x20;

For 20x leverage:

* Margin Used: 35.71 x 20 / 20 = 12.5 USDT

***

## Margin Management & Liquidation

Traders must maintain a maintenance margin whenever they have active trades, which is a smaller proportion of the initial margin, to keep positions active. A margin call will be issued if the collateral falls below this threshold due to price fluctuations, which will liquidate your trade order.&#x20;

The liquidation threshold, also known as the maintenance margin, is the minimum margin requirement that traders must maintain to keep their positions open. If the account balance falls below this threshold due to adverse price movements, the position will be automatically liquidated to prevent further losses.

Maintenance Margin Calculation:

Our maintenance margin is set at 2.5% of the position’s notional value.

Using the previous example:

Based on the metrics in the initial maintenance margin example, we have &#x20;

* Notional Value: 35.71 × 7 = 250 USDT
* Maintenance Margin: 250 × 0.025 = 6.25 USDT

***

<br>


# Liquidation

#### What is Liquidation

Liquidation occurs when the account balance (initial margin + unrealised PnL) drops below the maintenance margin requirement. The key factors affecting liquidation include:

* Mark Price Movement – If the mark price moves unfavourably, unrealised losses will increase, reducing the trader's margin balance.
* Leverage Impact: Higher leverage reduces the initial margin required but increases liquidation risk, as small price movements can quickly deplete the margin.

#### Liquidation Calculation Formula:

For Long positions:

> **Liquidation Price (Long) = Asset Price × (1−Initial Margin Ratio)/(1−Maintenance Margin Ratio)**

For Short positions:

> **Liquidation Price (Short) = Asset Price × (1+Initial Margin Ratio)/(1+Maintenance Margin Ratio)**

#### &#x20;Example of Liquidation Trigger

* Asset price: $7
* Quantity: 35.71 APT
* Notional Value: $250
* Leverage: 10x
* Initial Margin Used: $25
* Initial Margin Ratio: 1 / 10 = 0.1
* Maintenance Margin Ratio: 0.025 (i.e. 2.5%)

Liquidation price for Long position -> L = 7×(1−0.025)/(1−0.1)​ = 7 × 0.975 / 0.9 = 6.461

Meaning, the liquidation price for long position is at $6.46&#x20;

\
Liquidation price for Short position -> S = 7×(1+0.025)/(1+0.1) = 7​ × 1.1 / 1.025 = =7.512

​ Meaning, the liquidation price for short position is at $7.51&#x20;

{% hint style="info" %}
Did you know that you get 50% of the remaining margin amount as refund when your trades get liquidated. For more details regarding how this works check out -> <https://docs.kanalabs.io/perpetual-futures/kana-perps/technical-architecture#liquidation-logic>
{% endhint %}

#### Preventing Liquidation

To avoid liquidation, traders should:

* Regularly monitor their margin balance and unrealised PnL.
* Add more collateral before the margin balance drops below the maintenance requirement.
* Use lower leverage to reduce liquidation risk.
* Set stop-loss orders to manage risk proactively.

Actively managing margin levels and monitoring price fluctuations can help traders avoid liquidation and control their positions. Adding collateral when necessary is also recommended to prevent forced liquidation.<br>


# Insurance Fund

## Insurance Fund

The **Insurance Fund** is a core risk-management component in Kana Perps. It is designed to absorb losses from undercollateralized liquidations and provide a backstop for extreme market events.

#### Purpose

The primary role of the Insurance Fund is to ensure that the platform remains solvent and traders are protected even if a liquidated position's loss exceeds the user’s posted collateral.

#### Funding Mechanisms

The Insurance Fund is funded in two main ways:

1. **Voluntary Contributions:**
   * Any user can deposit funds into the Insurance Fund at any time.
   * These deposits are recorded and tracked separately from user trading balances.
   * The fund is denominated in `KanaUSDT`.
2. **Automatic Allocations from Liquidations:**
   * During every liquidation, if the user has remaining collateral:
     * **20%** of that collateral is automatically added to the Insurance Fund.
     * The rest is distributed as per the standard liquidation logic (30% to the liquidator, 50% back to the user).
   * These contributions continue until the fund reaches its configured **threshold cap**.

#### Threshold and Admin Control

* The Insurance Fund has a **platform-wide threshold** that defines the maximum reserve it should hold.
* Once this threshold is reached:
  * **Platform administrators** are granted permission to withdraw excess funds for operational or treasury use.
* Withdrawals can only occur **after the threshold is met**, ensuring that the fund remains adequately capitalized for risk protection.

> **Important:** Admins cannot access or withdraw funds from the Insurance Fund before the threshold is reached, enforcing a strict safeguard for user protection.

#### Use During Insolvency

When a position’s losses **exceed the user’s collateral**, and liquidation is triggered:

* The Insurance Fund **covers the shortfall**.
* In such cases, **no rewards** are given to the liquidator.
* The fund acts as a payer of last resort to ensure markets remain balanced and counterparties are not affected


# Hedge Mode

The Hedge Mode is a novel and exclusive functionality of the Kana Perps platform. It is designed to help traders maintain flexibility while minimising their exposure to liquidation risk. It enables users to open long and short positions on the same asset simultaneously, whether for speculative trading or risk management. This allows traders to hedge existing positions while maintaining full control over their exposure.

By opening a hedged position against existing open positions, traders can avoid getting liquidated by neutralising exposure. This feature can also help prevent traders from incurring losses during sudden news-driven short-term market volatility by opening dual positions and exiting one side to lock in profits. Traders can also use the hedged mode to capture funding rate arbitrage for passive income

Here is a breakdown of Hedge Mode works in various  scenarios -&#x20;

* Hedging a Short-Term 2-3% Price Decline
* Dual Positioning for Profit-Taking (Speculative Trading)

Each section will include PnL calculations, funding effects, and liquidation risks.

<br>

<br>


# Hedging a Short-Term 2-3% Price Decline

Trader’s Initial Long Position Details

The trader already has an open long position worth $250 USDT, which was executed at the price of $7 per APT for 20X Leverage, resulting in an order with the position size of 35.71 APT tokens but speculates the possibility of a small price drop (\~2-3%).

* Opens a short position with an order value of $250 at $6.86 (2% lower).
* Short Position Size:

S = 250 / 6.86 = 36.45 APT

* Margin Used&#x20;

250 / 20 = 12.5 APT

**What Happens If Price Drops?**

* At 3% Drop ($6.79)

Long PnL = (6.79 − 7) × 35.71 = −7.5 USDT

Short PnL = (6.86 − 6.79) × 36.45 = 2.56 USDT

* At 2% Drop ($6.86)

Long PnL = $-5 USDT

Short PnL = $0 USDT (neutral hedge).

**Liquidation Risks**

Long Position Liquidation Price = 7 × (1−120) = 6.65

This means the Long position liquidates if the price falls below $6.65.

Short Position Liquidation Price = 6.86 × (1 + 120) = 7.2&#x20;

This means the short position liquidates if the price rises above $7.2

**Decision Point**

* This hedge partially offsets losses if the price stabilises at $6.79 - $6.86.
* The trader can close the short position for a small profit.

**Key Takeaway**

* Hedging helps protect against a small downside move.
* However, if the price rebounds too fast, the short position becomes a liability.


# Dual Positioning for Flexible Profit-Taking

This is a speculative trading method on Kana Perps platform

**How to Use Dual Positions**

* Traders can open long and short positions at the same price and equal size.
* This allows them to profit from funding rate changes or close the more profitable side.

**Example**:&#x20;

* Opening a Long and Short at $7
* Long Position: $250 at $7
* Short Position: $250 at $7
* Total Margin Used: (250 / 20) + (250 / 20) = 25 USDT

**How Funding Rate Works**

* If the Funding Rate is Positive (+0.02%), the Long pays Short, and the Trader must now wait for a price move to close one position profitably.
* If the Funding Rate Flips Negative (-0.01%), the Short pays Long, resulting in the trader earning passive income. Here, the trader profits without price movement.

Profiting by Closing One Position

Scenario 1: Price Drops from $7 to $6.80

* Long loses $7.14 USDT.
* Short profits $7.14 USDT.
* Trader closes the short, keeping the long open.

Scenario 2: Price Rises from $7 to $7.20

* Short loses $7.14 USDT.
* Long profits $7.14 USDT.
* Trader closes the long, keeping the short open.

**Liquidation Risks**

* Only at extreme price moves (15-20%+) would one position risk liquidation.

**Why This Works for Speculators**

* No risk from funding rate shifts (as long cancels short).
* Flexible profit-taking—whichever side gains, the trader closes the winning side.
* Earning passive funding fees when rates flip negative.

**Key Takeaway**

* Best case: Funding rate flips negative → Long earns passive fees.
* Alternative: Price moves → Close the profitable position.


# Trading Fees

Trading fees are proportional to the position size and are applied when a position is opened or closed.

* Taker orders incur a 0.05% fee.
* Maker orders have no fees.

We also offer a VIP Fee Structure where the fees charged on taker orders are discounted further based on the wallet’s “Kana” Tokens holdings and 14-day trading volume. Here’s a detailed breakdown of the same -&#x20;

* VIP0: $3M volume – Taker fee 0.03% (0.015% with KANA + referral discount)
* VIP1: $3M + 10K KANA – Taker fee 0.025% (0.0125% with KANA + referral)
* VIP2: $10M + 40K KANA – Taker fee 0.02% (0.01% with KANA + referral)
* VIP3: $25M + 100K KANA – Taker fee 0.015% (0.007% with KANA + referral)
* VIP4: $100M + 200K KANA – Taker fee 0.01% (0.005% with KANA + referral)
* VIP5: $500M + 300K KANA – Taker fee 0.005% (0.0025% with KANA + referral)
* VIP6: $1B + 500K KANA – Taker fee 0.002% (0.001% with KANA + referral)
* VIP7: $1.5B + 700K KANA – Taker fee 0.0015% (0.0007% with KANA + referral)
* VIP8: $2B + 1M KANA – Taker fee 0.001% (0.0005% with KANA + referral)
* VIP9: $5B + 1.5M KANA – Taker fee 0.0005% (0.00025% with KANA + referral)

> Maker fees are always 0% and higher KANA holdings equals lower fees. Note the discount for Kana holdings is applicable post TGE

<br>


# Technical Architecture

Kana Labs' perpetual DEX leverages the Aptos blockchain and integrates **Econia** on-chain orderbook. Built with scalability, composability, and security in mind, the system is designed to be modular, decentralized, permissionless, and optimized for high-throughput trading.

***

## Core Components

### 1. Trade Profiles

Trade profiles are [Aptos objects](https://aptos.dev/en/build/smart-contracts/objects) that represent an individual user’s trading state on Kana Perps. These objects serve as the foundational identity for interaction with the trading protocol.

* When a user interacts with the platform for the first time (e.g., deposits funds), a **trade profile is automatically created** if it does not already exist.
* This profile is essential for:
  * Holding trading balances
  * Managing open positions
  * Storing collateral
  * Interfacing with order placement and settlement mechanisms

Because of Aptos's object model, each trade profile is uniquely tied to the user and ensures strong state isolation across traders.

***

### 2. Market Creation

Kana enables permissionless market creation for any asset with a reliable price feed available on **Pyth Network**. Markets are created and owned by a **market creator**, who is responsible for parameter management and liquidity provisioning.

**2.1 Market Creator Responsibilities**

Upon creating a market, the creator becomes:

* **Maintainer**: Controls market state and configuration.
* **Fee Recipient**: Receives all trading fees generated by the market.
* **Market Maker Whitelister**: Has authority to whitelist addresses as market makers.

#### 2.2 Initialization Parameters

| Parameter            | Description                                  |
| -------------------- | -------------------------------------------- |
| `creator`            | Signer reference for the market creator      |
| `fee_wallet`         | Address that collects market fees            |
| `base_name`          | Identifier for the base asset                |
| `lot_size`           | Minimum tradable unit size                   |
| `tick_size`          | Minimum price increment                      |
| `min_lots`           | Minimum order size in lots                   |
| `max_lots`           | Maximum order size in lots                   |
| `max_position_value` | Maximum position value allowed               |
| `maintenance_margin` | Required margin to prevent liquidation       |
| `max_leverage`       | Maximum leverage allowed on the market       |
| `quote_precision`    | Decimal precision for quote asset            |
| `base_decimals`      | Decimal precision for base asset             |
| `quote_decimals`     | Decimal precision for quote pricing          |
| `pyth_price_feed_id` | Vector identifier for Pyth oracle price feed |

#### 2.3 Mutable Parameters

| Mode            | Code | Description                                                       |
| --------------- | ---- | ----------------------------------------------------------------- |
| Active          | 1    | Market is fully operational for all users                         |
| Inactive        | 2    | Market is temporarily disabled                                    |
| Deprecated      | 3    | Market is permanently disabled (irreversible)                     |
| Settlement Only | 4    | Only position settlement is allowed, no new orders (irreversible) |
| MM Only         | 5    | Only whitelisted market makers can place orders                   |

#### 2.4 Market Modes

Kana Perps defines several operational modes for markets, each representing a different trading state. These modes are critical for lifecycle management and operational flexibility:

1. <mark style="color:green;">**Active**</mark>: The market is live and open to all traders. Orders can be placed, canceled, and matched freely.
2. <mark style="color:yellow;">**Inactive**</mark>: The market is temporarily paused.
3. <mark style="color:red;">**Deprecated**</mark>: The market is permanently closed. No further trading or changes are allowed, and the market can never be reactivated.
4. <mark style="color:orange;">**Settlement-Only**</mark>: Only order settlement (e.g., closing positions) is allowed. New order placements are disallowed. Like deprecated mode, this state is irreversible.
5. <mark style="color:blue;">**Market Maker Only (MM Only)**</mark>: Only addresses that have been whitelisted as market makers can place orders. This mode is typically used during initial market setup to allow liquidity provisioning before opening the market to the public.

By default, all newly created markets begin in <mark style="color:blue;">**Market Maker Only**</mark> mode, giving the creator an opportunity to whitelist professional liquidity providers and bootstrap depth on the orderbook before transitioning to a publicly tradable state.

> <mark style="color:red;">**Note:**</mark> <mark style="color:red;"></mark><mark style="color:red;">Once a market enters</mark> <mark style="color:red;"></mark><mark style="color:red;">`SETTLEMENTONLY`</mark> <mark style="color:red;"></mark><mark style="color:red;">or</mark> <mark style="color:red;"></mark><mark style="color:red;">`DEPRECATED`</mark><mark style="color:red;">, it cannot be reactivated. This enforces immutability guarantees for deprecated markets.</mark>

**2.5 Market Maker Whitelisting**

Market creators can whitelist specific addresses as **market makers**, enabling them to:

* Exceed standard position limits (`max_position_value`)
* Trade during restricted phases such as `MM_ONLY` mode
* Participate in liquidity provisioning.

***

### 3. Asset Management

Econia markets require two assets: a **base asset** and a **quote asset**.

**3.1 Base Asset**

* The base asset is not required to be an Aptos `Coin` type.
* It is **custom-managed** by **the market underwriter** internally.

**3.2 Quote Asset: KanaUSDT**

Kana Perps standardizes all quote currencies via an internal stablecoin abstraction called `KanaUSDT`:

* **Pegged 1:1 to USDT**
* **Internally minted/burned** during trade flows
* **Non-transferable and inaccessible externally**

This design ensures:

* Unified accounting across all markets
* Economic isolation from external protocols
* Guaranteed encapsulation of Econia orderbook access — **only Kana modules can interact with these markets**

> This design effectively “locks” the Econia markets created via Kana, preventing unauthorized access by third-party contracts or traders.

***

## Order Lifecycle

#### 4. Order Placement

When a user places an order, the system performs a sequence of operations to manage risk and settlement preparation.

**4.1 Collateral Calculation**

1. The total order value is computed from size and price.
2. The **required collateral** is calculated based on the user’s selected leverage.
3. Collateral is withdrawn from the user’s trading profile and stored in a **collateral vault** specific to the order.

**4.2 Execution Flow**

* **Long Positions**:
  * Kana calculates the quote contribution:\
    `KanaContribution = TotalPositionValue - UserCollateral`
  * Internal minting of `KanaUSDT` equal to `TotalPositionValue`
  * Funds are deposited into the corresponding Econia market account
  * The order is placed on the **Econia orderbook**
* **Short Positions**:
  * The base asset is deposited directly using the underwriter capability
  * `KanaUSDT` equal to user collateral is minted and deposited alongside the base asset

#### 5. Order Cancellation

If a user cancels an order:

* It is removed from the Econia orderbook
* Associated collateral is unlocked and refunded to the user’s trading profile

***

## Funding Rate Mechanism

Funding rates incentivize price convergence between perpetual markets and the oracle spot price. Kana implements a dynamic funding system using the **Pyth oracle** and **impact pricing**.

#### 6.1 Calculation

* Every minute, a temporary funding rate is derived using:

  ```
  impact_quote = 500 * 10^6 * market_leverage
  ```
* `impact_bid` and `impact_ask` are calculated to simulate slippage
* A rolling hourly average is computed from 60 one-minute snapshots

#### 6.2 Application

* The hourly average is applied to all open positions, credited or debited based on long/short exposure
* A **1% per-minute cap** is enforced to prevent abusive funding events:
  * If any minute's funding exceeds this threshold, it is clamped to 0

***

## Liquidation Logic

Kana’s liquidation process ensures robust solvency guarantees and minimizes risk propagation.

#### 7.1 Trigger Conditions

* Liquidation is triggered when the **oracle price** from Pyth breaches a position’s liquidation threshold
* External actors (e.g., bots) call the `liquidate` function

#### 7.2 Execution and Distribution

If the user’s collateral **covers the loss**:

* Position is closed
* Remaining collateral is distributed as:
  * **30%** to the liquidator
  * **20%** to the insurance fund
  * **50%** refunded to the user

If the loss **exceeds the collateral**:

* Insurance fund is used to cover the shortfall
* **No reward** is given to the liquidator

This ensures:

* Risk is socialized responsibly
* Liquidator incentives align with solvency maintenance

##

***


# API Docs

API for our perpetual futures platform

## Introduction

This section provides the API for Kana Perps, our perpetual futures trading platform. It includes endpoints for market data, placing orders, managing positions, and more to help you integrate and trade easily.

### Overview

Kanalabs supports both REST and WebSocket APIs for seamless integration with your application.

### REST API Endpoints

#### Testnet

* **Base URL**: <https://perps-tradeapi.kanalabs.io>

### WebSocket API Endpoints

#### Testnet

* **WebSocket URL**: wss\://perps-sdk-ws.kanalabs.io

### Request and Response Format

* **Requests**: All requests must be in JSON format.
* **Responses**: Responses can either be a JSON object or an array.

### SDKs

#### TypeScript SDK

* **GitHub Repository**: [kana-perps-sdk](https://github.com/kanalabs/kana-perps-sdk)

```
Please note that an API Key is required to integrate your bots/trading tools with our API.
To get the API key from us, reach out via email at hello@kanalabs.io
```


# Installation Setup

Overview of supported trading markets and installation prerequisites for using the API.

### Testnet Supported Markets

<table data-header-hidden><thead><tr><th></th><th width="282"></th><th></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td><td><strong>Description</strong></td></tr><tr><td>APT-USD</td><td>1338</td><td>Aptos-based trading market.</td></tr><tr><td>BTC-USD</td><td>1339</td><td>Bitcoin-based trading market.</td></tr><tr><td>ETH-USD</td><td>1340</td><td>Ethereum-based trading market.</td></tr><tr><td>SOL-USD</td><td>2387</td><td>Solana-based trading market.</td></tr></tbody></table>

### Mainnet Supported Markets

<table data-header-hidden><thead><tr><th></th><th width="282"></th><th></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td><td><strong>Description</strong></td></tr><tr><td>APT-USD</td><td>14</td><td>Aptos-based trading market.</td></tr><tr><td>BTC-USD</td><td>15</td><td>Bitcoin-based trading market.</td></tr><tr><td>ETH-USD</td><td>16</td><td>Ethereum-based trading market.</td></tr><tr><td>SOL-USD</td><td>31</td><td>Solana-based trading market.</td></tr></tbody></table>

#### Prerequisites

Before using the API, ensure you have the following:

1. **Node.js**: Install version 16 or higher. [Download here](https://nodejs.org/).
2. **npm**: Verify npm is installed to manage packages.

#### Install Required Packages

Run these commands to install the required dependencies:

1. Install `dotenv` and `axios`:

   ```bash
   npm install dotenv axios
   ```
2. Install the Aptos SDK for TypeScript:

   ```bash
   npm install @aptos-labs/ts-sdk
   ```

#### Example Setup in TypeScript

Create a file, e.g., `setup.ts`, and use the following code:

```typescript
// Import required packages
import dotenv from 'dotenv';
import axios from 'axios';
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";

// Load environment variables from .env file
dotenv.config();

// Setup the client
const config = new AptosConfig({ network: Network.TESTNET });
const aptos = new Aptos(config);
const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
);
const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
});
```

### **Size Conversion Details:**

**APT Market**

* `base_decimals`: **8**
* `lot_size_multiplier`: **100000**

**BTC Market**

* `base_decimals`: **8**
* `lot_size_multiplier`: **1000**

**ETH Market**

* `base_decimals`: **8**
* `lot_size_multiplier`: **10000**

#### Size Conversion Example in TypeScript:

```typescript
import BigNumber from "bignumber.js";

async function main(): Promise<void> {

    // Size conversion
    const size = new BigNumber("your_size_value"); // Eg: 5.67
    const baseDecimals = "your_base_decimals_value"; // Eg: 8
    const lotSizeMultiplier = new BigNumber("your_lot_size_multiplier_value"); // Eg: 100000

    // 10^baseDecimals
    const sizeScalingFactor = new BigNumber(10).pow(baseDecimals);

    // Convert size and remove decimals
    const convertedSize = size.multipliedBy(sizeScalingFactor).dividedBy(lotSizeMultiplier).integerValue(BigNumber.ROUND_FLOOR);

    console.log("Converted Size: ", convertedSize.toString());
}

main().catch(error => {
    console.error('An error occurred:', error);
});

```

### **Price Conversion Details:**

**APT Market**

* `price_precision`: **3**

**BTC Market**

* `price_precision`: **0**

**ETH Market**

* `price_precision`: **1**

#### Price Conversion Example in TypeScript:

```typescript
import BigNumber from "bignumber.js";

async function main(): Promise<void> {

    // Price conversion
    const price = new BigNumber("your_price_value"); // Eg: 8.356
    const pricePrecision = "your_price_precision_value"; // Eg: 3

    // 10^pricePrecision
    const priceMultiplier = new BigNumber(10).pow(pricePrecision);

    // Convert price and remove decimals
    const convertedPrice = price.multipliedBy(priceMultiplier).integerValue(BigNumber.ROUND_FLOOR);

    console.log("Converted Price: ", convertedPrice.toString());
}

main().catch(error => {
    console.error('An error occurred:', error);
});

```


# Kana Perps Typescript REST API

### **Important Note:**

For all the API endpoints below, pass your wallet address as the `userAddress` parameter.

To track your transactions on-chain (e.g., via **Aptos Explorer** or **Aptos Scan**), you must use your **profile address**, as all on-chain trades are executed using this profile address.

To obtain your profile address, use the `/getProfileAddress` endpoint and provide your wallet address as the `userAddress` parameter.

### How to Fetch the Profile Address:

**Example endpoint:**\
<https://perps-tradeapi.kanalabs.io/getProfileAddress?userAddress=0xd01e3a233632a41463bd6d289e99e69e1b50815c7afff710e1c992659a8722f3>\
\
**Example code:**\
<https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/kana-perps-typescript-rest-api#id-20.-get-profile-address>

## ✅ <mark style="color:red;">**Testnet API  Endpoint URL**</mark>

```typescript
https://perps-tradeapi.kanalabs.io
```

## ✅ <mark style="color:red;">**Mainnet API Endpoint URL**</mark>

```typescript
https://perps-tradeapi.kana.trade
```

### <mark style="color:yellow;">Please ensure that the correct network is passed</mark>: use `Network.TESTNET` for Testnet and `Network.MAINNET` for Mainnet

## **1. Get Market Info**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getMarketInfo`](#id-1.-get-market-info)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `marketId` (Required) - The ID of the market you want information about.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getMarketInfo?marketId=501
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Market information fetched successfully",
  "data": [
    {
    "__variant__": "V1",
    "base_decimals": 8,
    "base_name": "APT/USDC",
    "counter": "0",
    "creator": "0xb61d7b57333abf8ac036e752f19d0ba0c4baa5404db1cbf868c57dac3628f2bf",
    "custodian_id": "75",
    "fee_address": "0x7724a4a23b25b460abc2a5d9fe1fe3c47e2a0e10a156dd713a221f129579c388",
    "is_recognised": false,
    "lot_size": "100000",
    "maintenance_margin": "250",
    "market_address": "0xcfa0086c26787035de6b4a312875c7a70b2f9a29fa880d0cf633ef3dd0acd2c3",
    "market_id": "1338",
    "market_status": 1,
    "max_leverage": "20",
    "max_lots": "150000000",
    "max_position_value": "125000000",
    "min_lots": "500",
    "quote_decimals": 6,
    "quote_precision": 3,
    "tick_size": "1",
    "timestamp": "1745079291",
    "underwriter_id": "73"
  }
  ]
}
```

**Example Code to Fetch Market Information:**

The following TypeScript/Node.js script demonstrates how to call the Get Market Info API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getMarketInfo';
    const params = {
        marketId: 501
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getMarketInfo: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **2.** Get Wallet Account Balance

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getWalletAccountBalance`](https://perps-tradeapi.kanalabs.io/getWalletAccountBalance)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `userAddress` (Required) - The wallet address for which the account balance is being fetched.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getWalletAccountBalance?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched wallet account balance successfully",
  "data": 16391.60
}
```

**Example Code to Fetch** Wallet Account Balance **Information:**

The following TypeScript/Node.js script demonstrates how to call the Get Wallet Account Balance API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getWalletAccountBalance';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getWalletAccountBalance: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **3.** Get Profile Balance Snapshot

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getProfileBalanceSnapshot`](https://perps-tradeapi.kanalabs.io/getProfileBalanceSnpashot)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `userAddress` (Required) - The wallet address for which the account balance is being fetched.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getProfileBalanceSnapshot?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Profile balance snapshot fetched successfully",
  "data": 44.321972
}
```

**Example Code to Fetch** Trading Account Balance **Information:**

The following TypeScript/Node.js script demonstrates how to call the Get Trading Account Balance API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getProfileBalanceSnapshot';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getProfileBalanceSnpashot: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **4. Deposit**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/deposit`](https://perps-tradeapi.kanalabs.io/deposit)
* **Method**:\
  `GET`
* **Query Parameters:**
  * `amount` (Required) - The amount of the quote coin to deposit.
  * `userAddress` (Required) - The address of the user making the deposit.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/deposit?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&amount=50000000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Deposit payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::deposit",
    "functionArguments": [
      "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
      50000000
    ],
    "typeArguments": []
  }
}
```

**Example Code to Depsoit a quote coin:**

The following TypeScript/Node.js script demonstrates how to call the Get Deposit API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
        process.env.APTOS_PRIVATEKEY || '',
        'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
        privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/deposit';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770',
        amount: 1000
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    const payloadData = res.data.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    console.log(`Submitted transaction: ${committedTxn.hash}`);
    const response = await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
    console.log("response", response.success);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **5. Withdraw Specific Market**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket`](https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `marketId` (Required) - The ID of the market you want to withdraw.
  * `amount` (Required) - The amount of the quote coin to withdraw.
  * `userAddress` (Required) - The address of the user making the withdraw.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket?marketId=501&userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&amount=50
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Withdraw specific market payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::withdraw_specific_market",
    "functionArguments": [
      "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
      501,
      50000000
    ],
    "typeArguments": []
  }
}
```

**Example Code to Withdraw a quote coin:**

The following TypeScript/Node.js script demonstrates how to call the Get Withdraw API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
        process.env.APTOS_PRIVATEKEY || '',
        'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
        privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770',
        marketId: 501,
        amount: 1000
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    const payloadData = res.data.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    console.log(`Submitted transaction: ${committedTxn.hash}`);
    const response = await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
    console.log("response", response.success);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **6. Place Limit Order**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/placeLimitOrder`](https://perps-tradeapi.kanalabs.io/placeLimitOrder)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market where the limit order will be placed.
  * **tradeSide** (Required) - Indicates the trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **direction** (Required) - Indicates the direction of the trade:
    * `false` to open a position.
    * `true` to close a position.
  * **size** (Required) - The size of the order.
  * **price** (Required) - The price at which the order is to be placed.
  * **leverage** (Required) - The leverage to be used for the order.
  * **restriction**  - Specifies the type of order restriction. It is an optional parameter with a default value of `0`.\
    Possible values are:
    * `0` - `NO_RESTRICTION`: Optionally fill as a taker, then post to the book as a maker.
    * `1` - `FILL_OR_ABORT`: Abort if any size posts as a maker (only fill).
    * `3` - `POST_OR_ABORT`: Abort if any size fills as a taker (only post).
    * If `restriction` is not provided, it defaults to `0`. It can either be a number or left undefined.
  * **takeProfit** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
  * **stopLoss** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/placeLimitOrder/?marketId=501&tradeSide=true&direction=false&size=10000&price=3000&leverage=3
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Limit Order payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::place_limit_order",
    "functionArguments": [
      "501",
      "true",
      "false",
      1000000,
      8000000,
      "5",
      0,
      0,
      0
    ],
    "typeArguments": []
  }
}
```

**Example Code to Place a limit order:**

The following TypeScript/Node.js script demonstrates how to call the Get Place Limit Order API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
        process.env.APTOS_PRIVATEKEY || '',
        'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
        privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/placeLimitOrder';
    const params = {
        marketId: 501,
        tradeSide: true,
        direction: false,
        size: 1.5,
        price: 5.7,
        leverage: 2
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    const payloadData = res.data.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    console.log(`Submitted transaction: ${committedTxn.hash}`);
    const response = await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
    console.log("response", response.success);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **7. Place Market Order**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/placeMarketOrder`](https://perps-tradeapi.kanalabs.io/placeMarketOrder)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market where the limit order will be placed.
  * **tradeSide** (Required) - Indicates the trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **direction** (Required) - Indicates the direction of the trade:
    * `false` to open a position.
    * `true` to close a position.
  * **size** (Required) - The size of the order.
  * **leverage** (Required) - The leverage to be used for the order.
  * **takeProfit** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
  * **stopLoss** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/placeMarketOrder?marketId=66&tradeSide=false&direction=true&size=1000&leverage=20
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Market Order payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::place_market_order",
    "functionArguments": [
      "501",
      "true",
      "false",
      1000000,
      "5",
      0,
      0
    ],
    "typeArguments": []
  }
}
```

**Example Code to Place a market order:**

The following TypeScript/Node.js script demonstrates how to call the Get Place Market Order API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
        process.env.APTOS_PRIVATEKEY || '',
        'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
        privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/placeMarketOrder';
    const params = {
        marketId: 501,
        tradeSide: true,
        direction: false,
        size: 5.7,
        leverage: 2
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    const payloadData = res.data.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    console.log(`Submitted transaction: ${committedTxn.hash}`);
    const response = await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
    console.log("response", response.success);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **8. Cancel Multiple Orders**

* **Endpoint URL**:\
  [`htps://perps-tradeapi.kanalabs.io/cancelMultipleOrders`](#api-overview)
* **Method**:\
  `POST`
* **Request Body**:
  * **marketId**: The ID of the market for which the orders will be canceled.
  * cancelOrderIds: A list of order IDs to cancel.
  * orderSides: The sides of the orders to cancel (true for long, false for short).

**Example Request:**

```json
{
  "marketId": "501",
  "cancelOrderIds": ["1077898597726583798162207", "1077880153515406921884445"],
  "orderSides": ["true", "false"]
}
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Cancel Multiple Orders payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::cancel_multiple_orders",
    "functionArguments": [
      501,
      [
        '1077898597726583798162207',
        '1077880153515406921884445'
      ],
      [
        true,
        false
      ]
    ],
    "typeArguments": []
  }
}
```

**Example Code to Cancel multiple orders:**

The following TypeScript/Node.js script demonstrates how to call the Post Cancel Multiple Orders API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
        process.env.APTOS_PRIVATEKEY || '',
        'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
        privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });

    const baseURL = 'https://perps-tradeapi.kanalabs.io/cancelMultipleOrders';
    const body = {
        marketId: 501,
        cancelOrderIds: ['82346266390151563318384'],
        orderSides: [true]
    };
    const res = await axios.post(baseURL, body, {
        headers: {
            'x-api-key': process.env.API_KEY,
            'Content-Type': 'application/json',
        },
    });

    const payloadData = res.data.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    console.log(`Submitted transaction: ${committedTxn.hash}`);
    const response = await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
    console.log("response", response.success);
}

main().catch(error => {
    console.error('An error occurred:', error);
});

```

## **8. Place Multiple Orders**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/placeMultipleOrders`](https://perps-tradeapi.kanalabs.io/placeMultipleOrders)
* **Method**:\
  `POST`

Request Body :

* marketId (Required) - The ID of the market where the orders will be placed.
* orderTypes (Required) - An array of order types for each order:
  * true for limit orders.
  * false for market orders.
* tradeSides (Required) - An array indicating the trade sides for each order:
  * true for long positions.
  * false for short positions.
* directions (Required) - An array indicating the direction of each trade:
  * false to open a position.
  * true to close a position.
* sizes (Required) - An array of sizes for each order.
* leverages (Required) - An array of leverages for each order.
* prices (Required) - An array of prices at which each order is to be placed.
* **restriction**  - Specifies the type of order restriction. It is an optional parameter with a default value of `0`.\
  Possible values are:
  * `0` - `NO_RESTRICTION`: Optionally fill as a taker, then post to the book as a maker.
  * `1` - `FILL_OR_ABORT`: Abort if any size posts as a maker (only fill).
  * `3` - `POST_OR_ABORT`: Abort if any size fills as a taker (only post).
  * If `restriction` is not provided, it defaults to `0`. It can either be a number or left undefined.
* **takeProfits** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
* **stopLosses** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```json
{
  "marketId": 501,
  "orderTypes": [true, true],
  "tradeSides": [true, true],
  "directions": [true, true],
  "sizes": [1.6, 1.8],
  "prices": [4.67, 6.78],
  "leverages": [2, 2]
}
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Multiple Orders payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::place_multiple_orders",
    "functionArguments": [
      501,
      [
        true,
        true
      ],
      [
        true,
        true
      ],
      [
        true,
        true
      ],
      [
        1000,
        1000
      ],
      [
        4670,
        6780
      ],
      [
        2,
        2
      ],
      [
        0,
        0
      ],
      [
        4600
      ],
      [
        0,
        0
      ]
    ],
    "typeArguments": []
  }
}
```

**Example Code to Place a multiple orders:**

The following TypeScript/Node.js script demonstrates how to call the Get Place Multiple Orders API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
        process.env.APTOS_PRIVATEKEY || '',
        'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
        privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });

    const baseURL = 'https://perps-tradeapi.kanalabs.io/placeMultipleOrders';
    const body = {
        marketId: 501,
        orderTypes: [true, true],
        tradeSides: [true, true],
        directions: [false, false],
        sizes: [1.7, 1.8],
        prices: [4.1, 4.2],
        leverages: [2, 2]
    };

    const res = await axios.post(baseURL, body, {
        headers: {
            'x-api-key': process.env.API_KEY,
            'Content-Type': 'application/json',
        },
    });

    const payloadData = res.data.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });

    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    console.log(`Submitted transaction: ${committedTxn.hash}`);
    const response = await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
    console.log("response", response.success);
}

main().catch(error => {
    console.error('An error occurred:', error);
});

```

## **9. Cancel and Place Multiple Orders**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/cancelAndPlaceMultipleOrders`](https://perps-tradeapi.kanalabs.io/cancelAndPlaceMultipleOrders)
* **Method**:\
  `POST`

Request Body :

* marketId (Required) - The ID of the market where the orders will be placed.
* cancelOrderIds **(Required)** - An array of strings representing the IDs of the orders to be canceled.
* orderSides **(Required)** - An array indicating the sides of the orders being canceled:
  * `true` for long sides.
  * `false` for short sides.
* orderTypes (Required) - An array of order types for each order:
  * true for limit orders.
  * false for market orders.
* tradeSides (Required) - An array indicating the trade sides for each order:
  * true for long positions.
  * false for short positions.
* directions (Required) - An array indicating the direction of each trade:
  * false to open a position.
  * true to close a position.
* sizes (Required) - An array of sizes for each order.
* leverages (Required) - An array of leverages for each order.
* prices (Required) - An array of prices at which each order is to be placed.
* **restriction**  - Specifies the type of order restriction. It is an optional parameter with a default value of `0`.\
  Possible values are:
  * `0` - `NO_RESTRICTION`: Optionally fill as a taker, then post to the book as a maker.
  * `1` - `FILL_OR_ABORT`: Abort if any size posts as a maker (only fill).
  * `3` - `POST_OR_ABORT`: Abort if any size fills as a taker (only post).
  * If `restriction` is not provided, it defaults to `0`. It can either be a number or left undefined
* **takeProfits** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
* **stopLosses** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```json
{
  "marketId": 501,
  "cancelOrderIds": ['23434565434567', '454345665456'],
  "orderSides": [true, true],
  "orderTypes": [true, true],
  "tradeSides": [true, false],
  "directions": [true, true],
  "sizes": [1000, 2000],
  "prices": [5000, 6000],
  "leverages": [2, 2]
}
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Cancel and place multiple Orders payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::cancel_and_place_multiple_orders",
    "functionArguments": [
      501,
      [
        '23434565434567',
        '454345665456'
      ],
      [
        "true",
        "true"
      ],
      [
        true,
        true
      ],
      [
        true,
        false
      ],
      [
        true,
        true
      ],
      [
        1000,
        2000
      ],
      [
        5000,
        6000
      ],
      [
        2,
        2
      ],
      [
        0,
        0
      ],
      [
        0,
        0
      ],
      [
        0,
        0
      ]
    ],
    "typeArguments": []
  }
}
```

**Example Code to cancel and Place a multiple orders:**

The following TypeScript/Node.js script demonstrates how to call the Get Cancel And Place Multiple Orders API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
        process.env.APTOS_PRIVATEKEY || '',
        'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
        privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });

    const baseURL = 'https://perps-tradeapi.kanalabs.io/cancelAndPlaceMultipleOrders';
    const body = {
        marketId: 501,
        cancelOrderIds: ['85076384513060576956420'],
        orderSides: [true],
        orderTypes: [true],
        tradeSides: [true],
        directions: [false],
        sizes: [1.7],
        prices: [4.1],
        leverages: [2]
    };

    const res = await axios.post(baseURL, body, {
        headers: {
            'x-api-key': process.env.API_KEY,
            'Content-Type': 'application/json',
        },
    });

    const payloadData = res.data.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });

    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });

    console.log(`Submitted transaction: ${committedTxn.hash}`);
    const response = await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
    console.log("response", response.success);
}

main().catch(error => {
    console.error('An error occurred:', error);
});

```

## **10.** Get Open Orders

* **Endpoint URL**:\
  [h`ttps://perps-tradeapi.kanalabs.io/getOpenOrders`](https://perps-tradeapi.kanalabs.io/getOpenOrders)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve open orders for.
  * **marketId (Optional)** - The ID of the market to filter open orders.  // Optional

```
Note : order_type Explanation:

OPEN_LONG (1): Opens a new long position.
OPEN_SHORT (2): Opens a new short position.
INCREASE_LONG (3): Increases the size of an existing long position.
INCREASE_SHORT (4): Increases the size of an existing short position.
DECREASE_LONG (5): Reduces the size of an existing long position.
DECREASE_SHORT (6): Reduces the size of an existing short position.
CLOSE_LONG (7): Closes an existing long position.
CLOSE_SHORT (8): Closes an existing short position.
```

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOpenOrders?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched open orders successfully",
  "data": [
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": 1741444213,
      "price": "7",
      "total_size": "2",
      "remaining_size": "2",
      "order_value": "14",
      "order_id": "645636324063400958808",
      "trade_id": "295147905179352826357",
      "last_updated": 1741444214,
      "transaction_version": 6703807706
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": 1741445758,
      "price": "7",
      "total_size": "2",
      "remaining_size": "2",
      "order_value": "14",
      "order_id": "682529812245179800408",
      "trade_id": "295147905179352826357",
      "last_updated": 1741445758,
      "transaction_version": 6703807706
    }
  ]
}
```

**Example Code to Fetch** Open Order&#x73;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Orders API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getOpenOrders';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getOpenOrders: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **11.** Get Order History

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getOrderHistory`](https://perps-tradeapi.kanalabs.io/getOrderHistory)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve the order history for.
  * **marketId** (optional) - The ID of the market to filter the order history.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOrderHistory?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched order history successfully",
  "data": [
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 1,
      "timestamp": 1741167151,
      "is_market_order": false,
      "size": "1.50",
      "price": "4.678",
      "order_value": "7.01700",
      "status": "Open",
      "order_id": "18446884819787846214",
      "trade_id": "18446744073709552117",
      "last_updated": 1741262093,
      "transaction_version": 6703807706
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 1,
      "timestamp": 1741236277,
      "is_market_order": false,
      "size": "1.50",
      "price": "4.678",
      "order_value": "7.01700",
      "status": "Cancelled",
      "order_id": "18446884819787846214",
      "trade_id": "18446744073709552117",
      "last_updated": 1741262168,
      "transaction_version": 6703807706
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 1,
      "timestamp": 1741236468,
      "is_market_order": false,
      "size": "1.50",
      "price": "4.50",
      "order_value": "6.7500",
      "status": "Open",
      "order_id": "36893628893497397652",
      "trade_id": "36893488147419103733",
      "last_updated": 1741262168,
      "transaction_version": 6703807706
    }
  }
]
```

**Example Code to Fetch Order History:**

The following TypeScript/Node.js script demonstrates how to call the Get Order History API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getOrderHistory';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getOrderHistory: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **12.** Get Positions

* **Endpoint URL**:

[`https://perps-tradeapi.kanalabs.io/getPositions`](https://perps-tradeapi.kanalabs.io/getPositions)

* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address of the user to view positions for.
  * **marketId** (optional) - The ID of the market to filter the positions.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getPositions?marketId=66&userAddress=0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched positions successfully",
  "data": [
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "trade_side": true,
      "size": "1",
      "available_order_size": "1",
      "value": "5.678",
      "entry_price": "5.678",
      "liq_price": "2.9117948717948717990163355253",
      "margin": "2.839",
      "tp": "6.012",
      "sl": null,
      "trade_id": "295147905179352826357",
      "last_updated": 1741262185,
      "transaction_version": 6703807706
    }
  ]
}
```

**Example Code to Fetch** Open Positio&#x6E;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Position API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getPositions';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getPositions: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **12.** Get All Trades

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAllTrades`](https://perps-tradeapi.kanalabs.io/getAllTrades)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market to retrieve all trades information.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAllTrades?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Recent trades fetched successfully",
  "data": [
    {
      "txn_version": 6297687196,
      "event_idx": 5,
      "emit_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "time": "2024-11-20T20:33:38.600241+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15951655917465922493754983",
      "maker_side": true,
      "market_id": 66,
      "price": 11879,
      "sequence_number_for_trade": 0,
      "size": 10000,
      "taker_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "taker_custodian_id": 28,
      "taker_order_id": "15951748150764039921729536",
      "taker_quote_fees_paid": 59395
    },
    {
      "txn_version": 6297687196,
      "event_idx": 4,
      "emit_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "time": "2024-11-20T20:33:38.600241+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15951655917465922493754983",
      "maker_side": true,
      "market_id": 66,
      "price": 11879,
      "sequence_number_for_trade": 0,
      "size": 10000,
      "taker_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "taker_custodian_id": 28,
      "taker_order_id": "15951748150764039921729536",
      "taker_quote_fees_paid": 59395
    }
  ]
}
```

**Example Code to Fetch** All trade&#x73;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Position API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getAllTrades';
    const params = {
        marketId: 501
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getAllTrades: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **13.** Get Order Status By Order Id

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId`](https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market associated with the order.
  * **orderId** (Required) - The unique identifier of the order to retrieve its status.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId?marketId=66&orderId=15308325717473050761363456
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "status": true,
  "message": "Fetched order status for a given order Id successfully",
  "data": {
    "market_id": 66,
    "order_id": "15308325717473050761363456",
    "created_at": "2024-11-20T11:54:45.957059+00:00",
    "last_updated_at": "2024-11-20T11:54:45.957059+00:00",
    "integrator": "0xee820ab02631dd1a195d3c53fa64f0a8f455dbb9261388e141c3bd3bd3c08363",
    "total_filled": 1000,
    "remaining_size": 0,
    "order_status": "closed",
    "order_type": "market",
    "user": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
    "direction": "buy",
    "price": 0,
    "average_execution_price": 12813,
    "custodian_id": 28,
    "self_match_behavior": 0,
    "restriction": 0,
    "last_increase_stamp": null,
    "min_base": null,
    "max_base": null,
    "min_quote": null,
    "max_quote": null,
    "total_fees_paid_in_quote_subunits": 6406
  }
}
```

**Example Code to Fetch** Order Status B Order I&#x64;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Order Status By Order Id API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId';
    const params = {
        marketId: 501,
        orderId : '85094831257134286508036'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getAllTrades: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **14.** Get Fills

**Note:**\
For the `getFills` endpoint, you must pass the **profile address**, not the wallet address.\
Please make sure to first call the **Get Profile Address** endpoint and use that returned address as the `address` parameter in the `getFills` request.

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getFills`](https://perps-tradeapi.kanalabs.io/getFills)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which fills are retrieved.
  * **address** (Optional) - The address of the user to filter fills (if applicable).
  * **from** (Required) - The start time of the range in ISO 8601 format (e.g., `2024-11-21T00:00:00Z`).
  * **to** (Required) - The end time of the range in ISO 8601 format (e.g., `2024-11-21T23:59:59Z`).
  * **orderId** (Required) - The unique identifier of the order to retrieve its status.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getFills?marketId=66&address=0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2&from=2024-11-20T00:00:00Z&to=2024-11-21T23:59:59Z
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched fill trades for a given time range Successfully",
  "data": [
    {
      "txn_version": 6296434935,
      "event_idx": 1,
      "emit_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "time": "2024-11-20T19:23:14.67535+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15891335065048614061485282",
      "maker_side": true,
      "market_id": 66,
      "price": 11490,
      "sequence_number_for_trade": 0,
      "size": 1000,
      "taker_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "taker_custodian_id": 28,
      "taker_order_id": "15891427297643009687945216",
      "taker_quote_fees_paid": 5745
    },
    {
      "txn_version": 6295302625,
      "event_idx": 4,
      "emit_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "time": "2024-11-20T18:19:35.70863+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15812401447297883953966476",
      "maker_side": false,
      "market_id": 66,
      "price": 11660,
      "sequence_number_for_trade": 0,
      "size": 1000,
      "taker_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "taker_custodian_id": 28,
      "taker_order_id": "15812549019983827645235200",
      "taker_quote_fees_paid": 5830
    }
  ]
}
```

**Example Code to Fetch** Order Status B Order IdFills Dat&#x61;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Fills Data API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getFills';
    const params = {
        marketId: 'your_market_id',
        address: 'your_address',
        from: 'your_from_time',
        to: 'your_to_time'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getFillsData : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **14.** Get Market Price

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getMarketPrice`](https://perps-tradeapi.kanalabs.io/getMarketPrice)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the price information is being retrieved.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getMarketPrice?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched Market Price Successfully",
  "data": {
    "bestAskPrice": 6.400,
    "bestBidPrice": 9.880
  }
}
```

**Example Code to Fetch** Market Pric&#x65;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Market Price API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getLastPlacedPrice';
    const params = {
        marketId: 501
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getLastExecutionPrice : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **15.** Get Last Execution Price

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getLastPlacedPrice`](https://perps-tradeapi.kanalabs.io/getLastPlacedPrice)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the last execution price information is being retrieved.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getLastPlacedPrice?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched last execution price Successfully",
  "data": 8.989
}
```

**Example Code to Fetch** Last Execution Pric&#x65;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Last Execution Price API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getLastPlacedPrice';
    const params = {
        marketId: 501
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getLastExecutionPrice : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **16.** Get All Open Order Ids

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds`](https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds)
* **Method**:\
  `GET`
* **Query Parameters**:
  * userAddress(Required) - The address associated with the orders.
  * **marketId** (optional) - The ID of the market for which open order IDs are being retrieved.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds?marketId=66&userAddress=0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Open order IDs fetched successfully",
  "data": [
    "645636324063400958808",
    "682529812245179800408",
    "700976556301709482840",
    "719423300401188838232",
    "737869903703050289159",
    "756316647793939709959"
  ]
}
```

**Example Code to Fetch** Open Order Id&#x73;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Order Ids API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770',
        marketId: 501
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getOpenOrderIds : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **17. Update Take Profit**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/updateTakeProfit`](https://perps-tradeapi.kanalabs.io/updateTakeProfit)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the take profit values will be updated.
  * **tradeSide** (Required) - The trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **newTakeProfitPrice** (Required) - The new take profit price to be set for the trade.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/updateTakeProfit?marketId=66&tradeSide=true&newTakeProfitPrice=6000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Update take profit payload built succesfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::update_take_profit",
    "functionArguments": [
      "501",
      "true",
      7590
    ],
    "typeArguments": []
  }
}
```

**Example Code to Update take profit price:**

The following TypeScript/Node.js script demonstrates how to call the Get Update Take Profit Price API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";


async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/updateTakeProfit';
    const params = {
        marketId: 501,
        tradeSide: true,
        newTakeProfitPrice: 6.7
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    const payloadData = res.data.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **18.** Get Account Aptos Balance

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAccountAptBalance`](https://perps-tradeapi.kanalabs.io/getAccountAptBalance)
* **Method**:\
  `GET`
* **Query Parameters**:
* **userAddress** (Required) - The address of the account whose balance will be&#x20;

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAccountAptBalance?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched Account Apt Balance Successfully",
  "data": 8.2344617
}
```

**Example Code to Fetch** Wallet Account Aptos Balance **Information:**

The following TypeScript/Node.js script demonstrates how to call the Get Wallet Account Aptos Balance API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getAccountAptBalance';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getWalletAccountAptosBalance : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **19. Update Stop Loss**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/updateStopLoss`](https://perps-tradeapi.kanalabs.io/updateStopLoss)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the take profit values will be updated.
  * **tradeSide** (Required) - The trade side:
    * `true` for the long side.
    * `false` for the short side.
  * newStopLossPrice (Required) - The new stop loss price to be set for the trade.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/updateStopLoss?marketId=66&tradeSide=true&newStopLossPrice=6000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Update stop loss payload built succesfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::update_stop_loss",
    "functionArguments": [
      "501",
      "true",
      7590
    ],
    "typeArguments": []
  }
}
```

**Example Code to Update stop loss price:**

The following TypeScript/Node.js script demonstrates how to call the Get Update Stop Loss Price API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";


async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/updateStopLoss';
    const params = {
        marketId: 501,
        tradeSide: true,
        newStopLossPrice: 4.6
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    const payloadData = res.data.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **20. Get Profile Address**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getProfileAddress`](https://perps-tradeapi.kanalabs.io/getProfileAddress)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `userAddress`(Required) - The address of the user to get the profile address.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getProfileAddress?userAddress=0xd01e3a233632a41463bd6d289e99e69e1b50815c7afff710e1c992659a8722f3
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Profile address fetched successfully",
  "data": "0x56ad3b670c9193414e5f3dbc1d9caf7a08368c4ab0b4b29c00ce13c463f6d934"
}
```

**Example Code to Fetch the profile address:**

The following TypeScript/Node.js script demonstrates how to call the Get profile address API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getProfileAddress';
    const params = {
        userAddress: "0x56ad3b670c9193414e5f3dbc1d9caf7a08368c4ab0b4b29c00ce13c463f6d934"
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getProfileAddress: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **21. Collapse position**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/collapsePosition`](https://perps-tradeapi.kanalabs.io/collapsePosition)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `marketId` (Required) - The ID of the market you want to collapse a position.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/collapsePosition?marketId=501
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "collapse position payload built succesfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::collapse_position",
    "functionArguments": [
      "624"
    ],
    "typeArguments": []
  }
}
```

**Example Code to collapse a position:**

The following TypeScript/Node.js script demonstrates how to call the collapse position API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
        process.env.APTOS_PRIVATEKEY || '',
        'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
        privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/collapsePosition';
    const params = {
        marketId: 624
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    const payloadData = res.data.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    console.log(`Submitted transaction: ${committedTxn.hash}`);
    const response = await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
    console.log("response", response.success);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **22.** Get All Trades

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAllTrades`](https://perps-tradeapi.kanalabs.io/getAllTrades)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market to retrieve all trades information.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAllTrades?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Recent trades fetched successfully",
  "data": [
    {
      "txn_version": 6297687196,
      "event_idx": 5,
      "emit_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "time": "2024-11-20T20:33:38.600241+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15951655917465922493754983",
      "maker_side": true,
      "market_id": 66,
      "price": 11879,
      "sequence_number_for_trade": 0,
      "size": 10000,
      "taker_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "taker_custodian_id": 28,
      "taker_order_id": "15951748150764039921729536",
      "taker_quote_fees_paid": 59395
    },
    {
      "txn_version": 6297687196,
      "event_idx": 4,
      "emit_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "time": "2024-11-20T20:33:38.600241+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15951655917465922493754983",
      "maker_side": true,
      "market_id": 66,
      "price": 11879,
      "sequence_number_for_trade": 0,
      "size": 10000,
      "taker_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "taker_custodian_id": 28,
      "taker_order_id": "15951748150764039921729536",
      "taker_quote_fees_paid": 59395
    }
  ]
}
```

**Example Code to Fetch** All trade&#x73;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Position API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getAllTrades';
    const params = {
        marketId: 501
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getAllTrades: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **23.** Get Account Apt Balance

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAccountAptBalance`](https://perps-tradeapi.kanalabs.io/getAccountAptBalance)\
  \
  **Method**:\
  `GET`
* **Query Parameters**:
  * `userAddress` (Required) - The wallet address for which the account balance is being fetched.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAccountAptBalance?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched wallet apt balance successfully",
  "data": 91.60
}
```

**Example Code to Fetch** Account Apt Balance **Information:**

The following TypeScript/Node.js script demonstrates how to call the Get Account Apt Balance API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getAccountAptBalance';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getAccountAptBalance: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## 24. Get Perpetual Asset Info

**Endpoint URL:**\
`https://perps-tradeapi.kanalabs.io/getPerpetualAssetsInfo`

**Method:**\
`GET`

**Query Parameters:**

* `marketId` (optional) – Numeric ID of the market to fetch.
* `baseName` (optional) – Name of the base asset (e.g., `"ETH"`, `"BTC"`).

**Note:** Either `marketId` or `baseName` must be provided. If neither is provided, the server will respond with a `400` error.

**Example Request:**

```
GET https://perps-tradeapi.kanalabs.io/getPerpetualAssetsInfo?marketId=1338
```

**Example Response:**

```json
{
  "success": true,
  "message": "Fetched market infos successfully",
  "data": [
    {
      "__variant__": "V1",
      "base_decimals": 8,
      "base_name": "APT/USDC",
      "counter": "9473",
      "creator": "0xb61d7b57333abf8ac036e752f19d0ba0c4baa5404db1cbf868c57dac3628f2bf",
      "fee_address": "0x7724a4a23b25b460abc2a5d9fe1fe3c47e2a0e10a156dd713a221f129579c388",
      "is_recognised": false,
      "last_updated": "1745235856",
      "lot_size": "100000",
      "maintenance_margin": "250",
      "market_address": "0xcfa0086c26787035de6b4a312875c7a70b2f9a29fa880d0cf633ef3dd0acd2c3",
      "market_id": "1338",
      "market_status": 1,
      "max_leverage": "20",
      "max_lots": "150000000",
      "max_position_value": "125000000000",
      "min_lots": "500",
      "quote_decimals": 6,
      "quote_precision": 3,
      "tick_size": "1"
    }
  ]
}
```

**Example Code:**

```ts
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getPerpetualAssetsInfo';
    const params = {
        marketId: '1338'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });

    console.log("Perpetual Asset Info:", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

***

### Get All Perpetual Market Assets

**Endpoint URL:**\
`https://perps-tradeapi.kanalabs.io/getPerpetualAssetsInfo/allMarkets`

**Method:**\
`GET`

**Description:**\
Fetches all available perpetual market asset information. This endpoint does not require any query parameters.

**Example Request:**

```
GET https://perps-tradeapi.kanalabs.io/getPerpetualAssetsInfo/allMarkets
```

**Example Response:**

```json
{
  "success": true,
  "message": "Fetched market infos successfully",
  "data": [
    {
      "__variant__": "V1",
      "base_decimals": 8,
      "base_name": "APT/USDC",
      "counter": "9473",
      "creator": "0xb61d7b57333abf8ac036e752f19d0ba0c4baa5404db1cbf868c57dac3628f2bf",
      "fee_address": "0x7724a4a23b25b460abc2a5d9fe1fe3c47e2a0e10a156dd713a221f129579c388",
      "is_recognised": false,
      "last_updated": "1745235856",
      "lot_size": "100000",
      "maintenance_margin": "250",
      "market_address": "0xcfa0086c26787035de6b4a312875c7a70b2f9a29fa880d0cf633ef3dd0acd2c3",
      "market_id": "1338",
      "market_status": 1,
      "max_leverage": "20",
      "max_lots": "150000000",
      "max_position_value": "125000000000",
      "min_lots": "500",
      "quote_decimals": 6,
      "quote_precision": 3,
      "tick_size": "1"
    },
    {
      "__variant__": "V1",
      "base_decimals": 8,
      "base_name": "BTC/USDC",
      "counter": "4813",
      "creator": "0xb61d7b57333abf8ac036e752f19d0ba0c4baa5404db1cbf868c57dac3628f2bf",
      "fee_address": "0x7724a4a23b25b460abc2a5d9fe1fe3c47e2a0e10a156dd713a221f129579c388",
      "is_recognised": false,
      "last_updated": "1745235864",
      "lot_size": "1000",
      "maintenance_margin": "250",
      "market_address": "0xc4de5894f6a97168998719c10f517572cbe10fe6911ca25004fbe87a88247ed4",
      "market_id": "1339",
      "market_status": 1,
      "max_leverage": "20",
      "max_lots": "6000000",
      "max_position_value": "125000000000",
      "min_lots": "10",
      "quote_decimals": 6,
      "quote_precision": 0,
      "tick_size": "10"
    },
    {
      "__variant__": "V1",
      "base_decimals": 8,
      "base_name": "ETH/USDC",
      "counter": "3377",
      "creator": "0xb61d7b57333abf8ac036e752f19d0ba0c4baa5404db1cbf868c57dac3628f2bf",
      "fee_address": "0x7724a4a23b25b460abc2a5d9fe1fe3c47e2a0e10a156dd713a221f129579c388",
      "is_recognised": false,
      "last_updated": "1745235871",
      "lot_size": "10000",
      "maintenance_margin": "250",
      "market_address": "0x9e173d4330b94718fd09c3d1d18b707f2713a1cd92e79403ee150429c3125718",
      "market_id": "1340",
      "market_status": 1,
      "max_leverage": "20",
      "max_lots": "10000000",
      "max_position_value": "125000000000",
      "min_lots": "10",
      "quote_decimals": 6,
      "quote_precision": 1,
      "tick_size": "10"
    }
  ]
}
```

**Example Code:**

```ts
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getPerpetualAssetsInfo/allMarkets';
    const res = await axios.get(baseURL, {
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });

    console.log("All Perpetual Markets Info:", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **25. Add Margin**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/addMargin`](https://perps-tradeapi.kanalabs.io/addMargin)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId (Required)** – The unique identifier of the market where the margin is being added.
  * **tradeSide** (Required) - Indicates the trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **amount (Required)** – The amount of additional margin to be added to the position.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/addMargin?marketId=1338&tradeSide=true&amount=1
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Add Margin payload built successfully",
  "data": {
    "function": "0x732f891290449af5e9369866537a51a8e7dc566791aec61a468223ed840b1eb4::perpetual_scripts::add_margin",
    "functionArguments": [
      "1338",
      "true",
      1000000
    ],
    "typeArguments": []
  }
}
```

**Example Code to add a margin:**

The following TypeScript/Node.js script demonstrates how to call the Get Add Margin API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
        process.env.APTOS_PRIVATEKEY || '',
        'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
        privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/addMargin';
    const params = {
        marketId: 1338,
        tradeSide: true,
        amount: 100
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    const payloadData = res.data.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    console.log(`Submitted transaction: ${committedTxn.hash}`);
    const response = await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
    console.log("response", response.success);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **26.** Get Net Profile Balance <a href="#id-26.-get-net-profile-balance" id="id-26.-get-net-profile-balance"></a>

This endpoint returns the net profile balance, which includes both the available balance in trading account and any pending balances from closed positions on all markets.

* **Endpoint URL**: [`https://perps-tradeapi.kanalabs.io/getNetProfileBalance`](https://perps-tradeapi.kanalabs.io/getNetProfileBalance)&#x20;
* **Method**: `GET`
* **Query Parameters**:
  * `userAddress` (Required) - The wallet address for which the account balance is being fetched.

**Example Request:**

```
GET https://perps-tradeapi.kanalabs.io/getNetProfileBalance?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Net Profile Balance fetched successfully",
  "data": 49443.432113
}
```

**Example Code to Fetch** Net Profile Balance **Information:**

The following TypeScript/Node.js script demonstrates how to call the Get Net Profile Balance API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getNetProfileBalance';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getNetProfileBalance: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **27. Settle Pnl** <a href="#id-27.-settle-pnl" id="id-27.-settle-pnl"></a>

This API returns a transaction payload used to manually (or automatically, on user interactions) refresh the user's position and settle the Pnl for a specific market, allowing the user to claim any unreleased Pnl.

* **Endpoint URL**: [`https://perps-tradeapi.kanalabs.io/settlePnl`](https://perps-tradeapi.kanalabs.io/settlePnl)
* **Method**: `GET`
* **Query Parameters**:
  * **marketId** (Required) -
  * userAddress (Required) -

**Example Request:**

```
GET https://perps-tradeapi.kanalabs.io/settlePnl?userAddress=0xd0ff27c8411015f386ffc464e3baaa12fca10f1bef1ec6af36c27ed96b65f6c6&marketId=1338=6000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Update position payload built succesfully",
  "data": {
    "function": "0x732f891290449af5e9369866537a51a8e7dc566791aec61a468223ed840b1eb4::perpetual_scripts::update_position",
    "functionArguments": [
      "0xd0ff27c8411015f386ffc464e3baaa12fca10f1bef1ec6af36c27ed96b65f6c6",
      "1338"
    ],
    "typeArguments": []
  }
}
```

**Example Code to Get Settle Pnl:**

The following TypeScript/Node.js script demonstrates how to call the Get Settle pnl API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";


async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/settlePnl';
    const params = {
        marketId: 1338,
        userAddress: "0xd0ff27c8411015f386ffc464e3baaa12fca10f1bef1ec6af36c27ed96b65f6c6"
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    const payloadData = res.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **28.** Get Trade History

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getTradeHistory`](https://perps-tradeapi.kanalabs.io/getOrderHistory)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve the trade history for.
  * **marketId** (optional) - The ID of the market to filter the trade history.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getTradeHistory?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched trade history successfully",
  "data": [
    {
    "address": "0x556c6465f9cedfe721d0a8537cf898cd2e5881ef89eb4a5a39df62e6ca439087",
    "leverage": 2,
    "market_id": "14",
    "timestamp": 1745998772,
    "size": "1",
    "order_type": 2,
    "price": "5.37",
    "order_value": "5.37",
    "pnl": "-0.0026850000000000000558927906",
    "fee": "0.0026850000000000000558927906",
    "trade_id": "55340232221128654862",
    "last_updated": 1749419915,
    "transaction_version": 2665614406,
    "entry_price": null,
    "order_id": "55340232221128654848"
  },
  {
    "address": "0x51f531abefc697845eabae4ba20c7cc26b1f849561bb016c4d90707c4ede1912",
    "leverage": 2,
    "market_id": "14",
    "timestamp": 1745998772,
    "size": "1",
    "order_type": 1,
    "price": "5.37",
    "order_value": "5.37",
    "pnl": "0",
    "fee": "0",
    "trade_id": "36893488147419103246",
    "last_updated": 1749419915,
    "transaction_version": 2665614406,
    "entry_price": null,
    "order_id": "36893628893497398522"
   }
  }
]
```

**Example Code to Fetch Trade History:**

The following TypeScript/Node.js script demonstrates how to call the Get Trade History API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getTradeHistory';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getTradeHistory: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **29.** Get Deposit and Withdraw History

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getDepositAndWithdrawHistory`](https://perps-tradeapi.kanalabs.io/getDepositAndWithdrawHistory)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve the order history

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getDepositAndWithdrawHistory?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770 Response:
```

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched deposit and withdraw history successfully",
  "data": [
    {
      "wallet_address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
      "address": "0xdf83209915c1b8087d8c2e3c1fe381f08fc7adbd55349a0bc9f4c906f8a76a82",
      "is_deposit": true,
      "timestamp": 1745236010,
      "amount": "10000",
      "last_updated": 1747110329,
      "transaction_version": 6694351099,
      "is_promoted": false,
      "promotion_id": null
    }
  ]
 }
```

**Example Code to Fetch Deposit and Withdraw History:**

The following Python script demonstrates how to call the Get **Deposit and Withdraw History** API using the requests library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getDepositAndWithdrawHistory';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getDepositAndWithdrawHistory: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **29.** Get Funding History

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getFundingHistory`](https://perps-tradeapi.kanalabs.io/getFundingHistory)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve the funding history.
  * **marketId** (optional) - The ID of the market to filter the funding  history.
  * offset (Optional) - The offset for paginating the results.\
    limit (Optional) - The maximum number of results to return.\
    order (Optional) - The sort order of the results. Accepts `asc` or `desc`.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getFundingHistory?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770 Response:
```

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched funding history successfully",
  "data": [
    {
      "address": "0xdf83209915c1b8087d8c2e3c1fe381f08fc7adbd55349a0bc9f4c906f8a76a82",
      "funding_amount": "0",
      "funding_rate": "0",
      "market_id": "1338",
      "funding_timestamp": 1748840400,
      "transaction_timestamp": 1748840428,
      "last_updated": 1748840431,
      "transaction_version": 6769626199,
      "trade_id": "83453070189462011512122",
      "size": "10",
      "leverage": 2,
      "trade_side": true
    }
  ]
}
```

**Example Code to Fetch** Funding **History:**

The following Python script demonstrates how to call the Get Funding **History** API using the requests library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getFundingHistory';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getFundingHistory: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **30.** Fetch Order Status By Id

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/fetchOrderStatusById`](https://perps-tradeapi.kanalabs.io/fetchOrderStatusById)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market associated with the order.
  * **orderId** (Required) - The unique identifier of the order to retrieve its status.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/fetchOrderStatusById?marketId=1338&orderId=33760566922324346434229328
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched final order status successfully",
  "data": {
    "address": "0x725c8b51b2c1b3d17336c48d75c56c19253f70e1de00e26c8138a29722d82da",
    "market_id": "1338",
    "leverage": 2,
    "order_type": 3,
    "timestamp": 1746216029,
    "is_market_order": false,
    "size": "0.218",
    "price": "5.20",
    "order_value": "1.13360",
    "status": "Cancelled",
    "order_id": "33760566922324346434229328",
    "trade_id": "172200355928078664336698",
    "last_updated": 1747229891,
    "transaction_version": 6704908886,
    "total_filled": "0.782",
    "remaining_size": "0.218",
    "total_trade_size": "1"
  }
}
```

#### **Possible Order Status Values:**

The `status` field will contain one of the following values:

| Status             | Meaning                                                                                                         |
| ------------------ | --------------------------------------------------------------------------------------------------------------- |
| `Open`             | Order is open                                                                                                   |
| `Filled`           | The order is fully filled. There will be no remaining open orders with the same order ID in the order history   |
| `Partially Filled` | The order is partially filled. There will be remaining open orders with the same order ID in the order history. |
| `Cancelled`        | The order has been cancelled                                                                                    |

**Example Code to Fetch** Order Status By I&#x64;**:**

The following Python script demonstrates how to call the Fetch Order Status By Id API using the requests library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/fetchOrderStatusById';
    const params = {
        marketId: 501,
        orderId : '85094831257134286508036
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("fetchOrderStatusById: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **31. Get Fills For Given Timestamp**&#x20;

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getFillsForGivenTimestamp`](https://perps-tradeapi.kanalabs.io/getFillsForGivenTimestamp)
* **Method**:\
  `GET`
* **Query Parameters**:

  userAddress (required)  \
  marketId (optional)  \
  offset (optional)  \
  limit (optional) —-> default 50  \
  order (optional) —-> asc or desc  \
  fromTimestamp (optional) --> In seconds (not milliseconds)  \
  toTimestamp (optional) --> In seconds (not milliseconds)

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getFillsForGivenTimestamp?marketId=1340&userAddress=0xb37f565528dc7dc1ddb376e930b62002ab61361d8bb9bfc2b4ace661fc6dbbfa&fromTimestamp=1751366416&toTimestamp=1751426951
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched fill trades for a given time range Successfully",
  "data": [
    {
      "address": "0x64e7e2d671526c2e092e5e7af94555c17c45d348400ae2a61424b6dbf338a9af",
      "leverage": 2,
      "market_id": "1340",
      "timestamp": 1751426951,
      "size": "1.0475",
      "order_type": 3,
      "price": "2449.50",
      "order_value": "2565.851250",
      "pnl": "0",
      "fee": "0",
      "trade_id": "245046548275157683668284",
      "last_updated": 1751426952,
      "transaction_version": 6798502405,
      "entry_price": null,
      "order_id": "112263471792402116758233007"
    },
    {
      "address": "0x64e7e2d671526c2e092e5e7af94555c17c45d348400ae2a61424b6dbf338a9af",
      "leverage": 2,
      "market_id": "1340",
      "timestamp": 1751366695,
      "size": "0.9669",
      "order_type": 4,
      "price": "2470.10",
      "order_value": "2388.339690",
      "pnl": "0",
      "fee": "0",
      "trade_id": "32982778403792678290748",
      "last_updated": 1751366696,
      "transaction_version": 6798038058,
      "entry_price": null,
      "order_id": "112263490233376000689856637"
    }
 ]
}
```

**Example Code to Fetch** Order Status By I&#x64;**:**

The following Python script demonstrates how to call the Fetch Order Status By Id API using the requests library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getFillsForGivenTimestamp';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770',
        fromTimestamp: 1751032488,
        toTimestamp: 1751032608
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getFillsForGivenTimestamp: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **32.** Get Positions From Contract

* **Endpoint URL**:

[`https://perps-tradeapi.kanalabs.io/getPositionsFromContract`](https://perps-tradeapi.kanalabs.io/getPositionsFromContract)

* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address of the user to view positions for.
  * **marketId** (optional) - The ID of the market to filter the positions.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getPositionsFromContract?marketId=66&userAddress=0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched positions from contract successfully",
  "data": [
    {
      "address": "0xef04eb57084fab57a42b7791d5e350240f890fc1c1cd12c2002cb93b86a7b564",
      "market_id": "14",
      "leverage": 10,
      "trade_side": true,
      "size": "1.76276",
      "available_order_size": "1.76276",
      "value": "9.53898961",
      "entry_price": "5.41139439884",
      "liq_price": "4.995",
      "margin": "0.953946706999278",
      "tp": "0",
      "sl": "0",
      "trade_id": "7667887236327365287084046"
    }
  ]
}
```

**Example Code to Fetch** Open Position from contrac&#x74;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Position From Contract API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getPositionsFromContract';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getPositionsFromContract: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **33.** Get Open Orders From Contract

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getOpenOrdersFromContract`](https://perps-tradeapi.kanalabs.io/getOpenOrdersFromContract)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve open orders for.
  * **marketId (Optional)** - The ID of the market to filter open orders.  // Optional

```
Note : order_type Explanation:

OPEN_LONG (1): Opens a new long position.
OPEN_SHORT (2): Opens a new short position.
INCREASE_LONG (3): Increases the size of an existing long position.
INCREASE_SHORT (4): Increases the size of an existing short position.
DECREASE_LONG (5): Reduces the size of an existing long position.
DECREASE_SHORT (6): Reduces the size of an existing short position.
CLOSE_LONG (7): Closes an existing long position.
CLOSE_SHORT (8): Closes an existing short position.
```

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOpenOrdersFromContract?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched open orders from contract successfully",
  "data": [
    {
      "address": "0xef04eb57084fab57a42b7791d5e350240f890fc1c1cd12c2002cb93b86a7b564",
      "market_id": "14",
      "leverage": 10,
      "order_type": 3,
      "price": "5.459",
      "total_size": "1.69717",
      "remaining_size": "1.69717",
      "order_value": "9.26485103",
      "order_id": "220873897950436224634197331",
      "trade_id": "7667887236327365287084046"
    },
    {
      "address": "0xef04eb57084fab57a42b7791d5e350240f890fc1c1cd12c2002cb93b86a7b564",
      "market_id": "14",
      "leverage": 10,
      "order_type": 3,
      "price": "5.448",
      "total_size": "1.69717",
      "remaining_size": "1.69717",
      "order_value": "9.24618216",
      "order_id": "220873916394787984380007752",
      "trade_id": "7667887236327365287084046"
    }
   ]
} 
```

**Example Code to Fetch** Open Orders From Contarc&#x74;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Orders From Contract API using the `axios` library.

```typescript
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getOpenOrdersFromContract';
    const params = {
        userAddress: '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getOpenOrdersFromContract: ", res.data);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```


# Kana Perps Python Websocket API

### **Important Note:**

For all the Websocket endpoints below, pass your profile address.

To track your transactions on-chain (e.g., via **Aptos Explorer** or **Aptos Scan**), you must use your **profile address**, as all on-chain trades are executed using this profile address.

To obtain your profile address, use the `/getProfileAddress` endpoint and provide your wallet address as the `userAddress` parameter.

### How to Fetch the Profile Address:

**Example endpoint:**\
<https://perps-tradeapi.kanalabs.io/getProfileAddress?userAddress=0xd01e3a233632a41463bd6d289e99e69e1b50815c7afff710e1c992659a8722f3>\
\
**Example code:**\
[https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/kana-perps-python-rest-api#id-20.-](https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/kana-perps-typescript-rest-api#id-19.-update-stop-loss)get-profile-address

### Testnet Supported Markets

<table data-header-hidden><thead><tr><th></th><th width="282"></th><th></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td><td><strong>Description</strong></td></tr><tr><td>APT-USD</td><td>1338</td><td>Aptos-based trading market.</td></tr><tr><td>BTC-USD</td><td>1339</td><td>Bitcoin-based trading market.</td></tr><tr><td>ETH-USD</td><td>1340</td><td>Ethereum-based trading market.</td></tr><tr><td>SOL-USD</td><td>2387</td><td>Solana-based trading market.</td></tr></tbody></table>

### Mainnet Supported Markets

<table data-header-hidden><thead><tr><th></th><th width="282"></th><th></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td><td><strong>Description</strong></td></tr><tr><td>APT-USD</td><td>14</td><td>Aptos-based trading market.</td></tr><tr><td>BTC-USD</td><td>15</td><td>Bitcoin-based trading market.</td></tr><tr><td>ETH-USD</td><td>16</td><td>Ethereum-based trading market.</td></tr><tr><td>SOL-USD</td><td>31</td><td>Solana-based trading market.</td></tr></tbody></table>

**WebSocket URL:**

### ✅ <mark style="color:red;">**Testnet WebSocket URL**</mark>

```typescript
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

### ✅ <mark style="color:red;">**Mainnet WebSocket URL**</mark>

```typescript
wss://perpetuals-indexer-ws.kana.trade/ws/
```

### **Important Note: Profile Address Required**

🔹 You **must** pass your **profile address** for WebSocket endpoints.\
🔹 To get your **profile address**, use the `/getProfileAddress` endpoint.

#### **Profile Address API:**

&#x20;**Endpoint:**

```
https://perps-tradeapi.kanalabs.io/getProfileAddress
```

**Example Request:**

```
https://perps-tradeapi.kanalabs.io/getProfileAddress?userAddress=0xd01e3a233632a41463bd6d289e99e69e1b50815c7afff710e1c992659a8722f3
```

&#x20;**Input Parameter:**

* `userAddress` (your wallet address)

&#x20;**Response Example:**

```typescript
{
  success: true,
  message: 'Profile address fetched successfully',
  data: '0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e'
}
```

#### WebSocket Client Documentation

**Installation:**

1. **Install Dependencies**: You will need the `websocket-client` library. Install it using pip:

```python
pip install websocket-client
```

### 1. WebSocket Client for Subscribing to Position Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "positions",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is `positions` in this case.
* **address**: The address to track for position updates.

**Example Response:**

After subscribing, you will receive position updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "positions", "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"}
[client] Received message: {"data":[{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","entry_price":"6050","is_long":false,"last_updated":"1739788459","leverage":2,"liq_price":"8853.658536585366","margin":"3025000","market_id":"396","size":"1000","sl":null,"tp":null,"trade_id":"16509835945970048696716","value":"6050000"}],"message":"positions"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to position updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/'

# Address to subscribe to
address = 'your_address'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'positions',
        'address': address,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 2. WebSocket Client for Subscribing to Order Fills Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "trade_history",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is trade\_history in this case.
* **address**: The address to track for order fills updates.

**Example Response:**

After subscribing, you will receive order fills updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "trade_history", "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"}
[client] Received message: {"data":[{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","fee":"3025","last_updated":"1739788459","market_id":"396","order_type":2,"pnl":"0","price":"6050","size":"1000","timestamp":"1739788459","trade_id":"16509835945970048696716"},"message":"trade_history"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to order fills updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/'

# Address to subscribe to
address = 'your_address'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'trade_history',
        'address': address,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 3. WebSocket Client for Subscribing to Open Orders Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "open_orders",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is open\_orders in this case.
* **address**: The address to track for open orders updates.

**Example Response:**

After subscribing, you will receive open orders updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "open_orders", "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"}
[client] Received message: {"data":[],"message":"open_orders"}
[client] Received message: {"data":[{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","last_updated":"1739790733","leverage":2,"market_id":"396","order_id":"12907057702855018828273522","order_type":1,"order_value":"6002000","price":"6002","remaining_size":"1000","timestamp":"1739790733","total_size":"1000","trade_id":"16528282690043758248332"}],"message":"open_orders"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to open orders updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/'

# Address to subscribe to
address = 'your_address'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'open_orders',
        'address': address,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 4. WebSocket Client for Subscribing to Order history Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "order_history",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is order\_history in this case.
* **address**: The address to track for order history updates.

**Example Response:**

After subscribing, you will receive order history updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "order_history", "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"}
[client] Received message: {"data":[{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","is_market_order":false,"last_updated":"1739790733","leverage":2,"market_id":"396","order_id":"12907057702855018828273522","order_type":1,"order_value":"6002000","price":"6002","size":"1000","status":"Open","timestamp":"1739790733","trade_id":"16528282690043758248332"},{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","is_market_order":false,"last_updated":"1739790700","leverage":2,"market_id":"396","order_id":"12906965467445688751095808","order_type":4,"order_value":"6002000","price":"6002","size":"1000","status":"Filled","timestamp":"1739790700","trade_id":"16509835945970048696716"}],"message":"order_history"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to order history updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/'

# Address to subscribe to
address = 'your_address'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'order_history',
        'address': address,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 5. WebSocket Client for Subscribing to Order Book Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "orderbook",
  "market_id": "1338"
}
```

* **topic**: The topic to subscribe to, which is orderbook in this case.
* **address**: The address to track for order book updates.

**Example Response:**

After subscribing, you will receive order book updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "orderbook", "market_id": "1338"}
[client] Received message: {"data":[{"is_ask":true,"last_updated":"1739790988","market_id":"396","price":"6036","size":"169320"},{"is_ask":true,"last_updated":"1739790988","market_id":"396","price":"6037","size":"253735"},{"is_ask":true,"last_updated":"1739790988","market_id":"396","price":"6040","size":"230485"},{"is_ask":true,"last_updated":"1739790996","market_id":"396","price":"6044","size":"255685"},{"is_ask":true,"last_updated":"1739790996","market_id":"396","price":"6051","size":"264082"},{"is_ask":true,"last_updated":"1739790990","market_id":"396","price":"6053","size":"235088"},{"is_ask":true,"last_updated":"1739790996","market_id":"396","price":"6057","size":"230868"},{"is_ask":true,"last_updated":"1739790990","market_id":"396","price":"6059","size":"487477"},{"is_ask":true,"last_updated":"1739758360","market_id":"396","price":"8000","size":"500"},{"is_ask":false,"last_updated":"1739790988","market_id":"396","price":"6031","size":"174998"},{"is_ask":false,"last_updated":"1739790988","market_id":"396","price":"6027","size":"225183"},{"is_ask":false,"last_updated":"1739790988","market_id":"396","price":"6024","size":"244770"},{"is_ask":false,"last_updated":"1739790996","market_id":"396","price":"6019","size":"238312"},{"is_ask":false,"last_updated":"1739790987","market_id":"396","price":"6018","size":"260393"},{"is_ask":false,"last_updated":"1739790996","market_id":"396","price":"6014","size":"267821"},{"is_ask":false,"last_updated":"1739790996","market_id":"396","price":"6011","size":"234869"},{"is_ask":false,"last_updated":"1739790990","market_id":"396","price":"6006","size":"447877"},{"is_ask":false,"last_updated":"1739790990","market_id":"396","price":"6002","size":"1000"},{"is_ask":false,"last_updated":"1739779575","market_id":"396","price":"5800","size":"103303"}],"message":"orderbook"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to order book updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/'

# Address to subscribe to
market_id= 'your_market_id'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'orderbook',
        'market_id': market_id,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()    

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 6. WebSocket Client for Subscribing to Recent Trades Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "recent_trades",
  "market_id": "1338"
}
```

* **topic**: The topic to subscribe to, which is recent\_trades in this case.
* **address**: The address to track for recent trades updates.

**Example Response:**

After subscribing, you will receive recent trades updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "recent_trades", "market_id": "1338"}
[client] Received message: {"data":[{"address":"0x73e73911c0771e4d58f17aea3d0c70980ca2bae32c665b37101d1a18f4ef60f1","fee":"0","last_updated":1746177751,"leverage":2,"market_id":"1338","order_type":1,"order_value":"65.393818","pnl":"0","price":"5.518","size":"11.851","timestamp":1746177750,"trade_id":"176590681017621537621306","transaction_version":6704413443},{"address":"0x85a0d7c3e1f5e243b80055b249d6e4cc4b2db5f599fa7a27b05850af8eccffdd","fee":"0.0326969090000000006806411505","last_updated":1746177751,"leverage":2,"market_id":"1338","order_type":7,"order_value":"65.393818","pnl":"-0.0682499090000000006806411505","price":"5.518","size":"11.851","timestamp":1746177750,"trade_id":"176609127761695247172922","transaction_version":6704413443}]}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to recent trades updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/'

# Address to subscribe to
market_id= '1338'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'recent_trades',
        'market_id': market_id,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()    

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 7. WebSocket Client for Subscribing to Live Funding Rate Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "live_funding_rate"
}
```

* **topic**: The topic to subscribe to, which is live\_funding\_rate in this case.

**Example Response:**

After subscribing, you will receive live funding rate updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "live_funding_rate"}
[client] Received message: {"data":[{"funding_rate":"0","funding_timestamp":0,"last_updated":1747382402,"market_id":"14","transaction_timestamp":1747382400,"transaction_version":2726355750},{"funding_rate":"0","funding_timestamp":0,"last_updated":1747382402,"market_id":"16","transaction_timestamp":1747382400,"transaction_version":2726355754},{"funding_rate":"0","funding_timestamp":0,"last_updated":1747382402,"market_id":"15","transaction_timestamp":1747382400,"transaction_version":2726355752}],"message":"live_funding_rate"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to live funding rate updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws.kana.trade/ws/'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'live_funding_rate',
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()    

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```


# Kana Perps Python REST API

### **Important Note:**

For all the API endpoints below, pass your wallet address as the `userAddress` parameter.

To track your transactions on-chain (e.g., via **Aptos Explorer** or **Aptos Scan**), you must use your **profile address**, as all on-chain trades are executed using this profile address.

To obtain your profile address, use the `/getProfileAddress` endpoint and provide your wallet address as the `userAddress` parameter.

### How to Fetch the Profile Address:

**Example endpoint:**\
<https://perps-tradeapi.kanalabs.io/getProfileAddress?userAddress=0xd01e3a233632a41463bd6d289e99e69e1b50815c7afff710e1c992659a8722f3>\
\
**Example code:**\
[https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/kana-perps-python-rest-api#id-20.-](https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/kana-perps-typescript-rest-api#id-19.-update-stop-loss)get-profile-address

## ✅ <mark style="color:red;">**Testnet API  Endpoint URL**</mark>

```typescript
https://perps-tradeapi.kanalabs.io
```

### ✅ <mark style="color:red;">**Mainnet API Endpoint URL**</mark>

```typescript
https://perps-tradeapi.kana.trade
```

### <mark style="color:yellow;">Please ensure that the correct network is used</mark>: for Testnet, set `NODE_URL = "https://api.testnet.aptoslabs.com/v1"`  and  for Mainnet, set `NODE_URL = "https://api.mainnet.aptoslabs.com/v1"`

## **1. Get Market Info**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getMarketInfo`](#id-1.-get-market-info)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `marketId` (Required) - The ID of the market you want information about.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getMarketInfo?marketId=501
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Market information fetched successfully",
  "data": [
    {
    "__variant__": "V1",
    "base_decimals": 8,
    "base_name": "APT/USDC",
    "counter": "0",
    "creator": "0xb61d7b57333abf8ac036e752f19d0ba0c4baa5404db1cbf868c57dac3628f2bf",
    "custodian_id": "75",
    "fee_address": "0x7724a4a23b25b460abc2a5d9fe1fe3c47e2a0e10a156dd713a221f129579c388",
    "is_recognised": false,
    "lot_size": "100000",
    "maintenance_margin": "250",
    "market_address": "0xcfa0086c26787035de6b4a312875c7a70b2f9a29fa880d0cf633ef3dd0acd2c3",
    "market_id": "1338",
    "market_status": 1,
    "max_leverage": "20",
    "max_lots": "150000000",
    "max_position_value": "125000000",
    "min_lots": "500",
    "quote_decimals": 6,
    "quote_precision": 3,
    "tick_size": "1",
    "timestamp": "1745079291",
    "underwriter_id": "73"
  }
  ]
}
```

**Example Code to Fetch Market Information:**

The following Python script demonstrates how to call the Get Market Info API using the requests library.

```python
import requests
import os
from dotenv import load_dotenv
load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getMarketInfo'
        params = {
            'marketId': 501
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_market_info = response.json()
        print("getMarketInfo: ", get_market_info)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **2.** Get Wallet Account Balance

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getWalletAccountBalance`](https://perps-tradeapi.kanalabs.io/getWalletAccountBalance)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `userAddress` (Required) - The wallet address for which the account balance is being fetched.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getWalletAccountBalance?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched wallet account balance successfully",
  "data": 16391.60
}
```

**Example Code to Fetch** Wallet Account Balance **Information:**

The following Python script demonstrates how to call the Get Wallet Account Balance API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv
load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getWalletAccountBalance'
        params = {
            'userAddress': '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_wallet_account_balance = response.json()
        print("getWalletAccountBalance: ", get_wallet_account_balance)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **3.** Get Profile Balance Snapshot

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getProfileBalanceSnapshot`](https://perps-tradeapi.kanalabs.io/getProfileBalanceSnpashot)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `userAddress` (Required) - The wallet address for which the account balance is being fetched.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getProfileBalanceSnapshot?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Profile balance snapshot fetched successfully",
  "data": 44.321972
}
```

**Example Code to Fetch** Trading Account Balance **Information:**

The following Python script demonstrates how to call the Get Trading Account Balance API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv
load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getProfileBalanceSnapshot'
        params = {
            'userAddress': '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_trading_account_balance = response.json()
        print("getTradingAccountBalance: ", get_trading_account_balance)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **4. Deposit**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/deposit`](https://perps-tradeapi.kanalabs.io/deposit)
* **Method**:\
  `GET`
* **Query Parameters:**
  * `amount` (Required) - The amount of the quote coin to deposit.
  * `userAddress` (Required) - The address of the user making the deposit.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/deposit?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&amount=50000000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Deposit payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::deposit",
    "functionArguments": [
      "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
      50000000
    ],
    "typeArguments": []
  }
}
```

**Example Code to Depsoit a quote coin:**

The following Python script demonstrates how to call the Get Deposit API using the requests library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.account_address import AccountAddress  # Import this
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List
load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/deposit"
    PARAMS = {
        "userAddress":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
        "amount": 50
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)
    
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            AccountAddress.from_str(payload_data["functionArguments"][0]),  
            int(payload_data["functionArguments"][1]),
        ]
        payload_data["argumentTypes"] = [Serializer.struct, Serializer.u64]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **5. Withdraw Specific Market**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket`](https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `marketId` (Required) - The ID of the market you want to withdraw.
  * `amount` (Required) - The amount of the quote coin to withdraw.
  * `userAddress` (Required) - The address of the user making the withdraw.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket?marketId=501&userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&amount=50
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Withdraw specific market payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::withdraw_specific_market",
    "functionArguments": [
      "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
      "501",
      50000000
    ],
    "typeArguments": []
  }
}
```

**Example Code to Withdraw a quote coin:**

The following Python script demonstrates how to call the Get Withdraw API using the requests library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.account_address import AccountAddress  # Import this
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List
load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket"
    PARAMS = {
        "userAddress": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
        "marketId": 501,
        "amount": 50
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)
    
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            AccountAddress.from_str(payload_data["functionArguments"][0]),  
            int(payload_data["functionArguments"][1]),
            int(payload_data["functionArguments"][1]),
        ]
        payload_data["argumentTypes"] = [Serializer.struct, Serializer.u64, Serializer.u64]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **6. Place Limit Order**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/placeLimitOrder`](https://perps-tradeapi.kanalabs.io/placeLimitOrder)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market where the limit order will be placed.
  * **tradeSide** (Required) - Indicates the trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **direction** (Required) - Indicates the direction of the trade:
    * `false` to open a position.
    * `true` to close a position.
  * **size** (Required) - The size of the order.
  * **price** (Required) - The price at which the order is to be placed.
  * **leverage** (Required) - The leverage to be used for the order.
  * **restriction**  - Specifies the type of order restriction. It is an optional parameter with a default value of `0`.\
    Possible values are:
    * `0` - `NO_RESTRICTION`: Optionally fill as a taker, then post to the book as a maker.
    * `1` - `FILL_OR_ABORT`: Abort if any size posts as a maker (only fill).
    * `3` - `POST_OR_ABORT`: Abort if any size fills as a taker (only post).
    * If `restriction` is not provided, it defaults to `0`. It can either be a number or left undefined.
  * **takeProfit** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
  * **stopLoss** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/placeLimitOrder/?marketId=501&tradeSide=true&direction=false&size=10000&price=3000&leverage=3
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Limit Order payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::place_limit_order",
    "functionArguments": [
      "501",
      "true",
      "false",
      1000000,
      8000000,
      "5",
      0,
      0,
      0
    ],
    "typeArguments": []
  }
}
```

**Example Code to Place a limit order:**

The following Python script demonstrates how to call the Get Place Limit Order API using the requests library.

```python
import asyncio
import os
import requests
from dotenv import load_dotenv
from typing import List
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag

load_dotenv()

class AptosTransactionHandler:
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List, types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            module, function_id = "::".join(payload["function"].split("::")[:-1]), payload["function"].split("::")[-1]
            function_arguments = self.create_transaction_function_arguments(payload["functionArguments"], payload["argumentTypes"])
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            
            entry_function = EntryFunction.natural(module=module, function=function_id, ty_args=type_arguments, args=function_arguments)
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction = await self.rest_client.create_bcs_signed_transaction(self.account, transaction_payload)
            txn_hash = await self.rest_client.submit_bcs_transaction(signed_transaction)
            await self.rest_client.wait_for_transaction(txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')

    if not private_key_hex:
        print("Error: APTOS_PRIVATEKEY is missing in .env file.")
        return

    account = Account.load_key(bytes.fromhex(private_key_hex[2:] if private_key_hex.startswith("0x") else private_key_hex))
    rest_client = RestClient(NODE_URL)

    API_URL = "https://perps-tradeapi.kanalabs.io/placeLimitOrder"
    PARAMS = {"marketId": 501, "tradeSide": True, "direction": False, "size": 2, "price": 7, "leverage": 2}
    HEADERS = {"x-api-key": os.getenv('API_KEY')}

    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)

    if not payload_data:
        print("Failed to fetch payload data.")
        return

    try:
        payload_data["functionArguments"] = [
            int(payload_data["functionArguments"][0]),
            payload_data["functionArguments"][1].lower() == "true",
            payload_data["functionArguments"][2].lower() == "true",
            *map(int, payload_data["functionArguments"][3:])
        ]

        payload_data["argumentTypes"] = [
            Serializer.u64, Serializer.bool, Serializer.bool, Serializer.u64,
            Serializer.u64, Serializer.u64, Serializer.u8, Serializer.u64, Serializer.u64
        ]

        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Hash: {txn_hash}")

    except Exception as e:
        print(f"Transaction process error: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **7. Place Market Order**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/placeMarketOrder`](https://perps-tradeapi.kanalabs.io/placeMarketOrder)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market where the limit order will be placed.
  * **tradeSide** (Required) - Indicates the trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **direction** (Required) - Indicates the direction of the trade:
    * `false` to open a position.
    * `true` to close a position.
  * **size** (Required) - The size of the order.
  * **leverage** (Required) - The leverage to be used for the order.
  * **takeProfit** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
  * **stopLoss** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/placeMarketOrder?marketId=66&tradeSide=false&direction=true&size=1000&leverage=20
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Market Order payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::place_market_order",
    "functionArguments": [
      "501",
      "true",
      "false",
      1000000,
      "5",
      0,
      0
    ],
    "typeArguments": []
  }
}
```

**Example Code to Place a market order:**

The following Python script demonstrates how to call the Get Place Market Order API using the requests library.

```python
import asyncio
import os
import requests
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag
from dotenv import load_dotenv
from typing import List

load_dotenv()

class AptosTransactionHandler:
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url: str, params: dict, headers: dict) -> dict | None:
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            module, function_id = "::".join(payload["function"].split("::")[:-1]), payload["function"].split("::")[-1]
            type_arguments = [TypeTag(StructTag.from_str(arg)) for arg in payload["typeArguments"]]
            function_arguments = [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]

            return TransactionPayload(payload=EntryFunction.natural(module, function_id, type_arguments, function_arguments))
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_txn = await self.rest_client.create_bcs_signed_transaction(sender=self.account, payload=transaction_payload)
            txn_hash = await self.rest_client.submit_bcs_transaction(signed_transaction=signed_txn)
            await self.rest_client.wait_for_transaction(txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    API_URL = "https://perps-tradeapi.kanalabs.io/placeMarketOrder"
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    PARAMS = {"marketId": 501, "tradeSide": True, "direction": False, "size": 2, "leverage": 2}

    rest_client = RestClient(NODE_URL)
    private_key = os.getenv('APTOS_PRIVATEKEY', "").lstrip("0x")
    
    if not private_key:
        print("Error: APTOS_PRIVATEKEY is missing in .env file.")
        return

    account = Account.load_key(bytes.fromhex(private_key))
    handler = AptosTransactionHandler(rest_client, account)
    
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)
    if not payload_data:
        print("Failed to fetch payload data.")
        return

    try:
        payload_data["functionArguments"] = [
            int(payload_data["functionArguments"][0]),
            payload_data["functionArguments"][1].lower() == "true",
            payload_data["functionArguments"][2].lower() == "true",
            *map(int, payload_data["functionArguments"][3:])
        ]

        payload_data["argumentTypes"] = [Serializer.u64, Serializer.bool, Serializer.bool] + [Serializer.u64] * (len(payload_data["functionArguments"]) - 3)

        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")

        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Hash: {txn_hash}")

    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())

```

## **8. Cancel Multiple Orders**

* **Endpoint URL**:\
  [`htps://perps-tradeapi.kanalabs.io/cancelMultipleOrders`](#api-overview)
* **Method**:\
  `POST`
* **Request Body**:
  * **marketId**: The ID of the market for which the orders will be canceled.
  * cancelOrderIds: A list of order IDs to cancel.
  * orderSides: The sides of the orders to cancel (true for long, false for short).

**Example Request:**

```json
{
  "marketId": 501,
  "cancelOrderIds": ["1077898597726583798162207", "1077880153515406921884445"],
  "orderSides": [true, false]
}
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Cancel Multiple Orders payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::cancel_multiple_orders",
    "functionArguments": [
      501,
      [
        "1077898597726583798162207",
        "1077880153515406921884445"
      ],
      [
        true,
        false
      ]
    ],
    "typeArguments": []
  }
}
```

**Example Code to Cancel multiple orders:**

The following Python script demonstrates how to call the Post Cancel Multiple Orders API using the requests library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List

load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, json_data, headers):
        try:
            response = requests.post(api_url, json=json_data, headers=headers)
            response.raise_for_status()
            payload_data = response.json().get("data")
            if payload_data is None:
                print("No data returned from API.")
                return {}

            # Convert order ID from float to integer
            payload_data["functionArguments"][1] = [int(x) for x in payload_data["functionArguments"][1]]

            return payload_data
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        try:
            return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]
        except Exception as e:
            print(f"Error creating transaction arguments: {e}")
            raise

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    
    API_URL = "https://perps-tradeapi.kanalabs.io/cancelMultipleOrders"
    BODY = {
        "marketId": 501,
        "cancelOrderIds": ["85722020555623231393816"], # pls ensure cancelOrderIds given in string
        "orderSides": [True]
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, BODY, HEADERS)
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["argumentTypes"] = [
            Serializer.u64,
            Serializer.sequence_serializer(Serializer.u128),
            Serializer.sequence_serializer(Serializer.bool)
        ]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **8. Place Multiple Orders**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/placeMultipleOrders`](https://perps-tradeapi.kanalabs.io/placeMultipleOrders)
* **Method**:\
  `POST`

Request Body :

* marketId (Required) - The ID of the market where the orders will be placed.
* orderTypes (Required) - An array of order types for each order:
  * true for limit orders.
  * false for market orders.
* tradeSides (Required) - An array indicating the trade sides for each order:
  * true for long positions.
  * false for short positions.
* directions (Required) - An array indicating the direction of each trade:
  * false to open a position.
  * true to close a position.
* sizes (Required) - An array of sizes for each order.
* leverages (Required) - An array of leverages for each order.
* prices (Required) - An array of prices at which each order is to be placed.
* **restriction**  - Specifies the type of order restriction. It is an optional parameter with a default value of `0`.\
  Possible values are:
  * `0` - `NO_RESTRICTION`: Optionally fill as a taker, then post to the book as a maker.
  * `1` - `FILL_OR_ABORT`: Abort if any size posts as a maker (only fill).
  * `3` - `POST_OR_ABORT`: Abort if any size fills as a taker (only post).
  * If `restriction` is not provided, it defaults to `0`. It can either be a number or left undefined.
* **takeProfits** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
* **stopLosses** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```json
{
  "marketId": 501,
  "orderTypes": [true, true],
  "tradeSides": [true, true],
  "directions": [true, true],
  "sizes": [1000, 1000],
  "prices": [1000, 1000],
  "leverages": [2, 2]
}
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Multiple Orders payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::place_multiple_orders",
    "functionArguments": [
      501,
      [
        true,
        true
      ],
      [
        true,
        true
      ],
      [
        true,
        true
      ],
      [
        1000,
        1000
      ],
      [
        4670,
        6780
      ],
      [
        2,
        2
      ],
      [
        0,
        0
      ],
      [
        4600
      ],
      [
        0,
        0
      ]
    ],
    "typeArguments": []
  }
}
```

**Example Code to Place a multiple orders:**

The following Python script demonstrates how to call the Get Place Multiple Orders API using the requests library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List

load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url: str, json_data: dict, headers: dict) -> dict:
     try:
        response = requests.post(api_url, json=json_data, headers=headers)
        response.raise_for_status()
        payload_data = response.json().get("data")
        if payload_data is None:
            print("No data returned from API.")
            return {}
        # Dynamically ensure the length matches the sizes provided
        payload_data["takeProfits"] = payload_data.get("takeProfits", [0] * len(json_data["sizes"]))
        payload_data["stopLosses"] = payload_data.get("stopLosses", [0] * len(json_data["sizes"]))
        payload_data["restrictions"] = payload_data.get("restrictions", [0] * len(json_data["sizes"]))
        return payload_data
     except requests.exceptions.RequestException as e:
        print(f"Error fetching payload: {e}")
        return {}

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        try:
            return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]
        except Exception as e:
            print(f"Error creating transaction arguments: {e}")
            raise

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/placeMultipleOrders"
    BODY = {
        "marketId": 501,
        "orderTypes": [True],
        "tradeSides": [True],
        "directions": [False],
        "sizes": [1.9],
        "prices": [4.12],
        "leverages": [2]
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, BODY, HEADERS)
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["argumentTypes"] = [
            Serializer.u64,
            Serializer.sequence_serializer(Serializer.bool),
            Serializer.sequence_serializer(Serializer.bool),
            Serializer.sequence_serializer(Serializer.bool),
            Serializer.sequence_serializer(Serializer.u64),
            Serializer.sequence_serializer(Serializer.u64),
            Serializer.sequence_serializer(Serializer.u64),
            Serializer.sequence_serializer(Serializer.u8),
            Serializer.sequence_serializer(Serializer.u64),
            Serializer.sequence_serializer(Serializer.u64)
        ]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **9. Cancel and Place Multiple Orders**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/cancelAndPlaceMultipleOrders`](https://perps-tradeapi.kanalabs.io/cancelAndPlaceMultipleOrders)
* **Method**:\
  `POST`

Request Body :

* marketId (Required) - The ID of the market where the orders will be placed.
* cancelOrderIds **(Required)** - An array of strings representing the IDs of the orders to be canceled.
* orderSides **(Required)** - An array indicating the sides of the orders being canceled:
  * `true` for long sides.
  * `false` for short sides.
* orderTypes (Required) - An array of order types for each order:
  * true for limit orders.
  * false for market orders.
* tradeSides (Required) - An array indicating the trade sides for each order:
  * true for long positions.
  * false for short positions.
* directions (Required) - An array indicating the direction of each trade:
  * false to open a position.
  * true to close a position.
* sizes (Required) - An array of sizes for each order.
* leverages (Required) - An array of leverages for each order.
* prices (Required) - An array of prices at which each order is to be placed.
* **restriction**  - Specifies the type of order restriction. It is an optional parameter with a default value of `0`.\
  Possible values are:
  * `0` - `NO_RESTRICTION`: Optionally fill as a taker, then post to the book as a maker.
  * `1` - `FILL_OR_ABORT`: Abort if any size posts as a maker (only fill).
  * `3` - `POST_OR_ABORT`: Abort if any size fills as a taker (only post).
  * If `restriction` is not provided, it defaults to `0`. It can either be a number or left undefined
* **takeProfits** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
* **stopLosses** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```json
{
  "marketId": 501,
  "cancelOrderIds": ["23434565434567", "454345665456"],
  "orderSides": [true, true],
  "orderTypes": [true, true],
  "tradeSides": [true, false],
  "directions": [true, true],
  "sizes": [1000, 2000],
  "prices": [5000, 6000],
  "leverages": [2, 2]
}
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Cancel and place multiple Orders payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::cancel_and_place_multiple_orders",
    "functionArguments": [
      501,
      [
        "23434565434567",
        "454345665456"
      ],
      [
        "true",
        "true"
      ],
      [
        true,
        true
      ],
      [
        true,
        false
      ],
      [
        true,
        true
      ],
      [
        1000,
        2000
      ],
      [
        5000,
        6000
      ],
      [
        2,
        2
      ],
      [
        0,
        0
      ],
      [
        0,
        0
      ],
      [
        0,
        0
      ]
    ],
    "typeArguments": []
  }
}
```

**Example Code to cancel and Place a multiple orders:**

The following TypeScript/Node.js script demonstrates how to call the Get Cancel And Place Multiple Orders API using the `axios` library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List

load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url: str, json_data: dict, headers: dict) -> dict:
        try:
            response = requests.post(api_url, json=json_data, headers=headers)
            response.raise_for_status()
            payload_data = response.json().get("data")
            if payload_data is None:
                print("No data returned from API.")
                return {}

            # Ensure correct integer representation for order IDs
            payload_data["takeProfits"] = payload_data.get("takeProfits", [0] * len(json_data["sizes"]))
            payload_data["stopLosses"] = payload_data.get("stopLosses", [0] * len(json_data["sizes"]))
            payload_data["restrictions"] = payload_data.get("restrictions", [0] * len(json_data["sizes"]))

            # Convert order ID lists from float to integer
            payload_data["functionArguments"][1] = [int(x) for x in payload_data["functionArguments"][1]]

            return payload_data
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return {}

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        try:
            return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]
        except Exception as e:
            print(f"Error creating transaction arguments: {e}")
            raise

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]

            if "argumentTypes" not in payload:
                raise KeyError("'argumentTypes' missing in payload.")

            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )

            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]

            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)

    API_URL = "https://perps-tradeapi.kanalabs.io/cancelAndPlaceMultipleOrders"
    BODY = {
        "marketId": 501,
        "cancelOrderIds": ["45877054622524009092208"],  # Ensure orderId given as string
        "orderSides": [True],
        "orderTypes": [True],
        "tradeSides": [True],
        "directions": [False],
        "sizes": [1.8],
        "prices": [7.6868],
        "leverages": [2]
    }
    
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    
    payload_data = handler.fetch_payload(API_URL, BODY, HEADERS)
    print("Before payload:", payload_data)

    if not payload_data:
        print("Failed to fetch payload data.")
        return

    # Ensure argumentTypes is included in payload_data
    payload_data["argumentTypes"] = [
        Serializer.u64,  # marketId
        Serializer.sequence_serializer(Serializer.u128),
        Serializer.sequence_serializer(Serializer.bool),
        Serializer.sequence_serializer(Serializer.bool),  # orderTypes
        Serializer.sequence_serializer(Serializer.bool),  # tradeSides
        Serializer.sequence_serializer(Serializer.bool),  # directions
        Serializer.sequence_serializer(Serializer.u64),  # sizes
        Serializer.sequence_serializer(Serializer.u64),  # prices
        Serializer.sequence_serializer(Serializer.u64),  # leverages
        Serializer.sequence_serializer(Serializer.u8),  # restrictions
        Serializer.sequence_serializer(Serializer.u64),  # takeProfits
        Serializer.sequence_serializer(Serializer.u64),  # stopLosses
    ]

    try:
        print("After payload:", payload_data)
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
    
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())

```

## **10.** Get Open Orders

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getOpenOrders`](https://perps-tradeapi.kanalabs.io/getOpenOrders)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve open orders for.
  * **marketId** - The ID of the market to filter open orders.  // Optional

```
Note : order_type Explanation:

OPEN_LONG (1): Opens a new long position.
OPEN_SHORT (2): Opens a new short position.
INCREASE_LONG (3): Increases the size of an existing long position.
INCREASE_SHORT (4): Increases the size of an existing short position.
DECREASE_LONG (5): Reduces the size of an existing long position.
DECREASE_SHORT (6): Reduces the size of an existing short position.
CLOSE_LONG (7): Closes an existing long position.
CLOSE_SHORT (8): Closes an existing short position.
```

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOpenOrders?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched open orders successfully",
  "data": [
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": 1741444213,
      "price": "7",
      "total_size": "2",
      "remaining_size": "2",
      "order_value": "14",
      "order_id": "645636324063400958808",
      "trade_id": "295147905179352826357",
      "last_updated": 1741444214,
      "transaction_version": 6703807706
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": 1741445758,
      "price": "7",
      "total_size": "2",
      "remaining_size": "2",
      "order_value": "14",
      "order_id": "682529812245179800408",
      "trade_id": "295147905179352826357",
      "last_updated": 1741445758,
      "transaction_version": 6703807706
    }
  ]
}
```

**Example Code to Fetch** Open Order&#x73;**:**

The following Python script demonstrates how to call the Get Open Orders API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getOpenOrders'
        params = {
            'marketId': 501,
            'userAddress': "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_open_orders = response.json()
        print("getOpenOrders: ", get_open_orders)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **11.** Get Order History

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getOrderHistory`](https://perps-tradeapi.kanalabs.io/getOrderHistory)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve the order history.
  * **marketId** (optional) - The ID of the market to filter the order history.
  * offset (Optional) - The offset for paginating the results.\
    limit (Optional) - The maximum number of results to return.\
    order (Optional) - The sort order of the results. Accepts `asc` or `desc`.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOrderHistory?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched order history successfully",
  "data": [
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 1,
      "timestamp": 1741167151,
      "is_market_order": false,
      "size": "1.50",
      "price": "4.678",
      "order_value": "7.01700",
      "status": "Open",
      "order_id": "18446884819787846214",
      "trade_id": "18446744073709552117",
      "last_updated": 1741262093,
      "transaction_version": 6703807706
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 1,
      "timestamp": 1741236277,
      "is_market_order": false,
      "size": "1.50",
      "price": "4.678",
      "order_value": "7.01700",
      "status": "Cancelled",
      "order_id": "18446884819787846214",
      "trade_id": "18446744073709552117",
      "last_updated": 1741262168,
      "transaction_version": 6703807706
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 1,
      "timestamp": 1741236468,
      "is_market_order": false,
      "size": "1.50",
      "price": "4.50",
      "order_value": "6.7500",
      "status": "Open",
      "order_id": "36893628893497397652",
      "trade_id": "36893488147419103733",
      "last_updated": 1741262168,
      "transaction_version": 6703807706
    }
  }
]
```

**Example Code to Fetch Order History:**

The following Python script demonstrates how to call the Get Order History API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getOrderHistory'
        params = {
            'marketId': 501,
            'userAddress': "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_order_history = response.json()
        print("getOrderHistory: ", get_order_history)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **12.** Get Positions

* **Endpoint URL**:\
  [h`ttps://perps-tradeapi.kanalabs.io/getPositions`](https://perps-tradeapi.kanalabs.io/getPositions)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address of the user to view positions for.
  * **marketId** (optional) - The ID of the market to filter the positions.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getPositions?marketId=66&userAddress=0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched positions successfully",
  "data": [
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "trade_side": true,
      "size": "1",
      "available_order_size": "1",
      "value": "5.678",
      "entry_price": "5.678",
      "liq_price": "2.9117948717948717990163355253",
      "margin": "2.839",
      "tp": "6.012",
      "sl": null,
      "trade_id": "295147905179352826357",
      "last_updated": 1741262185,
      "transaction_version": 6703807706
    }
  ]
}
```

**Example Code to Fetch** Open Positio&#x6E;**:**

The following Python script demonstrates how to call the Get Open Position API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getPositions'
        params = {
            'marketId': 501,
            'userAddress': "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_open_position = response.json()
        print("getOpenPosition: ", get_open_position)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **13.** Get Order Status By Order Id

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId`](https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market associated with the order.
  * **orderId** (Required) - The unique identifier of the order to retrieve its status.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId?marketId=66&orderId=15308325717473050761363456
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "status": true,
  "message": "Fetched order status for a given order Id successfully",
  "data": {
    "market_id": 66,
    "order_id": "15308325717473050761363456",
    "created_at": "2024-11-20T11:54:45.957059+00:00",
    "last_updated_at": "2024-11-20T11:54:45.957059+00:00",
    "integrator": "0xee820ab02631dd1a195d3c53fa64f0a8f455dbb9261388e141c3bd3bd3c08363",
    "total_filled": 1000,
    "remaining_size": 0,
    "order_status": "closed",
    "order_type": "market",
    "user": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
    "direction": "buy",
    "price": 0,
    "average_execution_price": 12813,
    "custodian_id": 28,
    "self_match_behavior": 0,
    "restriction": 0,
    "last_increase_stamp": null,
    "min_base": null,
    "max_base": null,
    "min_quote": null,
    "max_quote": null,
    "total_fees_paid_in_quote_subunits": 6406
  }
}
```

**Example Code to Fetch** Order Status B Order I&#x64;**:**

The following Python script demonstrates how to call the Get Order Status By Order Id API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId'
        params = {
            'marketId': 501,
            'orderId': '85703575078023708283016'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_order_status_by_order_id = response.json()
        print("getOrderStatusByOrderId: ", get_order_status_by_order_id)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **14.** Get Fills

**Note:**\
For the `getFills` endpoint, you must pass the **profile address**, not the wallet address.\
Please make sure to first call the **Get Profile Address** endpoint and use that returned address as the `address` parameter in the `getFills` request.

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getFills`](https://perps-tradeapi.kanalabs.io/getFills)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which fills are retrieved.
  * **address** (Optional) - The address of the user to filter fills (if applicable).
  * **from** (Required) - The start time of the range in ISO 8601 format (e.g., `2024-11-21T00:00:00Z`).
  * **to** (Required) - The end time of the range in ISO 8601 format (e.g., `2024-11-21T23:59:59Z`).
  * **orderId** (Required) - The unique identifier of the order to retrieve its status.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getFills?marketId=66&address=0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2&from=2024-11-20T00:00:00Z&to=2024-11-21T23:59:59Z
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched fill trades for a given time range Successfully",
  "data": [
    {
      "txn_version": 6296434935,
      "event_idx": 1,
      "emit_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "time": "2024-11-20T19:23:14.67535+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15891335065048614061485282",
      "maker_side": true,
      "market_id": 66,
      "price": 11490,
      "sequence_number_for_trade": 0,
      "size": 1000,
      "taker_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "taker_custodian_id": 28,
      "taker_order_id": "15891427297643009687945216",
      "taker_quote_fees_paid": 5745
    },
    {
      "txn_version": 6295302625,
      "event_idx": 4,
      "emit_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "time": "2024-11-20T18:19:35.70863+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15812401447297883953966476",
      "maker_side": false,
      "market_id": 66,
      "price": 11660,
      "sequence_number_for_trade": 0,
      "size": 1000,
      "taker_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "taker_custodian_id": 28,
      "taker_order_id": "15812549019983827645235200",
      "taker_quote_fees_paid": 5830
    }
  ]
}
```

**Example Code to Fetch** Order Status B Order IdFills Dat&#x61;**:**

The following Python script demonstrates how to call the Get Fills Data API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getFills'
        params = {
            'marketId': 'your_market_id',
            'address': 'your_address',
            'from': 'your_from_time',
            'to': 'your_to_time'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_fills_data = response.json()
        print("getFillsData: ", get_fills_data)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **14.** Get Market Price

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getMarketPrice`](https://perps-tradeapi.kanalabs.io/getMarketPrice)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the price information is being retrieved.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getMarketPrice?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched Market Price Successfully",
  "data": {
    "bestAskPrice": 6.400,
    "bestBidPrice": 9.880
  }
}
```

**Example Code to Fetch** Market Pric&#x65;**:**

The following Python script demonstrates how to call the Get Market Price API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getMarketPrice'
        params = {
            'marketId': 501
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_market_price = response.json()
        print("getMarketPrice: ", get_market_price)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **15.** Get Last Execution Price

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getLastPlacedPrice`](https://perps-tradeapi.kanalabs.io/getLastPlacedPrice)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the last execution price information is being retrieved.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getLastPlacedPrice?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched last execution price Successfully",
  "data": 8.989
}
```

**Example Code to Fetch** Last Execution Pric&#x65;**:**

The following Python script demonstrates how to call the Get Last Execution Price API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getLastPlacedPrice'
        params = {
            'marketId': 501
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_last_execution_price = response.json()
        print("getLastExecutionPrice: ", get_last_execution_price)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **16.** Get All Open Order Ids

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds`](https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds)
* **Method**:\
  `GET`
* **Query Parameters**:
  * userAddress(Required) - The address associated with the orders.
  * **marketId** (optional) - The ID of the market for which open order IDs are being retrieved.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds?marketId=66&userAddress=0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Open order IDs fetched successfully",
  "data": [
    "645636324063400958808",
    "682529812245179800408",
    "700976556301709482840",
    "719423300401188838232",
    "737869903703050289159",
    "756316647793939709959"
  ]
}
```

**Example Code to Fetch** Open Order Id&#x73;**:**

The following Python script demonstrates how to call the Get Open Order Ids API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds'
        params = {
            'userAddress': '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770',
            'marketId': 501
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_open_order_ids = response.json()
        print("getOpenOrderIds: ", get_open_order_ids)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **17. Update Take Profit**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/updateTakeProfit`](https://perps-tradeapi.kanalabs.io/updateTakeProfit)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the take profit values will be updated.
  * **tradeSide** (Required) - The trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **newTakeProfitPrice** (Required) - The new take profit price to be set for the trade.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/updateTakeProfit?marketId=66&tradeSide=true&newTakeProfitPrice=6000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Update take profit payload built succesfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::update_take_profit",
    "functionArguments": [
      "501",
      "true",
      7590
    ],
    "typeArguments": []
  }
}
```

**Example Code to Update take profit price:**

The following Python script demonstrates how to call the Get Update Take Profit Price API using the requests library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List
load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/updateTakeProfit"
    PARAMS = {
        "marketId": 501,
        "tradeSide": True,
        "newTakeProfitPrice": 6.89
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)
    
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            int(payload_data["functionArguments"][0]),
            payload_data["functionArguments"][1].lower() == "true",
            int(payload_data["functionArguments"][2]),
        ]
        payload_data["argumentTypes"] = [Serializer.u64, Serializer.bool, Serializer.u64]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **18.** Get Account Aptos Balance

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAccountAptBalance`](https://perps-tradeapi.kanalabs.io/getAccountAptBalance)
* **Method**:\
  `GET`
* **Query Parameters**:
* **userAddress** (Required) - The address of the account whose balance will be&#x20;

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAccountAptBalance?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched Account Apt Balance Successfully",
  "data": 8.2344617
}
```

**Example Code to Fetch** Wallet Account Aptos Balance **Information:**

The following Python script demonstrates how to call the Get Wallet Account Aptos Balance API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getAccountAptBalance'
        params = {
            'userAddress': '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_wallet_account_aptos_balance = response.json()
        print("getWalletAccountAptosBalance: ", get_wallet_account_aptos_balance)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **19. Update Stop Loss**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/updateStopLoss`](https://perps-tradeapi.kanalabs.io/updateStopLoss)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the take profit values will be updated.
  * **tradeSide** (Required) - The trade side:
    * `true` for the long side.
    * `false` for the short side.
  * newStopLossPrice (Required) - The new stop loss price to be set for the trade.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/updateStopLoss?marketId=66&tradeSide=true&newStopLossPrice=6000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Update stop loss payload built succesfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::update_stop_loss",
    "functionArguments": [
      "501",
      "true",
      7590
    ],
    "typeArguments": []
  }
}
```

**Example Code to Update stop loss price:**

The following Python script demonstrates how to call the Get Update Stop Loss Price API using the requests library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List
load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/updateStopLoss"
    PARAMS = {
        "marketId": 501,
        "tradeSide": True,
        "newStopLossPrice": 6.89
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)
    
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            int(payload_data["functionArguments"][0]),
            payload_data["functionArguments"][1].lower() == "true",
            int(payload_data["functionArguments"][2]),
        ]
        payload_data["argumentTypes"] = [Serializer.u64, Serializer.bool, Serializer.u64]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **20. Get Profile Address** <a href="#id-20.-get-profile-address" id="id-20.-get-profile-address"></a>

* **Endpoint URL**: [`https://perps-tradeapi.kanalabs.io/getProfileAddress`](https://perps-tradeapi.kanalabs.io/getProfileAddress)
* **Method**: `GET`
* **Query Parameters**:
  * `userAddress`(Required) - The address of the user to get the profile address.

**Example Request:**

Copy

```
GET https://perps-tradeapi.kanalabs.io/getProfileAddress?userAddress=0xd01e3a233632a41463bd6d289e99e69e1b50815c7afff710e1c992659a8722f3
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

Copy

```typescript
{
  "success": true,
  "message": "Profile address fetched successfully",
  "data": "0x56ad3b670c9193414e5f3dbc1d9caf7a08368c4ab0b4b29c00ce13c463f6d934"
}
```

**Example Code to Fetch the profile address:**

The following TypeScript/Node.js script demonstrates how to call the Get profile address API using the `axios` library.

```python
import os
import requests
from dotenv import load_dotenv
load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getProfileAddress'
        params = {
            'userAddress': '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_wallet_account_balance = response.json()
        print("getWalletAccountBalance: ", get_wallet_account_balance)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **21. Collapse position**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/collapsePosition`](https://perps-tradeapi.kanalabs.io/collapsePosition)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `marketId` (Required) - The ID of the market you want to collapse a position.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/collapsePosition?marketId=501
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "collapse position payload built succesfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::collapse_position",
    "functionArguments": [
      "624"
    ],
    "typeArguments": []
  }
}
```

**Example Code to collapse a position:**

The following TypeScript/Node.js script demonstrates how to call the collapse position API using the `axios` library.

```typescript
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.account_address import AccountAddress  # Import this
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List
load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/collapsePosition"
    PARAMS = {
        "marketId": 624
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)
    
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            int(payload_data["functionArguments"][0])
        ]
        payload_data["argumentTypes"] = [Serializer.u64]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **22.** Get All Trades

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAllTrades`](https://perps-tradeapi.kanalabs.io/getAllTrades)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market to retrieve all trades information.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAllTrades?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Recent trades fetched successfully",
  "data": [
    {
      "txn_version": 6297687196,
      "event_idx": 5,
      "emit_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "time": "2024-11-20T20:33:38.600241+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15951655917465922493754983",
      "maker_side": true,
      "market_id": 66,
      "price": 11879,
      "sequence_number_for_trade": 0,
      "size": 10000,
      "taker_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "taker_custodian_id": 28,
      "taker_order_id": "15951748150764039921729536",
      "taker_quote_fees_paid": 59395
    },
    {
      "txn_version": 6297687196,
      "event_idx": 4,
      "emit_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "time": "2024-11-20T20:33:38.600241+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15951655917465922493754983",
      "maker_side": true,
      "market_id": 66,
      "price": 11879,
      "sequence_number_for_trade": 0,
      "size": 10000,
      "taker_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "taker_custodian_id": 28,
      "taker_order_id": "15951748150764039921729536",
      "taker_quote_fees_paid": 59395
    }
  ]
}
```

**Example Code to Fetch** All trade&#x73;**:**

The following Python script demonstrates how to call the Get Open Position API using the requests library.

```typescript
import os
import requests
from dotenv import load_dotenv
load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getAlllTrades'
        params = {
          marketId: 'your_market_id'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        getAlllTrades= response.json()
        print("getAlllTrades: ", getAlllTrades)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **23.** Get Account Apt Balance

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAccountAptBalance`](https://perps-tradeapi.kanalabs.io/getAccountAptBalance)\
  \
  **Method**:\
  `GET`
* **Query Parameters**:
  * `userAddress` (Required) - The wallet address for which the account balance is being fetched.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAccountAptBalance?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched wallet apt balance successfully",
  "data": 91.60
}
```

**Example Code to Fetch** Account Apt Balance **Information:**

The following TypeScript/Node.js script demonstrates how to call the Get Account Apt Balance API using the `axios` library.

```python
import os
import requests
from dotenv import load_dotenv
load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getAccountAptBalance'
        params = {
            'userAddress': '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        getAccountAptBalance = response.json()
        print("getAccountAptBalance: ", getAccountAptBalance)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## 24. Get Perpetual Asset Info

**Endpoint URL:**\
`https://perps-tradeapi.kanalabs.io/getPerpetualAssetsInfo`

**Method:**\
`GET`

**Query Parameters:**

* `marketId` (optional) – Numeric ID of the market to fetch.
* `baseName` (optional) – Name of the base asset (e.g., `"ETH"`, `"BTC"`).

**Note:** Either `marketId` or `baseName` must be provided. If neither is provided, the server will respond with a `400` error.

**Example Request:**

```
GET https://perps-tradeapi.kanalabs.io/getPerpetualAssetsInfo?marketId=1338
```

**Example Response:**

```json
{
  "success": true,
  "message": "Fetched market infos successfully",
  "data": [
    {
      "__variant__": "V1",
      "base_decimals": 8,
      "base_name": "APT/USDC",
      "counter": "9473",
      "creator": "0xb61d7b57333abf8ac036e752f19d0ba0c4baa5404db1cbf868c57dac3628f2bf",
      "fee_address": "0x7724a4a23b25b460abc2a5d9fe1fe3c47e2a0e10a156dd713a221f129579c388",
      "is_recognised": false,
      "last_updated": "1745235856",
      "lot_size": "100000",
      "maintenance_margin": "250",
      "market_address": "0xcfa0086c26787035de6b4a312875c7a70b2f9a29fa880d0cf633ef3dd0acd2c3",
      "market_id": "1338",
      "market_status": 1,
      "max_leverage": "20",
      "max_lots": "150000000",
      "max_position_value": "125000000000",
      "min_lots": "500",
      "quote_decimals": 6,
      "quote_precision": 3,
      "tick_size": "1"
    }
  ]
}
```

**Example Code:**

```python
import os
import requests
from dotenv import load_dotenv
load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getPerpetualAssetsInfo'
        params = {
            'marketId': '1338'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        getPerpetualAssetsInfo = response.json()
        print("getPerpetualAssetsInfo: ", getPerpetualAssetsInfo)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

***

### Get All Perpetual Market Assets

**Endpoint URL:**\
`https://perps-tradeapi.kanalabs.io/getPerpetualAssetsInfo/allMarkets`

**Method:**\
`GET`

**Description:**\
Fetches all available perpetual market asset information. This endpoint does not require any query parameters.

**Example Request:**

```
GET https://perps-tradeapi.kanalabs.io/getPerpetualAssetsInfo/allMarkets
```

**Example Response:**

```json
{
  "success": true,
  "message": "Fetched market infos successfully",
  "data": [
    {
      "__variant__": "V1",
      "base_decimals": 8,
      "base_name": "APT/USDC",
      "counter": "9473",
      "creator": "0xb61d7b57333abf8ac036e752f19d0ba0c4baa5404db1cbf868c57dac3628f2bf",
      "fee_address": "0x7724a4a23b25b460abc2a5d9fe1fe3c47e2a0e10a156dd713a221f129579c388",
      "is_recognised": false,
      "last_updated": "1745235856",
      "lot_size": "100000",
      "maintenance_margin": "250",
      "market_address": "0xcfa0086c26787035de6b4a312875c7a70b2f9a29fa880d0cf633ef3dd0acd2c3",
      "market_id": "1338",
      "market_status": 1,
      "max_leverage": "20",
      "max_lots": "150000000",
      "max_position_value": "125000000000",
      "min_lots": "500",
      "quote_decimals": 6,
      "quote_precision": 3,
      "tick_size": "1"
    },
    {
      "__variant__": "V1",
      "base_decimals": 8,
      "base_name": "BTC/USDC",
      "counter": "4813",
      "creator": "0xb61d7b57333abf8ac036e752f19d0ba0c4baa5404db1cbf868c57dac3628f2bf",
      "fee_address": "0x7724a4a23b25b460abc2a5d9fe1fe3c47e2a0e10a156dd713a221f129579c388",
      "is_recognised": false,
      "last_updated": "1745235864",
      "lot_size": "1000",
      "maintenance_margin": "250",
      "market_address": "0xc4de5894f6a97168998719c10f517572cbe10fe6911ca25004fbe87a88247ed4",
      "market_id": "1339",
      "market_status": 1,
      "max_leverage": "20",
      "max_lots": "6000000",
      "max_position_value": "125000000000",
      "min_lots": "10",
      "quote_decimals": 6,
      "quote_precision": 0,
      "tick_size": "10"
    },
    {
      "__variant__": "V1",
      "base_decimals": 8,
      "base_name": "ETH/USDC",
      "counter": "3377",
      "creator": "0xb61d7b57333abf8ac036e752f19d0ba0c4baa5404db1cbf868c57dac3628f2bf",
      "fee_address": "0x7724a4a23b25b460abc2a5d9fe1fe3c47e2a0e10a156dd713a221f129579c388",
      "is_recognised": false,
      "last_updated": "1745235871",
      "lot_size": "10000",
      "maintenance_margin": "250",
      "market_address": "0x9e173d4330b94718fd09c3d1d18b707f2713a1cd92e79403ee150429c3125718",
      "market_id": "1340",
      "market_status": 1,
      "max_leverage": "20",
      "max_lots": "10000000",
      "max_position_value": "125000000000",
      "min_lots": "10",
      "quote_decimals": 6,
      "quote_precision": 1,
      "tick_size": "10"
    }
  ]
}
```

**Example Code:**

```python
import os
import requests
from dotenv import load_dotenv
load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getPerpetualAssetsInfo/allMarkets'
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, headers=headers)
        response.raise_for_status()
        getPerpetualAssetsInfo = response.json()
        print("getPerpetualAssetsInfo: ", getPerpetualAssetsInfo)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **25. Add Margin**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/addMargin`](https://perps-tradeapi.kanalabs.io/addMargin)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId (Required)** – The unique identifier of the market where the margin is being added.
  * **tradeSide** (Required) - Indicates the trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **amount (Required)** – The amount of additional margin to be added to the position.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/addMargin?marketId=1338&tradeSide=true&amount=1
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Add Margin payload built successfully",
  "data": {
    "function": "0x732f891290449af5e9369866537a51a8e7dc566791aec61a468223ed840b1eb4::perpetual_scripts::add_margin",
    "functionArguments": [
      "1338",
      "true",
      1000000
    ],
    "typeArguments": []
  }
}
```

**Example Code to add a margin:**

The following python demonstrates how to call the Get Add Margin API using the `axios` library.

```python
import asyncio
import os
import requests
from dotenv import load_dotenv
from typing import List
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag

load_dotenv()

class AptosTransactionHandler:
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List, types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            module, function_id = "::".join(payload["function"].split("::")[:-1]), payload["function"].split("::")[-1]
            function_arguments = self.create_transaction_function_arguments(payload["functionArguments"], payload["argumentTypes"])
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            
            entry_function = EntryFunction.natural(module=module, function=function_id, ty_args=type_arguments, args=function_arguments)
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction = await self.rest_client.create_bcs_signed_transaction(self.account, transaction_payload)
            txn_hash = await self.rest_client.submit_bcs_transaction(signed_transaction)
            await self.rest_client.wait_for_transaction(txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')

    if not private_key_hex:
        print("Error: APTOS_PRIVATEKEY is missing in .env file.")
        return

    account = Account.load_key(bytes.fromhex(private_key_hex[2:] if private_key_hex.startswith("0x") else private_key_hex))
    rest_client = RestClient(NODE_URL)

    API_URL = "https://perps-tradeapi.kanalabs.io/addMargin"
    PARAMS = {"marketId": 1338, "tradeSide": True, "amount": 10}
    HEADERS = {"x-api-key": os.getenv('API_KEY')}

    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)

    if not payload_data:
        print("Failed to fetch payload data.")
        return

    try:
        payload_data["functionArguments"] = [
            int(payload_data["functionArguments"][0]),
            payload_data["functionArguments"][1].lower() == "true",
            int(payload_data["functionArguments"][2]),
        ]

        payload_data["argumentTypes"] = [
            Serializer.u64, Serializer.bool, Serializer.u64
        ]
        
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Hash: {txn_hash}")

    except Exception as e:
        print(f"Transaction process error: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **26.** Get Net Profile Balance <a href="#id-26.-get-net-profile-balance" id="id-26.-get-net-profile-balance"></a>

This endpoint returns the net profile balance, which includes both the available balance in trading account and any pending balances from closed positions on all markets.

* **Endpoint URL**: [`https://perps-tradeapi.kanalabs.io/getNetProfileBalance`](https://perps-tradeapi.kanalabs.io/getNetProfileBalance)&#x20;
* **Method**: `GET`
* **Query Parameters**:
  * `userAddress` (Required) - The wallet address for which the account balance is being fetched.

**Example Request:**

```
GET https://perps-tradeapi.kanalabs.io/getNetProfileBalance?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Net Profile Balance fetched successfully",
  "data": 49443.432113
}
```

**Example Code to Fetch** Net Profile Balance **Information:**

The following python  demonstrates how to call the Get Net Profile Balance API using the `axios` library.

```python
import os
import requests
from dotenv import load_dotenv
load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getNetProfileBalance'
        params = {
            'userAddress': '0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_net_profile_balance= response.json()
        print("getNetProfileBalance: ", get_net_profile_balance)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **27. Settle Pnl** <a href="#id-27.-settle-pnl" id="id-27.-settle-pnl"></a>

This API returns a transaction payload used to manually (or automatically, on user interactions) refresh the user's position and settle the Pnl for a specific market, allowing the user to claim any unreleased Pnl.

* **Endpoint URL**: [`https://perps-tradeapi.kanalabs.io/settlePnl`](https://perps-tradeapi.kanalabs.io/settlePnl)
* **Method**: `GET`
* **Query Parameters**:
  * **marketId** (Required) -
  * userAddress (Required) -

**Example Request:**

```
GET https://perps-tradeapi.kanalabs.io/settlePnl?userAddress=0xd0ff27c8411015f386ffc464e3baaa12fca10f1bef1ec6af36c27ed96b65f6c6&marketId=1338=6000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Update position payload built succesfully",
  "data": {
    "function": "0x732f891290449af5e9369866537a51a8e7dc566791aec61a468223ed840b1eb4::perpetual_scripts::update_position",
    "functionArguments": [
      "0xd0ff27c8411015f386ffc464e3baaa12fca10f1bef1ec6af36c27ed96b65f6c6",
      "1338"
    ],
    "typeArguments": []
  }
}
```

**Example Code to Get Settle Pnl:**

The following python demonstrates how to call the Get Settle pnl API using the `axios` library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.account_address import AccountAddress  # Import this
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List
load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/settlePnl"
    PARAMS = {
        "userAddress":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
        "marketId": 1338
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)
    
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            AccountAddress.from_str(payload_data["functionArguments"][0]),  
            int(payload_data["functionArguments"][1]),
        ]
        payload_data["argumentTypes"] = [Serializer.struct, Serializer.u64]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **28.** Get Trade History

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getTradeHistory`](https://perps-tradeapi.kanalabs.io/getOrderHistory)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve the trade history.
  * **marketId** (optional) - The ID of the market to filter the trade history.
  * offset (Optional) - The offset for paginating the results.\
    limit (Optional) - The maximum number of results to return.\
    order (Optional) - The sort order of the results. Accepts `asc` or `desc`.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getTradeHistory?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched trade history successfully",
  "data": [
    {
    "address": "0x556c6465f9cedfe721d0a8537cf898cd2e5881ef89eb4a5a39df62e6ca439087",
    "leverage": 2,
    "market_id": "14",
    "timestamp": 1745998772,
    "size": "1",
    "order_type": 2,
    "price": "5.37",
    "order_value": "5.37",
    "pnl": "-0.0026850000000000000558927906",
    "fee": "0.0026850000000000000558927906",
    "trade_id": "55340232221128654862",
    "last_updated": 1749419915,
    "transaction_version": 2665614406,
    "entry_price": null,
    "order_id": "55340232221128654848"
  },
  {
    "address": "0x51f531abefc697845eabae4ba20c7cc26b1f849561bb016c4d90707c4ede1912",
    "leverage": 2,
    "market_id": "14",
    "timestamp": 1745998772,
    "size": "1",
    "order_type": 1,
    "price": "5.37",
    "order_value": "5.37",
    "pnl": "0",
    "fee": "0",
    "trade_id": "36893488147419103246",
    "last_updated": 1749419915,
    "transaction_version": 2665614406,
    "entry_price": null,
    "order_id": "36893628893497398522"
   }
  }
]
```

**Example Code to Fetch Trade History:**

The following TypeScript/Node.js script demonstrates how to call the Get Trade History API using the `axios` library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getTradeHistory'
        params = {
            'marketId': 501,
            'userAddress': "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_trade_history = response.json()
        print("getTradeHistory: ", get_trade_history)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **29.** Get Deposit and Withdraw History

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getDepositAndWithdrawHistory`](https://perps-tradeapi.kanalabs.io/getDepositAndWithdrawHistory)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve the order history

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getDepositAndWithdrawHistory?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770 Response:
```

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched deposit and withdraw history successfully",
  "data": [
    {
      "wallet_address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
      "address": "0xdf83209915c1b8087d8c2e3c1fe381f08fc7adbd55349a0bc9f4c906f8a76a82",
      "is_deposit": true,
      "timestamp": 1745236010,
      "amount": "10000",
      "last_updated": 1747110329,
      "transaction_version": 6694351099,
      "is_promoted": false,
      "promotion_id": null
    }
  ]
 }
```

**Example Code to Fetch Deposit and Withdraw History:**

The following Python script demonstrates how to call the Get **Deposit and Withdraw History** API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getDepositAndWithdrawHistory'
        params = {
            'userAddress': "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_deposit_and_withdraw_history= response.json()
        print("getDepositAndWithdrawHistory: ", get_deposit_and_withdraw_history)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **29.** Get Funding History

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getFundingHistory`](https://perps-tradeapi.kanalabs.io/getFundingHistory)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve the funding history.
  * **marketId** (optional) - The ID of the market to filter the funding  history.
  * offset (Optional) - The offset for paginating the results.\
    limit (Optional) - The maximum number of results to return.\
    order (Optional) - The sort order of the results. Accepts `asc` or `desc`.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getFundingHistory?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770 Response:
```

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched funding history successfully",
  "data": [
    {
      "address": "0xdf83209915c1b8087d8c2e3c1fe381f08fc7adbd55349a0bc9f4c906f8a76a82",
      "funding_amount": "0",
      "funding_rate": "0",
      "market_id": "1338",
      "funding_timestamp": 1748840400,
      "transaction_timestamp": 1748840428,
      "last_updated": 1748840431,
      "transaction_version": 6769626199,
      "trade_id": "83453070189462011512122",
      "size": "10",
      "leverage": 2,
      "trade_side": true
    }
  ]
}
```

**Example Code to Fetch** Funding **History:**

The following Python script demonstrates how to call the Get Funding **History** API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getFundingHistory'
        params = {
            'userAddress': "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_funding_history= response.json()
        print("getFundingHistory: ", get_funding_history)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **30.** Fetch Order Status By Id

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/fetchOrderStatusById`](https://perps-tradeapi.kanalabs.io/fetchOrderStatusById)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market associated with the order.
  * **orderId** (Required) - The unique identifier of the order to retrieve its status.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/fetchOrderStatusById?marketId=1338&orderId=33760566922324346434229328
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched final order status successfully",
  "data": {
    "address": "0x725c8b51b2c1b3d17336c48d75c56c19253f70e1de00e26c8138a29722d82da",
    "market_id": "1338",
    "leverage": 2,
    "order_type": 3,
    "timestamp": 1746216029,
    "is_market_order": false,
    "size": "0.218",
    "price": "5.20",
    "order_value": "1.13360",
    "status": "Cancelled",
    "order_id": "33760566922324346434229328",
    "trade_id": "172200355928078664336698",
    "last_updated": 1747229891,
    "transaction_version": 6704908886,
    "total_filled": "0.782",
    "remaining_size": "0.218",
    "total_trade_size": "1"
  }
}
```

#### **Possible Order Status Values:**

The `status` field will contain one of the following values:

| Status             | Meaning                                                                                                         |
| ------------------ | --------------------------------------------------------------------------------------------------------------- |
| `Open`             | Order is open                                                                                                   |
| `Filled`           | The order is fully filled. There will be no remaining open orders with the same order ID in the order history   |
| `Partially Filled` | The order is partially filled. There will be remaining open orders with the same order ID in the order history. |
| `Cancelled`        | The order has been cancelled                                                                                    |

**Example Code to Fetch** Order Status By I&#x64;**:**

The following Python script demonstrates how to call the Fetch Order Status By Id API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/fetchOrderStatusById'
        params = {
            'marketId': 501,
            'orderId': '85703575078023708283016'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        fetch_order_status_by_id= response.json()
        print("fetchOrderStatusById: ", fetch_order_status_by_id)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **31. Get Fills For Given Timestamp**&#x20;

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getFillsForGivenTimestamp`](https://perps-tradeapi.kanalabs.io/getFillsForGivenTimestamp)
* **Method**:\
  `GET`
* **Query Parameters**:

  userAddress (required)  \
  marketId (optional)  \
  offset (optional)  \
  limit (optional) —-> default 50  \
  order (optional) —-> asc or desc  \
  fromTimestamp (optional) --> In seconds (not milliseconds)  \
  toTimestamp (optional) --> In seconds (not milliseconds)

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getFillsForGivenTimestamp?marketId=1340&userAddress=0xb37f565528dc7dc1ddb376e930b62002ab61361d8bb9bfc2b4ace661fc6dbbfa&fromTimestamp=1751366416&toTimestamp=1751426951
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched fill trades for a given time range Successfully",
  "data": [
    {
      "address": "0x64e7e2d671526c2e092e5e7af94555c17c45d348400ae2a61424b6dbf338a9af",
      "leverage": 2,
      "market_id": "1340",
      "timestamp": 1751426951,
      "size": "1.0475",
      "order_type": 3,
      "price": "2449.50",
      "order_value": "2565.851250",
      "pnl": "0",
      "fee": "0",
      "trade_id": "245046548275157683668284",
      "last_updated": 1751426952,
      "transaction_version": 6798502405,
      "entry_price": null,
      "order_id": "112263471792402116758233007"
    },
    {
      "address": "0x64e7e2d671526c2e092e5e7af94555c17c45d348400ae2a61424b6dbf338a9af",
      "leverage": 2,
      "market_id": "1340",
      "timestamp": 1751366695,
      "size": "0.9669",
      "order_type": 4,
      "price": "2470.10",
      "order_value": "2388.339690",
      "pnl": "0",
      "fee": "0",
      "trade_id": "32982778403792678290748",
      "last_updated": 1751366696,
      "transaction_version": 6798038058,
      "entry_price": null,
      "order_id": "112263490233376000689856637"
    }
 ]
}
```

**Example Code to Get fills for given timestamp:**

The following Python script demonstrates how to call the get fills for given timestamp API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getFillsForGivenTimestamp'
        params = {
            'userAddress': "0xd0ff27c8411015f386ffc464e3baaa12fca10f1bef1ec6af36c27ed96b65f6c6",
            'fromTimestamp': 1751032488,
            'toTimestamp': 1751032608
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_fills_for_given_timestamp= response.json()
        print("getFillsForGivenTimestamp: ", get_fills_for_given_timestamp)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **32.** Get Positions From Contract

* **Endpoint URL**:

[`https://perps-tradeapi.kanalabs.io/getPositionsFromContract`](https://perps-tradeapi.kanalabs.io/getPositionsFromContract)

* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address of the user to view positions for.
  * **marketId** (optional) - The ID of the market to filter the positions.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getPositionsFromContract?marketId=66&userAddress=0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched positions from contract successfully",
  "data": [
    {
      "address": "0xef04eb57084fab57a42b7791d5e350240f890fc1c1cd12c2002cb93b86a7b564",
      "market_id": "14",
      "leverage": 10,
      "trade_side": true,
      "size": "1.76276",
      "available_order_size": "1.76276",
      "value": "9.53898961",
      "entry_price": "5.41139439884",
      "liq_price": "4.995",
      "margin": "0.953946706999278",
      "tp": "0",
      "sl": "0",
      "trade_id": "7667887236327365287084046"
    }
  ]
}
```

**Example Code to Fetch** Open Position from contrac&#x74;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Position From Contract API using the `axios` library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getPositionsFromContract'
        params = {
            'marketId': 501,
            'userAddress': "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_open_position = response.json()
        print("getPositionsFromContract: ", get_open_position)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **33.** Get Open Orders From Contract

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getOpenOrdersFromContract`](https://perps-tradeapi.kanalabs.io/getOpenOrdersFromContract)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve open orders for.
  * **marketId (Optional)** - The ID of the market to filter open orders.  // Optional

```
Note : order_type Explanation:

OPEN_LONG (1): Opens a new long position.
OPEN_SHORT (2): Opens a new short position.
INCREASE_LONG (3): Increases the size of an existing long position.
INCREASE_SHORT (4): Increases the size of an existing short position.
DECREASE_LONG (5): Reduces the size of an existing long position.
DECREASE_SHORT (6): Reduces the size of an existing short position.
CLOSE_LONG (7): Closes an existing long position.
CLOSE_SHORT (8): Closes an existing short position.
```

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOpenOrdersFromContract?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched open orders from contract successfully",
  "data": [
    {
      "address": "0xef04eb57084fab57a42b7791d5e350240f890fc1c1cd12c2002cb93b86a7b564",
      "market_id": "14",
      "leverage": 10,
      "order_type": 3,
      "price": "5.459",
      "total_size": "1.69717",
      "remaining_size": "1.69717",
      "order_value": "9.26485103",
      "order_id": "220873897950436224634197331",
      "trade_id": "7667887236327365287084046"
    },
    {
      "address": "0xef04eb57084fab57a42b7791d5e350240f890fc1c1cd12c2002cb93b86a7b564",
      "market_id": "14",
      "leverage": 10,
      "order_type": 3,
      "price": "5.448",
      "total_size": "1.69717",
      "remaining_size": "1.69717",
      "order_value": "9.24618216",
      "order_id": "220873916394787984380007752",
      "trade_id": "7667887236327365287084046"
    }
   ]
} 
```

**Example Code to Fetch** Open Orders From Contarc&#x74;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Orders From Contract API using the `axios` library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getOpenOrdersFromContract'
        params = {
            'marketId': 501,
            'userAddress': "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_open_position = response.json()
        print("getOpenOrdersFromContract: ", get_open_position)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```


# Steps to place an order

## **Typescript**

1\. Faucet a usdt to your wallet account\
\
You can check here to faucet the usdt\
usdt\_faucet: <https://explorer.aptoslabs.com/object/0x24246c14448a5994d9f23e3b978da2a354e64b6dfe54220d[>…]c448cc/modules/run/usdt/faucet\_to\_address?network=testnet\
\
2\. After faucet you have to deposit that into your trading account :\
\
<https://docs.kanalabs.io/products-and-features/trading-apis/kana-perps-api/kana-perps-rest-api#id-4.-deposit>\
\
3\. After deposited you have to place the limit or market order:\
\
<https://docs.kanalabs.io/products-and-features/trading-apis/kana-perps-api/kana-perps-arest-api#id-6.-place-limit-order>

## **Python**

1\. Faucet a usdt to your wallet account\
\
You can check here to faucet the usdt\
usdt\_faucet: <https://explorer.aptoslabs.com/object/0x24246c14448a5994d9f23e3b978da2a354e64b6dfe54220d[>…]c448cc/modules/run/usdt/faucet\_to\_address?network=testnet\
\
2\. After faucet you have to deposit that into your trading account :\
\
<https://docs.kanalabs.io/~/changes/JpxQ3y4p9AD4BHUqimHx/products-and-features/trading-apis/kana-perps-api/kana-perps-python-rest-api#id-4.-deposit>\
\
3\. After deposited you have to place the limit or market order:\
\
<https://docs.kanalabs.io/~/changes/JpxQ3y4p9AD4BHUqimHx/products-and-features/trading-apis/kana-perps-api/kana-perps-python-rest-api#id-6.-place-limit-order>


# Perps Contract Error Codes

## KanaPerps Error Codes

#### perpetual\_core.move

| Error Messag                                                 | Error Code | Description                                                                         |
| ------------------------------------------------------------ | ---------- | ----------------------------------------------------------------------------------- |
| E\_NOT\_KANA                                                 | 1001       | Indicates that the caller is not Kana                                               |
| E\_PAUSED                                                    | 1002       | System or functionality is paused                                                   |
| E\_MARKET\_NOT\_FOUND                                        | 1003       | Market ID is not available in the perpetual market registry                         |
| E\_LEVERAGE\_MISMATCH\_CLOSE\_POSITION                       | 1004       | Leverage given while closing position does not match the current leverage           |
| E\_LEVERAGE\_MISMATCH\_INCREASE\_POSITION                    | 1005       | Leverage given while increasing position does not match the current leverage        |
| E\_INVALID\_LEVERAGE                                         | 1006       | Leverage is either greater than the maximum allowed for the market or zero          |
| E\_INSUFFICIENT\_LIQUIDITY\_IN\_ORDERBOOK                    | 1007       | Not enough liquidity in orderbook to fill the order                                 |
| E\_INSUFFICIENT\_BALANCE\_TO\_EXIT\_POSITION                 | 1008       | Not enough balance available to exit the position                                   |
| E\_INSUFFICIENT\_BALANCE\_IN\_TRADING\_ACCOUNT\_TO\_WITHDRAW | 1009       | User doesn't have enough balance in trading account to withdraw                     |
| E\_INSUFFICIENT\_FUND\_IN\_USER\_DEPOSITS                    | 1010       | User doesn't have enough funds in UserDeposits to withdraw                          |
| E\_TRADE\_SIZE\_EXCEEDS\_EXISTING\_FILLED                    | 1011       | Given order size is greater than the existing filled position size                  |
| E\_LOSS\_GREATER\_THAN\_COLLATERAL                           | 1012       | Loss is greater than available collateral                                           |
| E\_INVALID\_MAINTENANCE\_MARGIN                              | 1013       | Given maintenance margin is greater than the divisor                                |
| E\_INVALID\_INITIAL\_MARGIN                                  | 1014       | Given max leverage allows the initial margin to be less than the maintenance margin |
| E\_INSUFFICIENT\_FUND\_IN\_COLLATERAL\_STORE                 | 1015       | Not enough funds available in the collateral store to withdraw                      |
| E\_INSUFFICIENT\_FUND\_IN\_INSURANCE\_FUND                   | 1016       | Not enough funds available in the insurance fund to withdraw                        |
| E\_SIZE\_TOO\_LARGE                                          | 1017       | Order size exceeds the maximum allowed lots for the market                          |
| E\_INSUFFICIENT\_BASE\_IN\_MARKET\_ACCOUNT                   | 1018       | Not enough base asset in market account to withdraw                                 |
| E\_INSUFFICIENT\_QUOTE\_IN\_MARKET\_ACCOUNT                  | 1019       | Not enough quote asset in market account to withdraw                                |
| E\_LIMIT\_ORDER\_FOUND\_CANNOT\_RESET                        | 1020       | Long Limit orders found in the position registry cannot be reset                    |
| E\_LIQUIDATION\_PRICE\_NOT\_REACHED                          | 1021       | Liquidation price not reached to liquidate the position                             |
| E\_LIQUIDATION\_SIZE\_ZERO                                   | 1022       | Liquidation size is zero                                                            |
| E\_ZERO\_FILLED\_SIZE\_FOR\_TPSL\_EXECUTION                  | 1023       | Zero filled size for take profit/stop loss orders                                   |
| E\_TAKE\_PROFIT\_ORDER\_NOT\_FILLED                          | 1024       | Take profit order not filled completely                                             |
| E\_STOP\_LOSS\_ORDER\_NOT\_FILLED                            | 1025       | Stop loss order not filled completely                                               |
| E\_NO\_BIDS\_IN\_ORDERBOOK                                   | 1026       | No bids present in the orderbook                                                    |
| E\_NO\_ASKS\_IN\_ORDERBOOK                                   | 1027       | No asks present in the orderbook                                                    |
| E\_TAKE\_PROFIT\_PRICE\_NOT\_REACHED                         | 1028       | Take profit price is not reached for the position                                   |
| E\_STOP\_LOSS\_PRICE\_NOT\_REACHED                           | 1029       | Stop loss price is not reached for the position                                     |
| E\_TAKE\_PROFIT\_NOT\_SET                                    | 1030       | Take profit price is not set                                                        |
| E\_STOP\_LOSS\_NOT\_SET                                      | 1031       | Stop loss price is not set                                                          |
| E\_CANCEL\_VECTOR\_LEN\_MISMATCH                             | 1032       | Cancel order ID vector length not equal to sides vector length                      |
| E\_VECTOR\_LENGTH\_MISMATCH\_IN\_MULTIPLE\_ORDER\_PLACING    | 1033       | Input vector lengths for placing multiple orders are not equal                      |
| E\_NOT\_MARKET\_CREATOR                                      | 1034       | Caller is not the market creator                                                    |
| E\_UNSUPPORTED\_RESTRICTION\_TYPE                            | 1035       | Unsupported restriction type                                                        |
| E\_INSUFFICIENT\_QUOTE\_IN\_MARKET\_ACCOUNT\_TO\_COLLAPSE    | 1036       | Insufficient quote asset in the market account to collapse                          |
| E\_INSUFFICIENT\_BASE\_IN\_MARKET\_ACCOUNT\_TO\_COLLAPSE     | 1037       | Insufficient base asset in the market account to collapse                           |
| E\_NO\_FILLED\_OPEN\_POSITION\_ON\_ONE\_SIDE                 | 1038       | Attempted collapse with no active position on one side                              |
| E\_ZERO\_FILLED\_SIZE\_FOR\_UPDATE\_TPSL                     | 1039       | Zero filled size for updating take profit/stop loss                                 |
| E\_NO\_OPEN\_POSITION                                        | 1040       | No open position available                                                          |
| E\_MARGIN\_ADDITION\_EXCEEDS\_POSITION\_VALUE                | 1041       | Attempting to add margin would exceed the total position value                      |
| E\_LESS\_THAN\_MIN\_MARGIN\_ADDITION                         | 1042       | Amount less than the minimum margin addition amount                                 |
| E\_TRADE\_PROFILE\_DOESNT\_EXISTS                            | 1043       | Trade profile doesn't exist                                                         |
| E\_DEPRECATED                                                | 1044       | Function is deprecated                                                              |

#### utils.move

| Error Code                                              | Error Message | Description                                                                |
| ------------------------------------------------------- | ------------- | -------------------------------------------------------------------------- |
| E\_VALUE\_TOO\_LARGE\_U64                               | 4001          | Value is greater than the maximum possible u64                             |
| E\_ZERO\_TRADE\_ID                                      | 4002          | Generated Trade ID is zero                                                 |
| E\_INVALID\_MARKET\_ID\_ZERO                            | 4003          | Given market ID is zero                                                    |
| E\_INVALID\_TRADE\_COUNTER\_ZERO                        | 4004          | Given trade counter is zero                                                |
| E\_INVALID\_TAKE\_PROFIT\_PRICE\_LONG                   | 4005          | Given take profit price is less than the entry price for long position     |
| E\_INVALID\_STOP\_LOSS\_PRICE\_LONG                     | 4006          | Given stop loss price is greater than the entry price for long position    |
| E\_INVALID\_TAKE\_PROFIT\_PRICE\_SHORT                  | 4007          | Given take profit price is greater than the entry price for short position |
| E\_INVALID\_STOP\_LOSS\_PRICE\_SHORT                    | 4008          | Given stop loss price is less than the entry price for short position      |
| E\_STOP\_LOSS\_LESS\_THAN\_LIQUIDATION\_PRICE\_LONG     | 4009          | Stop loss price is less than the liquidation price for long position       |
| E\_STOP\_LOSS\_GREATER\_THAN\_LIQUIDATION\_PRICE\_SHORT | 4010          | Stop loss price is greater than the liquidation price for short position   |
| E\_INSUFFICIENT\_LIQUIDITY\_IN\_ORDERBOOK               | 4011          | Not enough liquidity in orderbook to fill                                  |
| E\_DIVISION\_BY\_ZERO                                   | 4012          | Denominator is zero                                                        |
| E\_INVALID\_PROFILE\_ID                                 | 4013          | Invalid Profile ID                                                         |

#### price\_oracle.move

| Error Code                        | Error Message | Description                                         |
| --------------------------------- | ------------- | --------------------------------------------------- |
| E\_NOT\_KANA                      | 2001          | Caller is not Kana                                  |
| E\_MARKET\_ID\_EXISTS             | 2002          | Market ID already exists                            |
| E\_INVALID\_PRICE\_FEED           | 2003          | Price feed does not exist                           |
| E\_INVALID\_PYTH\_PRICE\_EXPONENT | 2004          | Pyth price exponent is less than the quote exponent |

#### delegate\_proxy.move

| Error Code                        | Error Message | Description                 |
| --------------------------------- | ------------- | --------------------------- |
| E\_ALREADY\_DELEGATED             | 5001          | Already Delegated           |
| E\_NOT\_DELEGATED                 | 5002          | Not Delegated               |
| E\_NOT\_DELEGATED\_PROXY\_ADDRESS | 5003          | Not Delegated proxy address |
| E\_DELEGATION\_EXPIRED            | 5004          | Delegation expired          |


# Websocket Connection

### **Important Note:**

For all the Websocket endpoints below, pass your profile address.

To track your transactions on-chain (e.g., via **Aptos Explorer** or **Aptos Scan**), you must use your **profile address**, as all on-chain trades are executed using this profile address.

To obtain your profile address, use the `/getProfileAddress` endpoint and provide your wallet address as the `userAddress` parameter.

### How to Fetch the Profile Address:

**Example endpoint:**\
<https://perps-tradeapi.kanalabs.io/getProfileAddress?userAddress=0xd01e3a233632a41463bd6d289e99e69e1b50815c7afff710e1c992659a8722f3>\
\
**Example code:**\
[https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/kana-perps-typescript-rest-api#id-20.-](https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/kana-perps-typescript-rest-api#id-19.-update-stop-loss)get-profile-address

### How to subscribe websocketURL:

#### ✅ **Testnet WebSocket URL**

```typescript
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

#### ✅ **Mainnet WebSocket URL**

```typescript
wss://perpetuals-indexer-ws.kana.trade/ws/
```

Connect websocket with URL

* order\_history

```
{
  "topic": "order_history",
  "address": "{{user_address}}"
}
```

* deposit\_withdraw\_history

```
{
  "topic": "deposit_withdraw_history",
  "address": "{{user_address}}"
}
```

* trade\_history

```
{
  "topic": "trade_history",
  "address": "{{user_address}}"
}
```

* positions

```
{
  "topic": "positions",
  "address": "{{user_address}}"
}
```

* open\_orders

```
{
  "topic": "open_orders",
  "address": "{{user_address}}"
}
```

* orderbook

```
{
  "topic": "orderbook",
  "market_id": "{{market_id}}"
}
```

* recent\_trades

```
{
  "topic": "recent_trades",
  "market_id": "{{market_id}}"
}
```

* live\_funding\_rate

```
{
    "topic": "live_funding_rate"
}
```

* live\_order\_history (It will update only latest single data)

```
{
  "topic": "live_order_history",
  "address": "{{user_address}}"
}
```

* live\_trade\_history (It will update only latest single data)

```
{
  "topic": "live_trade_history",
  "address": "{{user_address}}"
}
```

* best\_price

```
{
  "topic": "bestPrice"
}
```

send message like and subscribe to websocket


# Supported Markets

Supported Markets & API/WebSocket Endpoints

### Testnet Supported Markets

<table data-header-hidden><thead><tr><th></th><th width="282"></th><th></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td><td><strong>Description</strong></td></tr><tr><td>APT-USD</td><td>1338</td><td>Aptos-based trading market.</td></tr><tr><td>BTC-USD</td><td>1339</td><td>Bitcoin-based trading market.</td></tr><tr><td>ETH-USD</td><td>1340</td><td>Ethereum-based trading market.</td></tr><tr><td>SOL-USD</td><td>2387</td><td>Solana-based trading market.</td></tr></tbody></table>

### Mainnet Supported Markets

<table data-header-hidden><thead><tr><th></th><th width="282"></th><th></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td><td><strong>Description</strong></td></tr><tr><td>APT-USD</td><td>14</td><td>Aptos-based trading market.</td></tr><tr><td>BTC-USD</td><td>15</td><td>Bitcoin-based trading market.</td></tr><tr><td>ETH-USD</td><td>16</td><td>Ethereum-based trading market.</td></tr><tr><td>SOL-USD</td><td>31</td><td>Solana-based trading market.</td></tr></tbody></table>

### API Endponit URL:

#### ✅ **Testnet API  Endpoint URL**

```typescript
https://perps-tradeapi.kanalabs.io
```

#### ✅ **Mainnet API Endpoint URL**

```typescript
https://perps-tradeapi.kana.trade
```

### **API** **Examples:**&#x20;

[Typescript REST API Examples](https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/kana-perps-typescript-rest-api)

[Python REST API Examples](https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/kana-perps-python-rest-api)

### **WebSocket URL:**

#### ✅ **Testnet WebSocket URL**

```typescript
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

#### ✅ **Mainnet WebSocket URL**

```typescript
wss://perpetuals-indexer-ws.kana.trade/ws/
```

### **Websocket Connection Endpoints Link:**&#x20;

[WebSocket Connection](https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/websocket-connection)


# For Developers & MMs


# Installation setup

## Prerequisites

Before using the API, ensure you have the following installed:

* **Node.js** (version 18 or higher)
* **npm** (for package management)

## Installation

Install required dependencies with these commands:

```bash
npm install dotenv axios @aptos-labs/ts-sdk
```

### Aptos Client & Account Setup

Configure your TypeScript environment with this template:

```typescript
// Import required packages
import dotenv from 'dotenv';
import axios from 'axios';
import { 
  AptosConfig, 
  Aptos, 
  Network, 
  Account, 
  Ed25519PrivateKey, 
  PrivateKeyVariants 
} from "@aptos-labs/ts-sdk";

// Load environment variables
dotenv.config();

// Initialize Aptos client
const config = new AptosConfig({ network: Network.TESTNET });
const aptos = new Aptos(config);

// Configure account
const formattedPrivateKey = PrivateKey.formatPrivateKey(
  process.env.APTOS_PRIVATEKEY || '',
  'ed25519' as PrivateKeyVariants
);

const account = Account.fromPrivateKey({
  privateKey: new Ed25519PrivateKey(formattedPrivateKey),
});
```


# Available Markets

The list of markets available to trade.

### Aptos Mainnet

<table data-header-hidden><thead><tr><th></th><th width="282"></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td></tr><tr><td>Aptos (APT)</td><td>14</td></tr><tr><td>Bitcoin (BTC)</td><td>15</td></tr><tr><td>Ethereum (ETH)</td><td>16</td></tr><tr><td>Coming soon...</td><td>xx</td></tr></tbody></table>

### Aptos Testnet

<table data-header-hidden><thead><tr><th></th><th width="282"></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td></tr><tr><td>Aptos (APT)</td><td>1338</td></tr><tr><td>Bitcoin (BTC)</td><td>1339</td></tr><tr><td>Ethereum (ETH)</td><td>1340</td></tr><tr><td>Coming soon...</td><td>xxxx</td></tr></tbody></table>


# Integrating REST APIs

### API Integration

* [Typescript](/perpetual-futures/kana-perps/for-developers-and-mms/integrating-rest-apis/typescript)
* [Python](/perpetual-futures/kana-perps/for-developers-and-mms/integrating-rest-apis/python)


# Typescript

### Table of Contents

1. [Base URLs](#base-urls)
2. [Authentication](#authentication)
3. [Core Concepts](#core-concepts)
4. [Account Management](#account-management)
5. [Market Data](#market-data)
6. [Order Management](#order-management)
7. [Position Management](#trade-history)
8. [Trade History](#trade-history)
9. [Utility Endpoints](#utility-endpoints)

### Base URLs

```typescript
const BASE_URLS = {
  TESTNET: "https://perps-tradeapi.kanalabs.io",
  MAINNET: "https://perps-tradeapi.kana.trade"
};
```

### Authentication

All endpoints require an API key passed in the headers:

```typescript
headers: {
  'x-api-key': process.env.API_KEY
}
```

### Core Concepts

#### Profile Address

All on-chain trades are executed using your profile address, not your wallet address. You must fetch your profile address first.

**Endpoint**: `GET /getProfileAddress`

```typescript
async function getProfileAddress(userAddress: string): Promise<string> {
  const response = await axios.get(`${BASE_URL}/getProfileAddress`, {
    params: { userAddress },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

### Account Management

#### Get Wallet Balance

**Endpoint**: `GET /getWalletAccountBalance`

```typescript
async function getWalletBalance(userAddress: string): Promise<number> {
  const response = await axios.get(`${BASE_URL}/getWalletAccountBalance`, {
    params: { userAddress },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

#### Get Profile Balance

**Endpoint**: `GET /getProfileBalanceSnapshot`

```typescript
async function getProfileBalance(userAddress: string): Promise<number> {
  const response = await axios.get(`${BASE_URL}/getProfileBalanceSnapshot`, {
    params: { userAddress },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

Get Net Profile Balance

This endpoint returns the net profile balance, which includes both the available balance in trading account and any pending balances from closed positions on all markets.

**Endpoint**: `GET /getNetProfileBalance`

```typescript
async function getNetProfileBalance(userAddress: string): Promise<number> {
  const response = await axios.get(`${BASE_URL}/getNetProfileBalance`, {
    params: { userAddress },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

#### Deposit Funds

**Endpoint**: `GET /deposit`

```typescript
async function depositFunds(userAddress: string, amount: number): Promise<void> {
  const response = await axios.get(`${BASE_URL}/deposit`, {
    params: { userAddress, amount },
    headers: { 'x-api-key': API_KEY }
  });
  
  const payload = response.data.data;
  const transaction = await aptos.transaction.build.simple({
    sender: userAddress,
    data: payload
  });
  await aptos.transaction.signAndSubmitTransaction({
    transaction,
    signer: account
  });
}
```

#### Withdraw Funds

**Endpoint**: `GET /withdrawSpecifiMarket`

```typescript
async function withdrawFunds(
  userAddress: string, 
  marketId: number, 
  amount: number
): Promise<void> {
  const response = await axios.get(`${BASE_URL}/withdrawSpecifiMarket`, {
    params: { userAddress, marketId, amount },
    headers: { 'x-api-key': API_KEY }
  });
  
  const payload = response.data.data;
  const transaction = await aptos.transaction.build.simple({
    sender: userAddress,
    data: payload
  });
  const committedTxn = await aptos.transaction.signAndSubmitTransaction({
    transaction,
    signer: account
  });
  await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
  return committedTxn.hash
}
```

### Market Data

#### Get Market Info

**Endpoint**: `GET /getMarketInfo`

```typescript
async function getMarketInfo(marketId: number): Promise<void> {
  const response = await axios.get(`${BASE_URL}/getMarketInfo`, {
    params: { marketId },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

#### Get Market Price

**Endpoint**: `GET /getMarketPrice`

```typescript
async function getMarketPrice(marketId: number): Promise<void> {
  const response = await axios.get(`${BASE_URL}/getMarketPrice`, {
    params: { marketId },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

#### Get Last Execution Price

**Endpoint**: `GET /getLastPlacedPrice`

```typescript
async function getLastExecutionPrice(marketId: number): Promise<number> {
  const response = await axios.get(`${BASE_URL}/getLastPlacedPrice`, {
    params: { marketId },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

#### Get Perpetual Market Info

Retrieves information about perpetual market, optionally filtered by market ID or base name.

**Endpoint**: `GET /getPerpetualAssetsInfo`

```typescript
async function getAssetInfo(marketId?: number, baseName?: string): Promise<any> {
  const response = await axios.get(`${BASE_URL}/getPerpetualAssetsInfo`, {
    params: { marketId, baseName },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

#### Get All Markets

Retrieves information about all available markets.

**Endpoint**: `GET /getPerpetualAssetsInfo/allMarkets`

```python
async function getAllMarkets(): Promise<any[]> {
  const response = await axios.get(`${BASE_URL}/getPerpetualAssetsInfo/allMarkets`, {
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

### Order Management

#### Place Limit Order

Places a limit order on the exchange.

**Endpoint**: `GET /placeLimitOrder`

```typescript
interface PlaceLimitOrderParams {
  marketId: number;
  tradeSide: boolean; // true = long, false = short
  direction: boolean; // false = open, true = close
  size: number;
  price: number;
  leverage: number;
  restriction?: number; // optional
  takeProfit?: number;  // optional
  stopLoss?: number;    // optional
}

async function placeLimitOrder(params: PlaceLimitOrderParams): Promise<void> {
  const response = await axios.get(`${BASE_URL}/placeLimitOrder`, {
    params,
    headers: { 'x-api-key': API_KEY }
  });
  
  const payload = response.data.data;
  const transaction = await aptos.transaction.build.simple({
    sender: userAddress,
    data: payload
  });
  await aptos.transaction.signAndSubmitTransaction({
    transaction,
    signer: account
  });
}
```

#### Place Market Order

**Endpoint**: `GET /placeMarketOrder`

```typescript
interface PlaceMarketOrderParams {
  marketId: number;
  tradeSide: boolean; // true = long, false = short
  direction: boolean; // false = open, true = close
  size: number;
  leverage: number;
  restriction?: number; // optional
  takeProfit?: number;  // optional
  stopLoss?: number;    // optional
}
async function placeMarketOrder(params: PlaceMarketOrderParams): Promise<void> {
  const response = await axios.get(`${BASE_URL}/placeMarketOrder`, {
    params,
    headers: { 'x-api-key': API_KEY }
  });
  
  const payload = response.data.data;
  const transaction = await aptos.transaction.build.simple({
    sender: userAddress,
    data: payload
  });
  await aptos.transaction.signAndSubmitTransaction({
    transaction,
    signer: account
  });
}
```

#### Place Multiple Orders

Places multiple orders in a single transaction.

**Endpoint**: `POST /placeMultipleOrders`

```typescript
interface PlaceMultipleOrdersParams {
    marketId: number;
    orderTypes: boolean[]; // true = limit, false = market
    tradeSides: boolean[]; // true = long, false = short
    directions: boolean[]; // false = open, true = close
    sizes: number[];
    prices: number[];
    leverages: number[];
    restrictions?: any[]; // optional
    takeProfits?: any[]; // optional
    stopLosses?: any[]; // optional
}
async function PlaceMultipleOrders(params: PlaceMarketOrdersParams): Promise<void> {
  const response = await axios.get(`${BASE_URL}/placeMultipleOrders`, {
    params,
    headers: { 'x-api-key': API_KEY }
  });
  
  const payload = response.data.data;
  const transaction = await aptos.transaction.build.simple({
    sender: userAddress,
    data: payload
  });
  await aptos.transaction.signAndSubmitTransaction({
    transaction,
    signer: account
  });
}
```

#### Cancel Orders

**Endpoint**: `POST /cancelMultipleOrders`

```typescript
async function cancelMultipleOrders(
  marketId: number,
  orderIds: string[],
  orderSides: boolean[]
): Promise<void> {
  const response = await axios.post(`${BASE_URL}/cancelMultipleOrders`, {
    marketId,
    cancelOrderIds: orderIds,
    orderSides
  }, {
    headers: { 
      'x-api-key': API_KEY,
      'Content-Type': 'application/json'
    }
  });
  
  const payload = response.data.data;
  const transaction = await aptos.transaction.build.simple({
    sender: userAddress,
    data: payload
  });
  await aptos.transaction.signAndSubmitTransaction({
    transaction,
    signer: account
  });
}
```

#### Cancel And Place Multiple Orders

**Endpoint**: `POST /cancelAndPlaceMultipleOrders`

```typescript
interface CancelAndPlaceMultipleOrdersParams {
    marketId: number;
    cancelOrderIds: any[];
    orderSides: boolean[]; // true = long, false = short
    orderTypes: boolean[]; // true = limit, false = market
    tradeSides: boolean[]; // true = long, false = short
    directions: boolean[]; // false = open, true = close
    sizes: number[];
    prices: number[];
    leverages: number[];
    restrictions?: any[]; // optional
    takeProfits?: any[]; // optional
    stopLosses?: any[]; // optional
}
async function cancelAndPlaceMultipleOrders(params: CancelAndPlaceMultipleOrdersParams): Promise<void> {
  const response = await axios.get(`${BASE_URL}/cancelAndPlaceMultipleOrders`, {
    params,
    headers: { 'x-api-key': API_KEY }
  });
  
  const payload = response.data.data;
  const transaction = await aptos.transaction.build.simple({
    sender: userAddress,
    data: payload
  });
  await aptos.transaction.signAndSubmitTransaction({
    transaction,
    signer: account
  });
}
```

### Position Management

#### Get Positions

**Endpoint**: `GET /getPositions`

```typescript
interface Position {
  market_id: string;
  leverage: number;
  size: string;
  entry_price: string;
  liq_price: string;
  // ... other fields
}

async function getPositions(userAddress: string, marketId?: number): Promise<Position[]> {
  const response = await axios.get(`${BASE_URL}/getPositions`, {
    params: { userAddress, marketId },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

#### Update Take Profit

**Endpoint**: `GET /updateTakeProfit`

```typescript
async function updateTakeProfit(
  marketId: number,
  tradeSide: boolean,
  newTakeProfitPrice: number
): Promise<void> {
  const response = await axios.get(`${BASE_URL}/updateTakeProfit`, {
    params: { marketId, tradeSide, newTakeProfitPrice },
    headers: { 'x-api-key': API_KEY }
  });
  
  const payload = response.data.data;
  const transaction = await aptos.transaction.build.simple({
    sender: userAddress,
    data: payload
  });
  await aptos.transaction.signAndSubmitTransaction({
    transaction,
    signer: account
  });
}
```

#### Update Stop Loss

**Endpoint**: `GET /updateStopLoss`

```typescript
async function updateStopLoss(
  marketId: number,
  tradeSide: boolean,
  newStopLossPrice: number
): Promise<void> {
  const response = await axios.get(`${BASE_URL}/updateStopLoss`, {
    params: { marketId, tradeSide, newStopLossPrice },
    headers: { 'x-api-key': API_KEY }
  });
  
  const payload = response.data.data;
  const transaction = await aptos.transaction.build.simple({
    sender: userAddress,
    data: payload
  });
  await aptos.transaction.signAndSubmitTransaction({
    transaction,
    signer: account
  });
}
```

### Trade History

#### Get Open Orders

**Endpoint**: `GET /getOpenOrders`

```typescript
interface OpenOrder {
  market_id: string;
  price: string;
  size: string;
  order_type: number; // see order_type explanation
  // ... other fields
}

async function getOpenOrders(userAddress: string, marketId?: number): Promise<OpenOrder[]> {
  const response = await axios.get(`${BASE_URL}/getOpenOrders`, {
    params: { userAddress, marketId },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

Get All Open Order Ids

**Endpoint**: `GET /getAllOpenOrderIds`

```typescript
async function getAllOpenOrderIds(userAddress: string, marketId: number): Promise<any[]> {
  const response = await axios.get(`${BASE_URL}/getAllOpenOrderIds`, {
    params: { userAddress, marketId },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

Get Order Status By Order Id

**Endpoint**: `GET /getOrderStatusByOrderId`

```typescript
async function getOrderStatusByOrderId(marketId: number, orderId: string): Promise<any[]> {
  const response = await axios.get(`${BASE_URL}/getOrderStatusByOrderId`, {
    params: { marketId, orderId },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

#### Get Order History

**Endpoint**: `GET /getOrderHistory`

```typescript
async function getOrderHistory(userAddress: string, marketId?: number): Promise<any[]> {
  const response = await axios.get(`${BASE_URL}/getOrderHistory`, {
    params: { userAddress, marketId },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

#### Get All Trades

**Endpoint**: `GET /getAllTrades`

```typescript
async function getAllTrades(marketId: number): Promise<any[]> {
  const response = await axios.get(`${BASE_URL}/getAllTrades`, {
    params: { marketId },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data;
}
```

#### Collapse Position

**Endpoint**: `GET /collapsePosition`

```typescript
async function collapsePosition(
  marketId: number
): Promise<void> {
  const response = await axios.get(`${BASE_URL}/collapsePosition`, {
    params: { marketId },
    headers: { 'x-api-key': API_KEY }
  });
  
  const payload = response.data.data;
  const transaction = await aptos.transaction.build.simple({
    sender: userAddress,
    data: payload
  });
  await aptos.transaction.signAndSubmitTransaction({
    transaction,
    signer: account
  });
}
```

#### Add Margin

**Endpoint**: `GET /addMargin`

```typescript
async function addMargin(
  marketId: number,
  tradeSide: boolean,
  amount: number
): Promise<void> {
  const response = await axios.get(`${BASE_URL}/addMargin`, {
    params: { marketId, tradeSide, amount },
    headers: { 'x-api-key': API_KEY }
  });
  
  const payload = response.data.data;
  const transaction = await aptos.transaction.build.simple({
    sender: userAddress,
    data: payload
  });
  await aptos.transaction.signAndSubmitTransaction({
    transaction,
    signer: account
  });
}
```

**Settle Pnl**

This API returns a transaction payload used to manually (or automatically, on user interactions) refresh the user's position and settle the Pnl for a specific market, allowing the user to claim any unreleased Pnl.

**Endpoint**: `GET /settlePnl`

```typescript
async function settlePnl(
  marketId: number,
  userAddress: string
): Promise<void> {
  const response = await axios.get(`${BASE_URL}/settlePnl`, {
    params: { marketId, userAddress },
    headers: { 'x-api-key': API_KEY }
  });
  
  const payload = response.data.data;
  const transaction = await aptos.transaction.build.simple({
    sender: userAddress,
    data: payload
  });
  await aptos.transaction.signAndSubmitTransaction({
    transaction,
    signer: account
  });
}
```

### Utility Endpoints

#### Get Account APT Balance

**Endpoint**: `GET /getAccountAptBalance`

```typescript
async function getAptBalance(userAddress: string): Promise<number> {
  const response = await axios.get(`${BASE_URL}/getAccountAptBalance`, {
    params: { userAddress },
    headers: { 'x-api-key': API_KEY }
  });
  return response.data.data;
}
```

### Helper Types

```typescript
// Order type explanations
enum OrderType {
  OPEN_LONG = 1,
  OPEN_SHORT = 2,
  INCREASE_LONG = 3,
  INCREASE_SHORT = 4,
  DECREASE_LONG = 5,
  DECREASE_SHORT = 6,
  CLOSE_LONG = 7,
  CLOSE_SHORT = 8
}

// Restriction types
enum RestrictionType {
  NO_RESTRICTION = 0,
  FILL_OR_ABORT = 1,
  POST_OR_ABORT = 3
}
```


# Python

### Table of Contents

1. [Base URLs](#base-urls)
2. [Authentication](#authentication)
3. [Core Concepts](#core-concepts)
4. [Account Management](#account-management)
5. [Market Data](#market-data)
6. [Order Management](#order-management)
7. [Position Management](#position-management)
8. [Trade History](#trade-history)
9. [Utility Endpoints](#utility-endpoints)

### Base URLs

```markdown
BASE_URLS = {
    "TESTNET": "https://perps-tradeapi.kanalabs.io",
    "MAINNET": "https://perps-tradeapi.kana.trade"
}

NODE_URLS = {
    "TESTNET": "https://api.testnet.aptoslabs.com/v1",
    "MAINNET": "https://api.mainnet.aptoslabs.com/v1"
}
```

### Authentication

All endpoints require an API key in the request headers:

```python
import os
from dotenv import load_dotenv

load_dotenv()

headers = {"x-api-key": os.getenv("API_KEY")}
```

### Core Concepts

#### Profile Address

On-chain trades use a profile address rather than a wallet address. You can fetch it using the `/getProfileAddress` endpoint.

**Endpoint**: `GET /getProfileAddress`

```python
import requests

def get_profile_address(base_url, user_address):
    response = requests.get(
        f"{base_url}/getProfileAddress", 
        params={"userAddress": user_address}, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

### Account Management

#### Get Wallet Balance

Retrieves the wallet balance for a given user address.

**Endpoint**: `GET /getWalletAccountBalance`

```python
def get_wallet_balance(base_url, user_address):
    response = requests.get(
        f"{base_url}/getWalletAccountBalance", 
        params={"userAddress": user_address}, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

#### Get Profile Balance

Retrieves the profile balance snapshot for a given user address.

**Endpoint**: `GET /getProfileBalanceSnapshot`

```python
def get_profile_balance(base_url, user_address):
    response = requests.get(
        f"{base_url}/getProfileBalanceSnapshot", 
        params={"userAddress": user_address}, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

Get Net Profile Balance

This endpoint returns the net profile balance, which includes both the available balance in trading account and any pending balances from closed positions on all markets.

**Endpoint**: `GET /getNetProfileBalance`

```python
def get_net_profile_balance(base_url, user_address):
    response = requests.get(
        f"{base_url}/getNetProfileBalance", 
        params={"userAddress": user_address}, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

#### Deposit Funds

Deposits funds from wallet to trading profile.

**Endpoint**: `GET /deposit`

```python
import asyncio
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionPayload
from aptos_sdk.bcs import Serializer

async def deposit_funds(base_url, node_url, user_address, amount, private_key):
    response = requests.get(
        f"{base_url}/deposit", 
        params={"userAddress": user_address, "amount": amount}, 
        headers=headers
    )
    response.raise_for_status()
    payload = response.json()["data"]

    rest_client = RestClient(node_url)
    account = Account.load_key(bytes.fromhex(private_key.lstrip("0x")))
    
    payload["functionArguments"] = [user_address, int(payload["functionArguments"][1])]
    payload["argumentTypes"] = [Serializer.struct, Serializer.u64]
    
    module, function_id = payload["function"].split("::")[:-1], payload["function"].split("::")[-1]
    entry_function = EntryFunction.natural(
        "::".join(module), 
        function_id, 
        [], 
        [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]
    )
    
    transaction = await rest_client.create_bcs_signed_transaction(account, TransactionPayload(entry_function))
    txn_hash = await rest_client.submit_bcs_transaction(transaction)
    await rest_client.wait_for_transaction(txn_hash)
    return txn_hash
```

#### Withdraw Funds

Withdraws funds from trading profile to wallet for a specific market.

**Endpoint**: `GET /withdrawSpecifiMarket`

```python
async def withdraw_funds(base_url, node_url, user_address, market_id, amount, private_key):
    response = requests.get(
        f"{base_url}/withdrawSpecifiMarket", 
        params={"userAddress": user_address, "marketId": market_id, "amount": amount}, 
        headers=headers
    )
    response.raise_for_status()
    payload = response.json()["data"]

    rest_client = RestClient(node_url)
    account = Account.load_key(bytes.fromhex(private_key.lstrip("0x")))
    
    payload["functionArguments"] = [user_address, int(payload["functionArguments"][1]), int(payload["functionArguments"][2])]
    payload["argumentTypes"] = [Serializer.struct, Serializer.u64, Serializer.u64]
    
    module, function_id = payload["function"].split("::")[:-1], payload["function"].split("::")[-1]
    entry_function = EntryFunction.natural(
        "::".join(module), 
        function_id, 
        [], 
        [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]
    )
    
    transaction = await rest_client.create_bcs_signed_transaction(account, TransactionPayload(entry_function))
    txn_hash = await rest_client.submit_bcs_transaction(transaction)
    await rest_client.wait_for_transaction(txn_hash)
    return txn_hash
```

### Market Data

#### Get Market Info

Retrieves information about a specific market.

**Endpoint**: `GET /getMarketInfo`

```python
def get_market_info(base_url, market_id):
    response = requests.get(
        f"{base_url}/getMarketInfo", 
        params={"marketId": market_id}, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"][0]
```

#### Get Market Price

Gets the current price for a specific market.

**Endpoint**: `GET /getMarketPrice`

```python
def get_market_price(base_url, market_id):
    response = requests.get(
        f"{base_url}/getMarketPrice", 
        params={"marketId": market_id}, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

#### Get Last Execution Price

Retrieves the last execution price for a market.

**Endpoint**: `GET /getLastPlacedPrice`

```python
def get_last_execution_price(base_url, market_id):
    response = requests.get(
        f"{base_url}/getLastPlacedPrice", 
        params={"marketId": market_id}, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

#### Get Perpetual Market Info

Retrieves information about perpetual assets, optionally filtered by market ID or base name.

**Endpoint**: `GET /getPerpetualAssetsInfo`

```python
def get_perpetual_assets_info(base_url, market_id=None, base_name=None):
    params = {}
    if market_id:
        params["marketId"] = market_id
    if base_name:
        params["baseName"] = base_name
    response = requests.get(
        f"{base_url}/getPerpetualAssetsInfo", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

#### Get All Markets

Retrieves information about all available markets.

**Endpoint**: `GET /getPerpetualAssetsInfo/allMarkets`

```python
def get_all_markets(base_url):
    response = requests.get(
        f"{base_url}/getPerpetualAssetsInfo/allMarkets", 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

### Order Management

#### Place Limit Order

Places a limit order on the exchange.

**Endpoint**: `GET /placeLimitOrder`

```python
async def place_limit_order(base_url, node_url, params, private_key):
    response = requests.get(
        f"{base_url}/placeLimitOrder", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    payload = response.json()["data"]

    rest_client = RestClient(node_url)
    account = Account.load_key(bytes.fromhex(private_key.lstrip("0x")))
    
    payload["functionArguments"] = [
        int(payload["functionArguments"][0]),
        payload["functionArguments"][1].lower() == "true",
        payload["functionArguments"][2].lower() == "true",
        *map(int, payload["functionArguments"][3:])
    ]
    payload["argumentTypes"] = [
        Serializer.u64, Serializer.bool, Serializer.bool, 
        Serializer.u64, Serializer.u64, Serializer.u64, 
        Serializer.u8, Serializer.u64, Serializer.u64
    ]
    
    module, function_id = payload["function"].split("::")[:-1], payload["function"].split("::")[-1]
    entry_function = EntryFunction.natural(
        "::".join(module), 
        function_id, 
        [], 
        [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]
    )
    
    transaction = await rest_client.create_bcs_signed_transaction(account, TransactionPayload(entry_function))
    txn_hash = await rest_client.submit_bcs_transaction(transaction)
    await rest_client.wait_for_transaction(txn_hash)
    return txn_hash
```

#### Place Market Order

Places a market order on the exchange.

**Endpoint**: `GET /placeMarketOrder`

```python
async def place_market_order(base_url, node_url, params, private_key):
    response = requests.get(
        f"{base_url}/placeMarketOrder", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    payload = response.json()["data"]

    rest_client = RestClient(node_url)
    account = Account.load_key(bytes.fromhex(private_key.lstrip("0x")))
    
    payload["functionArguments"] = [
        int(payload["functionArguments"][0]),
        payload["functionArguments"][1].lower() == "true",
        payload["functionArguments"][2].lower() == "true",
        *map(int, payload["functionArguments"][3:])
    ]
    payload["argumentTypes"] = [Serializer.u64, Serializer.bool, Serializer.bool] + [Serializer.u64] * (len(payload["functionArguments"]) - 3)
    
    module, function_id = payload["function"].split("::")[:-1], payload["function"].split("::")[-1]
    entry_function = EntryFunction.natural(
        "::".join(module), 
        function_id, 
        [], 
        [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]
    )
    
    transaction = await rest_client.create_bcs_signed_transaction(account, TransactionPayload(entry_function))
    txn_hash = await rest_client.submit_bcs_transaction(transaction)
    await rest_client.wait_for_transaction(txn_hash)
    return txn_hash
```

#### Place Multiple Orders

Places multiple orders in a single transaction.

**Endpoint**: `POST /placeMultipleOrders`

```python
async def place_multiple_orders(base_url, node_url, body, private_key):
    response = requests.post(
        f"{base_url}/placeMultipleOrders", 
        json=body, 
        headers=headers
    )
    response.raise_for_status()
    payload = response.json()["data"]

    rest_client = RestClient(node_url)
    account = Account.load_key(bytes.fromhex(private_key.lstrip("0x")))
    
    payload["argumentTypes"] = [
        Serializer.u64,
        Serializer.sequence_serializer(Serializer.bool),
        Serializer.sequence_serializer(Serializer.bool),
        Serializer.sequence_serializer(Serializer.bool),
        Serializer.sequence_serializer(Serializer.u64),
        Serializer.sequence_serializer(Serializer.u64),
        Serializer.sequence_serializer(Serializer.u64),
        Serializer.sequence_serializer(Serializer.u8),
        Serializer.sequence_serializer(Serializer.u64),
        Serializer.sequence_serializer(Serializer.u64)
    ]
    
    module, function_id = payload["function"].split("::")[:-1], payload["function"].split("::")[-1]
    entry_function = EntryFunction.natural(
        "::".join(module), 
        function_id, 
        [], 
        [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]
    )
    
    transaction = await rest_client.create_bcs_signed_transaction(account, TransactionPayload(entry_function))
    txn_hash = await rest_client.submit_bcs_transaction(transaction)
    await rest_client.wait_for_transaction(txn_hash)
    return txn_hash
```

#### Cancel Multiple Orders

Cancels multiple orders in a single transaction.

**Endpoint**: `POST /cancelMultipleOrders`

```python
async def cancel_multiple_orders(base_url, node_url, body, private_key):
    response = requests.post(
        f"{base_url}/cancelMultipleOrders", 
        json=body, 
        headers=headers
    )
    response.raise_for_status()
    payload = response.json()["data"]
    payload["functionArguments"][1] = [int(x) for x in payload["functionArguments"][1]]

    rest_client = RestClient(node_url)
    account = Account.load_key(bytes.fromhex(private_key.lstrip("0x")))
    
    payload["argumentTypes"] = [
        Serializer.u64,
        Serializer.sequence_serializer(Serializer.u128),
        Serializer.sequence_serializer(Serializer.bool)
    ]
    
    module, function_id = payload["function"].split("::")[:-1], payload["function"].split("::")[-1]
    entry_function = EntryFunction.natural(
        "::".join(module), 
        function_id, 
        [], 
        [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]
    )
    
    transaction = await rest_client.create_bcs_signed_transaction(account, TransactionPayload(entry_function))
    txn_hash = await rest_client.submit_bcs_transaction(transaction)
    await rest_client.wait_for_transaction(txn_hash)
    return txn_hash
```

#### Cancel and Place Multiple Orders

Cancels existing orders and places new ones in a single transaction.

**Endpoint**: `POST /cancelAndPlaceMultipleOrders`

```python
async def cancel_and_place_multiple_orders(base_url, node_url, body, private_key):
    response = requests.post(
        f"{base_url}/cancelAndPlaceMultipleOrders", 
        json=body, 
        headers=headers
    )
    response.raise_for_status()
    payload = response.json()["data"]
    payload["functionArguments"][1] = [int(x) for x in payload["functionArguments"][1]]

    rest_client = RestClient(node_url)
    account = Account.load_key(bytes.fromhex(private_key.lstrip("0x")))
    
    payload["argumentTypes"] = [
        Serializer.u64,
        Serializer.sequence_serializer(Serializer.u128),
        Serializer.sequence_serializer(Serializer.bool),
        Serializer.sequence_serializer(Serializer.bool),
        Serializer.sequence_serializer(Serializer.bool),
        Serializer.sequence_serializer(Serializer.bool),
        Serializer.sequence_serializer(Serializer.u64),
        Serializer.sequence_serializer(Serializer.u64),
        Serializer.sequence_serializer(Serializer.u64),
        Serializer.sequence_serializer(Serializer.u8),
        Serializer.sequence_serializer(Serializer.u64),
        Serializer.sequence_serializer(Serializer.u64)
    ]
    
    module, function_id = payload["function"].split("::")[:-1], payload["function"].split("::")[-1]
    entry_function = EntryFunction.natural(
        "::".join(module), 
        function_id, 
        [], 
        [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]
    )
    
    transaction = await rest_client.create_bcs_signed_transaction(account, TransactionPayload(entry_function))
    txn_hash = await rest_client.submit_bcs_transaction(transaction)
    await rest_client.wait_for_transaction(txn_hash)
    return txn_hash
```

### Position Management

#### Get Positions

Retrieves current positions for a user, optionally filtered by market ID.

**Endpoint**: `GET /getPositions`

```python
def get_positions(base_url, user_address, market_id=None):
    params = {"userAddress": user_address}
    if market_id:
        params["marketId"] = market_id
    response = requests.get(
        f"{base_url}/getPositions", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

#### Update Take Profit

Updates the take profit price for a position.

**Endpoint**: `GET /updateTakeProfit`

```python
async def update_take_profit(base_url, node_url, market_id, trade_side, new_take_profit_price, private_key):
    params = {
        "marketId": market_id, 
        "tradeSide": trade_side, 
        "newTakeProfitPrice": new_take_profit_price
    }
    response = requests.get(
        f"{base_url}/updateTakeProfit", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    payload = response.json()["data"]

    rest_client = RestClient(node_url)
    account = Account.load_key(bytes.fromhex(private_key.lstrip("0x")))
    
    payload["functionArguments"] = [
        int(payload["functionArguments"][0]),
        payload["functionArguments"][1].lower() == "true",
        int(payload["functionArguments"][2])
    ]
    payload["argumentTypes"] = [Serializer.u64, Serializer.bool, Serializer.u64]
    
    module, function_id = payload["function"].split("::")[:-1], payload["function"].split("::")[-1]
    entry_function = EntryFunction.natural(
        "::".join(module), 
        function_id, 
        [], 
        [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]
    )
    
    transaction = await rest_client.create_bcs_signed_transaction(account, TransactionPayload(entry_function))
    txn_hash = await rest_client.submit_bcs_transaction(transaction)
    await rest_client.wait_for_transaction(txn_hash)
    return txn_hash
```

#### Update Stop Loss

Updates the stop loss price for a position.

**Endpoint**: `GET /updateStopLoss`

```python
async def update_stop_loss(base_url, node_url, market_id, trade_side, new_stop_loss_price, private_key):
    params = {
        "marketId": market_id, 
        "tradeSide": trade_side, 
        "newStopLossPrice": new_stop_loss_price
    }
    response = requests.get(
        f"{base_url}/updateStopLoss", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    payload = response.json()["data"]

    rest_client = RestClient(node_url)
    account = Account.load_key(bytes.fromhex(private_key.lstrip("0x")))
    
    payload["functionArguments"] = [
        int(payload["functionArguments"][0]),
        payload["functionArguments"][1].lower() == "true",
        int(payload["functionArguments"][2])
    ]
    payload["argumentTypes"] = [Serializer.u64, Serializer.bool, Serializer.u64]
    
    module, function_id = payload["function"].split("::")[:-1], payload["function"].split("::")[-1]
    entry_function = EntryFunction.natural(
        "::".join(module), 
        function_id, 
        [], 
        [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]
    )
    
    transaction = await rest_client.create_bcs_signed_transaction(account, TransactionPayload(entry_function))
    txn_hash = await rest_client.submit_bcs_transaction(transaction)
    await rest_client.wait_for_transaction(txn_hash)
    return txn_hash
```

#### Collapse Position

Closes a position immediately at market price.

**Endpoint**: `GET /collapsePosition`

```python
async def collapse_position(base_url, node_url, market_id, private_key):
    response = requests.get(
        f"{base_url}/collapsePosition", 
        params={"marketId": market_id}, 
        headers=headers
    )
    response.raise_for_status()
    payload = response.json()["data"]

    rest_client = RestClient(node_url)
    account = Account.load_key(bytes.fromhex(private_key.lstrip("0x")))
    
    payload["functionArguments"] = [int(payload["functionArguments"][0])]
    payload["argumentTypes"] = [Serializer.u64]
    
    module, function_id = payload["function"].split("::")[:-1], payload["function"].split("::")[-1]
    entry_function = EntryFunction.natural(
        "::".join(module), 
        function_id, 
        [], 
        [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]
    )
    
    transaction = await rest_client.create_bcs_signed_transaction(account, TransactionPayload(entry_function))
    txn_hash = await rest_client.submit_bcs_transaction(transaction)
    await rest_client.wait_for_transaction(txn_hash)
    return txn_hash
```

### Trade History

#### Get Open Orders

Retrieves all open orders for a user, optionally filtered by market ID.

**Endpoint**: `GET /getOpenOrders`

```python
def get_open_orders(base_url, user_address, market_id=None):
    params = {"userAddress": user_address}
    if market_id:
        params["marketId"] = market_id
    response = requests.get(
        f"{base_url}/getOpenOrders", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

Get All Open Order Ids

**Endpoint**: `GET /getAllOpenOrderIds`

```python
def get_all_open_order_ids(base_url, user_address, market_id=None):
    params = {"userAddress": user_address}
    if market_id:
        params["marketId"] = market_id
    response = requests.get(
        f"{base_url}/getAllOpenOrderIds", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

Get Order Status By Order Id

**Endpoint**: `GET /getOrderStatusByOrderId`

```typescript
def get_order_status_by_order_id(base_url, market_id, order_id):
    params = {"marketId": market_id, "orderId": order_id}
    response = requests.get(
        f"{base_url}/getOrderStatusByOrderId", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

#### Get Order History

Retrieves order history for a user, optionally filtered by market ID.

**Endpoint**: `GET /getOrderHistory`

```python
def get_order_history(base_url, user_address, market_id=None):
    params = {"userAddress": user_address}
    if market_id:
        params["marketId"] = market_id
    response = requests.get(
        f"{base_url}/getOrderHistory", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

#### Get All Trades

Retrieves all trades for a specific market.

**Endpoint**: `GET /getAllTrades`

```python
def get_all_trades(base_url, market_id):
    response = requests.get(
        f"{base_url}/getAllTrades", 
        params={"marketId": market_id}, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

#### Get Fills

Retrieves fill history for a specific market and address within a time range.

**Endpoint**: `GET /getFills`

```python
def get_fills(base_url, market_id, address, from_time, to_time, order_id=None):
    params = {
        "marketId": market_id, 
        "address": address, 
        "from": from_time, 
        "to": to_time
    }
    if order_id:
        params["orderId"] = order_id
    response = requests.get(
        f"{base_url}/getFills", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

#### Get Order Status by Order ID

Retrieves the status of a specific order by its ID.

**Endpoint**: `GET /getOrderStatusByOrderId`

```python
def get_order_status_by_order_id(base_url, market_id, order_id):
    response = requests.get(
        f"{base_url}/getOrderStatusByOrderId", 
        params={"marketId": market_id, "orderId": order_id}, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

#### Get All Open Order IDs

**Endpoint**: `GET /getAllOpenOrderIds`

```python
def get_all_open_order_ids(base_url, user_address, market_id=None):
    params = {"userAddress": user_address}
    if market_id:
        params["marketId"] = market_id
    response = requests.get(
        f"{base_url}/getAllOpenOrderIds", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

Retrieves all open order IDs for a user, optionally filtered by market ID.

#### Add Margin

**Endpoint**: `GET /addMargin`

```python
async def add_margin(base_url, node_url, market_id, trade_side, amount, private_key):
    params = {
        "marketId": market_id, 
        "tradeSide": trade_side, 
        "amount": amount
    }
    response = requests.get(
        f"{base_url}/addMargin", 
        params=params, 
        headers=headers
    )
    response.raise_for_status()
    payload = response.json()["data"]

    rest_client = RestClient(node_url)
    account = Account.load_key(bytes.fromhex(private_key.lstrip("0x")))
    
    payload["functionArguments"] = [
        int(payload["functionArguments"][0]),
        payload["functionArguments"][1].lower() == "true",
        int(payload["functionArguments"][2])
    ]
    payload["argumentTypes"] = [Serializer.u64, Serializer.bool, Serializer.u64]
    
    module, function_id = payload["function"].split("::")[:-1], payload["function"].split("::")[-1]
    entry_function = EntryFunction.natural(
        "::".join(module), 
        function_id, 
        [], 
        [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]
    )
    
    transaction = await rest_client.create_bcs_signed_transaction(account, TransactionPayload(entry_function))
    txn_hash = await rest_client.submit_bcs_transaction(transaction)
    await rest_client.wait_for_transaction(txn_hash)
    return txn_hash
```

**Settle Pnl**

This API returns a transaction payload used to manually (or automatically, on user interactions) refresh the user's position and settle the Pnl for a specific market, allowing the user to claim any unreleased Pnl.

**Endpoint**: `GET /settlePnl`

```python
async def settle_pnl(base_url, node_url, user_address, market_id, private_key):
    response = requests.get(
        f"{base_url}/settlePnl", 
        params={"userAddress": user_address, "marketId": market_id}, 
        headers=headers
    )
    response.raise_for_status()
    payload = response.json()["data"]

    rest_client = RestClient(node_url)
    account = Account.load_key(bytes.fromhex(private_key.lstrip("0x")))
    
    payload["functionArguments"] = [user_address, int(payload["functionArguments"][1])]
    payload["argumentTypes"] = [Serializer.struct, Serializer.u64]
    
    module, function_id = payload["function"].split("::")[:-1], payload["function"].split("::")[-1]
    entry_function = EntryFunction.natural(
        "::".join(module), 
        function_id, 
        [], 
        [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]
    )
    
    transaction = await rest_client.create_bcs_signed_transaction(account, TransactionPayload(entry_function))
    txn_hash = await rest_client.submit_bcs_transaction(transaction)
    await rest_client.wait_for_transaction(txn_hash)
    return txn_hash
```

### Utility Endpoints

#### Get Account APT Balance

Retrieves the APT balance for a user's account.

**Endpoint**: `GET /getAccountAptBalance`

```python
def get_account_apt_balance(base_url, user_address):
    response = requests.get(
        f"{base_url}/getAccountAptBalance", 
        params={"userAddress": user_address}, 
        headers=headers
    )
    response.raise_for_status()
    return response.json()["data"]
```

#### Helper Types

```python
# Order type constants
ORDER_TYPES = {
    "OPEN_LONG": 1,
    "OPEN_SHORT": 2,
    "INCREASE_LONG": 3,
    "INCREASE_SHORT": 4,
    "DECREASE_LONG": 5,
    "DECREASE_SHORT": 6,
    "CLOSE_LONG": 7,
    "CLOSE_SHORT": 8
}

# Order restriction types
RESTRICTION_TYPES = {
    "NO_RESTRICTION": 0,
    "FILL_OR_ABORT": 1,
    "POST_OR_ABORT": 3
}
```


# Walkthrough


# Integrating WebSockets

#### Important Note:

* To track transactions on-chain (e.g., via Aptos Explorer or Aptos Scan), you **must** use your [**profile address**](https://docs.kanalabs.io/perpetual-futures/kana-perps/for-developers-and-mms/pages/OKw87YCpbRTEWOkODG2z#id-1.-trade-profiles), as all on-chain trades are executed using this address.
* To obtain your profile address, call the **`/getProfileAddress`** endpoint with your wallet address as the `userAddress` parameter.

***

### WebSocket URLs

#### Testnet URL:

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

#### Mainnet URL:

```
wss://perpetuals-indexer-ws.kana.trade/ws/
```

***

### Parameters to Subscribe:

To connect to a WebSocket and subscribe to the relevant topics, send a subscription message in the following format:

#### Example:

```json
{
  "topic": "topic_name",
  "address": "user_address"
  "market_id": "market_id" (*only for getting orderbook)
}
```

You can replace `topic_name` with any of the supported topics (listed below), and `user_address` with your [profile address](https://docs.kanalabs.io/perpetual-futures/kana-perps/for-developers-and-mms/pages/OKw87YCpbRTEWOkODG2z#id-1.-trade-profiles).

***

## Available Topics

### 1. **Order History**

Track your order history with the following subscription:

```json
{
  "topic": "order_history",
  "address": "user_address"
}
```

#### Response:

```json
{
  "message": "order_history",
  "data": [
    {
      "address": "0x51f531abefc697845eabae4ba20c7cc26b1f849561bb016c4d90707c4ede1912",
      "order_id": "11905620858892513160724480",
      "market_id": "14",
      "order_type": 9,
      "is_market_order": true,
      "size": "10",
      "price": "5.75789140",
      "order_value": "57.57891400",
      "leverage": 20,
      "status": "Filled",
      "timestamp": 1747075649,
      "last_updated": 1747075650,
      "trade_id": "737648402019497550020622",
      "transaction_version": 2713317408
    }
    // ...more orders
  ]
}
```

### 2. **Deposit/Withdraw History**

Subscribe to track deposit and withdraw events:

```json
{
  "topic": "deposit_withdraw_history",
  "address": "user_address"
}
```

#### Response:

<pre class="language-json"><code class="lang-json"><strong>{
</strong>  "message": "deposit_withdraw_history",
  "data": [
    {
      "address": "0x51f531abefc697845eabae4ba20c7cc26b1f849561bb016c4d90707c4ede1912",
      "amount": "10",
      "is_deposit": true,
      "timestamp": 1745995346,
      "last_updated": 1746027625,
      "transaction_version": 2665483307
    }
    // ...more transactions
  ]
}
</code></pre>

### 3. **Trade History**

Subscribe to get updates on your past trades:

```json
{
  "topic": "trade_history",
  "address": "user_address"
}
```

#### Response:

```json
{
  "message": "trade_history",
  "data": [
    {
      "address": "0x51f531abefc697845eabae4ba20c7cc26b1f849561bb016c4d90707c4ede1912",
      "trade_id": "737648402019497550020622",
      "market_id": "14",
      "order_type": 9,
      "size": "10",
      "price": "5.75789140",
      "order_value": "57.57891400",
      "leverage": 20,
      "fee": "0.0287894570000000005993009656",
      "pnl": "-1.0143854570000000005993009656",
      "timestamp": 1747075649,
      "last_updated": 1747075650,
      "transaction_version": 2713317408
    }
    // ...more trades
  ]
}
```

#### 4. **Positions**

Subscribe to track your current positions:

```json
{
  "topic": "positions",
  "address": "user_address"
}
```

#### Response:

```json
{
  "message": "positions",
  "data": [
    {
      "address": "0xf05bbcfcb4b1cd144600ee179210d478ed141adb57dd6eb411ff85854f78d7aa",
      "market_id": "1338",
      "trade_id": "208485101521065352365370",
      "size": "6.90",
      "entry_price": "5.8370434782608695652173913043",
      "value": "40.27560",
      "leverage": 2,
      "margin": "20.08478",
      "liq_price": "3.001",
      "available_order_size": "6.90",
      "trade_side": true,
      "sl": null,
      "tp": null,
      "timestamp": 1747075629,
      "transaction_version": 6719222371
    }
    // ...more positions
  ]
}
```

#### 5. **Open Orders**

Track open orders in real-time:

```json
{
  "topic": "open_orders",
  "address": "user_address"
}
```

#### Response:

```json
{
  "message": "open_orders",
  "data": [
    {
      "address": "0x725c8b51b2c1b3d17336c48d75c56c19253f70e1de00e26c8138a29722d82da",
      "order_id": "55066334967796803229980238",
      "market_id": "1338",
      "order_type": 1,
      "price": "5.71",
      "total_size": "1",
      "remaining_size": "1",
      "order_value": "5.71",
      "leverage": 2,
      "timestamp": 1747078972,
      "last_updated": 1747078973,
      "trade_id": "210735604298057917662522",
      "transaction_version": 6719284743
    }
  ]
}
```

#### 6. **Orderbook**

Monitor the orderbook for a specific market:

```json
{
  "topic": "orderbook",
  "market_id": "market_id"
}
```

#### Response:

```json
{
  "message": "orderbook",
  "data": [
    {
      "market_id": "1338",
      "price": 5.768,
      "size": "487.649",
      "is_ask": true,
      "last_updated": 1747079061,
      "transaction_version": 6719285834
    }
    // ...more order book entries
  ]
}
```

#### 7. **Recent Trades**

Subscribe to view recent trades for a given market:

```json
{
  "topic": "recent_trades",
  "market_id": "market_id"
}
```

#### Response:

```json
{
  "message": "recent_trades",
  "data": [
    {
      "address": "0x2cdbf0dabbb0d769d2b01acd1b8b69a2712345044ff93e7d2d5fcb0cf7936842",
      "market_id": "1338",
      "trade_id": "95996856159584506611002",
      "order_type": 9,
      "price": "5.658",
      "size": "67",
      "order_value": "379.086",
      "leverage": 5,
      "fee": "0.1895430000000000039456563184",
      "pnl": "7.2094569999999999960543436821",
      "timestamp": 1747075851,
      "last_updated": 1747075852,
      "transaction_version": 6719250247
    }
    // ...more recent trades
  ]
}
```

#### 8. **Live Funding Rate**

Subscribe to view live funding rate:

```json
{
    "topic": "live_funding_rate"
}
```

#### Response:

```json
{
  "message": "live_funding_rate",
  "data": [
  {
    "funding_rate": "-0.0002642469135802469135802469",
    "funding_timestamp": 0,
    "last_updated": 1749453746,
    "market_id": "14",
    "transaction_timestamp": 1749453741,
    "transaction_version": 2848764162
  },
  {
    "funding_rate": "0",
    "funding_timestamp": 0,
    "last_updated": 1749453746,
    "market_id": "16",
    "transaction_timestamp": 1749453743,
    "transaction_version": 2848764254
  },
  {
    "funding_rate": "0",
    "funding_timestamp": 0,
    "last_updated": 1749453746,
    "market_id": "15",
    "transaction_timestamp": 1749453742,
    "transaction_version": 2848764211
  }
 ]
}
```

#### 9. **Live Order History**

Subscribe to view live order history for a given user address (It will update only latest single data):

```json
{
  "topic": "live_order_history",
  "address": "{{user_address}}"
}
```

#### Response:

```json
{
  "message": "live_order_history",
  {
  "data": {
    "address": "0x725c8b51b2c1b3d17336c48d75c56c19253f70e1de00e26c8138a29722d82da",
    "is_market_order": true,
    "last_updated": 1749454518,
    "leverage": 2,
    "market_id": "1338",
    "order_id": "81291775866809905605246976",
    "order_type": 7,
    "order_value": "4.652",
    "price": "4.652",
    "size": "1",
    "status": "Open",
    "timestamp": 1749454517,
    "trade_id": "334291896103764494386490",
    "transaction_version": 6780532763
  }
 }
}
```

#### 10. **Live Trade History**

Subscribe to view live trade history for a given user address (It will update only latest single data):

```json
{
  "topic": "live_trade_history",
  "address": "{{user_address}}"
}
```

#### Response:

```json
{
  "message": "live_trade_history",
  {
  "data": {
    "address": "0x725c8b51b2c1b3d17336c48d75c56c19253f70e1de00e26c8138a29722d82da",
    "fee": "0.0023305000000000000485132769",
    "last_updated": 1749454657,
    "leverage": 2,
    "market_id": "1338",
    "order_id": "81295631236321310901534720",
    "order_type": 1,
    "order_value": "4.661",
    "pnl": "-0.0023305000000000000485132769",
    "price": "4.661",
    "size": "1",
    "timestamp": 1749454656,
    "trade_id": "334347236335985623041338",
    "transaction_version": 6780534260
  }
 }
}
```

***

## Example of Subscribing to WebSocket Endpoints

To connect to the WebSocket and subscribe to multiple topics, use the following example approach:

1. **Connect to the WebSocket URL** (Choose either <mark style="color:orange;">Testnet</mark> or <mark style="color:orange;">Mainnet</mark> URLs depending on your environment).
2. **Send a subscription message** for each topic you want to subscribe to (e.g., order history, positions, etc.).

Here is a JavaScript example using WebSocket:

```javascript
const socket = new WebSocket('wss://perpetuals-indexer-ws.kana.trade/ws/');

socket.onopen = function() {
  // Subscribe to order history
  socket.send(JSON.stringify({
    topic: "order_history",
    address: "your_profile_address"
  }));

  // Subscribe to trade history
  socket.send(JSON.stringify({
    topic: "trade_history",
    address: "your_profile_address"
  }));
};

socket.onmessage = function(event) {
  console.log('Received data:', event.data);
};

socket.onerror = function(error) {
  console.error('WebSocket Error:', error);
};
```

***

### Error Handling

If your WebSocket connection fails, check the following:

* Ensure you're using the correct WebSocket URL (Testnet vs Mainnet).
* Double-check your **profile address** to ensure it is valid and associated with your wallet.

If you encounter any errors in subscription requests, the server may send a response indicating the issue (e.g., invalid topic or missing parameters). Handle these responses appropriately in your code.


# FAQ


# Faucets

## How to Get APT on Testnet

1. Go to [Aptos faucet](https://aptos.dev/en/network/faucet) page.
2. Connect your google account
3. Enter your Aptos wallet address
4. Click on Mint

***

## How to Get USDT on Testnet Using Your Petra Wallet

#### Method 1:

1. Go to the [**USDC Faucet**](https://explorer.aptoslabs.com/object/0x24246c14448a5994d9f23e3b978da2a354e64b6dfe54220debb8850586c448cc/modules/run/usdt/faucet?network=testnet) Module on the Aptos Explorer.
2. Connect your Petra Wallet.
3. Enter the amount you want to mint (maximum: **1000 USDT**).\
   **Note on amount format:** USDT uses 6 decimal places.\
   For example:
   * To mint **1 USDT**, enter `1000000`.
   * To mint **1000 USDT**, enter `1000000000`.

#### Method 2:

1. Go to [testnet.kana.trade](https://testnet.kana.trade)
2. Connect your Petra wallet
3. Click on Deposit button on the top right
4. Click on Mint USDT button

***

## How to Get USDT on Testnet to Any Wallet Address

1. Go to the [**USDC Faucet to Address**](https://explorer.aptoslabs.com/object/0x24246c14448a5994d9f23e3b978da2a354e64b6dfe54220debb8850586c448cc/modules/run/usdt/faucet_to_address?network=testnet) Module on the Aptos Explorer.
2. Connect your Petra Wallet.
3. Enter the **wallet address** and the **amount** you want to mint (maximum: **1000 USDT**).\
   **Note on amount format:** USDT uses 6 decimal places.\
   For example:
   * To send **1 USDT**, enter `1000000`.
   * To send **1000 USDT**, enter `1000000000`.


# Kana Labs - DeFi Simplified

A complete and comprehensive DeFi product suite that provides end to end solutions be it for retail users looking to make their mark in Crypto or for developers & businesses entering the DeFi market.

Kana Labs provides traders with practical tools that simplify DeFi, offering a straightforward way to navigate decentralized markets. These tools are designed to reduce complexity and help traders engage with decentralized finance efficiently, whether they are new to DeFi or experienced market participants.

**List of Products -**

* **AMM DEX Aggregator (Swap Platform)**: Unlocks liquidity across multiple chains for efficient, cost-effective token swaps with minimal slippage.&#x20;
* **Kana Trade (Orderbook Platform)**: Decentralized spot trading with advanced tools, low fees, and a user-friendly orderbook interface.&#x20;
* **OPerps aka Perpetual Options**: Short-term options trading with capped risk, dynamic leverage, and flexible strategies for profit maximization.&#x20;
* **Perps aka Perpetual Futures**: High-speed trading designed for precision and advanced strategies on a decentralized perpetual futures platform. (Coming Soon)


# Staking Aggregator

The Staking Aggregator brings together top staking protocol from the 9 supported chains in our DeFi ecosystem under one roof. Further, the UI combines our AMM Swap Aggregator to the token selection process enabling users to stake from any tokens in their possession across any protocol of their choice easily.

The tokens will be swapped to the required source token of the selected protocol and the staking transaction is executed. This means that users can now stake using any tokens across any chain of their choice without having to worry about possessing the required source tokens.


# Trading APIs

Quick Links to APIs for Kana Labs DeFi Product Suite

{% content-ref url="/pages/Qx9Jw0IB2xiW2UsPeaAy" %}
[Kana Trade API](/spot-and-perp-apis/trading-apis/kana-trade-api)
{% endcontent-ref %}

{% content-ref url="/pages/GMPy9CPDeTfHSdZy9O93" %}
[Kana Perps API](/spot-and-perp-apis/trading-apis/kana-perps-api)
{% endcontent-ref %}


# Kana Trade API

API for our on-chain orderbook platform Kana Trade

## **Link to Github Repo & Swagger for Kana Trade APIs**

Here's an example implementation of trade book API using javascript/typescript

{% embed url="<https://github.com/kanalabs/trade-implementation>" %}

***

{% hint style="info" %}
Please note that an API Key is required to integrate your bots/trading tools with our API. To get the API key from us, reach out via email at <hello@kanalabs.io>
{% endhint %}

For Swagger API Documentation, Please visit ->

{% embed url="<https://tradeapi.kanalabs.io/swagger/static/index.html#/tradeapi.kanalabs.io>" %}

***


# Kana Perps API

API for our perpetual futures platform

## Introduction

This section provides the API for Kana Perps, our perpetual futures trading platform. It includes endpoints for market data, placing orders, managing positions, and more to help you integrate and trade easily.

### Overview

Kanalabs supports both REST and WebSocket APIs for seamless integration with your application.

### REST API Endpoints

#### Testnet

* **Base URL**: <https://perps-tradeapi.kanalabs.io>

### WebSocket API Endpoints

#### Testnet

* **WebSocket URL**: wss\://perps-sdk-ws.kanalabs.io

### Request and Response Format

* **Requests**: All requests must be in JSON format.
* **Responses**: Responses can either be a JSON object or an array.

### SDKs

#### TypeScript SDK

* **GitHub Repository**: [kana-perps-sdk](https://github.com/kanalabs/kana-perps-sdk)

```
Please note that an API Key is required to integrate your bots/trading tools with our API.
To get the API key from us, reach out via email at hello@kanalabs.io
```


# Installation Setup

Overview of supported trading markets and installation prerequisites for using the API.

### Supported Markets

This API provides information for the following trading markets:

<table data-header-hidden><thead><tr><th width="350"></th><th width="179"></th><th></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td><td><strong>Description</strong></td></tr><tr><td>APT/USDC</td><td>396</td><td>Aptos-based trading market.</td></tr><tr><td>BTC/USDC</td><td>397</td><td>Bitcoin-based trading market.</td></tr><tr><td>ETH/USDC</td><td>398</td><td>Ethereum-based trading market.</td></tr></tbody></table>

#### Prerequisites

Before using the API, ensure you have the following:

1. **Node.js**: Install version 16 or higher. [Download here](https://nodejs.org/).
2. **npm**: Verify npm is installed to manage packages.

#### Install Required Packages

Run these commands to install the required dependencies:

1. Install `dotenv` and `axios`:

   ```bash
   npm install dotenv axios
   ```
2. Install the Aptos SDK for TypeScript:

   ```bash
   npm install @aptos-labs/ts-sdk
   ```

#### Example Setup in TypeScript

Create a file, e.g., `setup.ts`, and use the following code:

```typescript
// Import required packages
import dotenv from 'dotenv';
import axios from 'axios';
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";

// Load environment variables from .env file
dotenv.config();

// Setup the client
const config = new AptosConfig({ network: Network.TESTNET });
const aptos = new Aptos(config);
const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
);
const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
});
```

### **Size Conversion Details:**

**APT Market**

* `base_decimals`: **8**
* `lot_size_multiplier`: **100000**

**BTC Market**

* `base_decimals`: **8**
* `lot_size_multiplier`: **1000**

**ETH Market**

* `base_decimals`: **8**
* `lot_size_multiplier`: **10000**

#### Size Conversion Example in TypeScript:

```typescript
import BigNumber from "bignumber.js";

async function main(): Promise<void> {

    // Size conversion
    const size = new BigNumber("your_size_value"); // Eg: 5.67
    const baseDecimals = "your_base_decimals_value"; // Eg: 8
    const lotSizeMultiplier = new BigNumber("your_lot_size_multiplier_value"); // Eg: 100000

    // 10^baseDecimals
    const sizeScalingFactor = new BigNumber(10).pow(baseDecimals);

    // Convert size and remove decimals
    const convertedSize = size.multipliedBy(sizeScalingFactor).dividedBy(lotSizeMultiplier).integerValue(BigNumber.ROUND_FLOOR);

    console.log("Converted Size: ", convertedSize.toString());
}

main().catch(error => {
    console.error('An error occurred:', error);
});

```

### **Price Conversion Details:**

**APT Market**

* `price_precision`: **3**

**BTC Market**

* `price_precision`: **0**

**ETH Market**

* `price_precision`: **1**

#### Price Conversion Example in TypeScript:

```typescript
import BigNumber from "bignumber.js";

async function main(): Promise<void> {

    // Price conversion
    const price = new BigNumber("your_price_value"); // Eg: 8.356
    const pricePrecision = "your_price_precision_value"; // Eg: 3

    // 10^pricePrecision
    const priceMultiplier = new BigNumber(10).pow(pricePrecision);

    // Convert price and remove decimals
    const convertedPrice = price.multipliedBy(priceMultiplier).integerValue(BigNumber.ROUND_FLOOR);

    console.log("Converted Price: ", convertedPrice.toString());
}

main().catch(error => {
    console.error('An error occurred:', error);
});

```


# Example setup functions

## We will see how to implement the run functions : (Example deposit function)

1\. Imports:

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";

async function main(): Promise<void> {
```

\
2\. Aptos client setup:

```typescript
    // Setup the Aptos client configuration
    const config = new AptosConfig({ network: Network.TESTNET }); // Connect to Aptos Testnet
    const aptos = new Aptos(config); // Create an instance of the Aptos SDK
```

\
3\. Wallet setup:

<pre class="language-typescript"><code class="lang-typescript">    // Initialize the account using a private key
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
<strong>    const account = Account.fromPrivateKey({
</strong>    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
</code></pre>

4\. Get transaction payload: (required function parameters for order deposit function)

```typescript
    // API endpoint for fetching limit order payload
    const baseURL = 'https://perps-tradeapi.kanalabs.io/limitOrder';
    const params = {
        marketId: 66, // Specify the market ID for the trade
        amount: 50000, // amount to deposit your trading account
    };
    // Fetch the payload for deposit
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    const payload = res.data; // Extract the data payload
```

\
5\. Building transaction

```typescript
    // Build a transaction payload using the Aptos SDK
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress, // The address of the account sending the transaction
        data: payload, // Payload fetched from the API
    });
```

\
6\. Sign and Submit Transaction

```typescript
    // Sign and submit the transaction
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload, // Built transaction payload
        signer: account, // Account used for signing
    });
```

\
7\. Wait for transaction to complete

```typescript
    // Wait for the transaction to be confirmed and retrieve its status
    const response = await aptos.waitForTransaction({
        transactionHash: committedTxn.hash, // Hash of the submitted transaction
    });
    // Log the success status of the transaction
    console.log("response", response.success);
```

8\. Call main function:

```typescript
}
// Run the main function and handle any errors
main().catch(error => {
    console.error('An error occurred:', error);
});
```

## We will see how to implement the view functions : (Example get market info function)

#### 1. **Imports:**

```typescript
// Import the axios library for making HTTP requests
import axios from "axios";
```

#### 2. **Main Function Setup:**

```typescript
// Main function to fetch market info from the API
async function main(): Promise<void> {
```

#### 3. **API Endpoint Setup:**

```typescript
// The base URL for the API endpoint
const baseURL = 'https://perps-tradeapi.kanalabs.io/getMarketInfo';
```

#### 4. **Parameters Setup:**

```typescript
// Parameters to be sent with the API request (marketId in this case)
const params = {
      marketId: 'your_market_id' // Replace with the actual marketId
  };
```

#### 5. **API Request:**

```typescript
try {
    // Sending a GET request to the API with the parameters and the API key
    const res = await axios.get(baseURL, {
        params, // Query parameters to be included in the request URL
        headers: {
            'x-api-key': process.env.API_KEY, // API key passed in the headers from environment variables
        },
    });
```

#### 6. **Extracting and Logging Data:**

```typescript
// Extracting the data returned by the API response
const getMarketInfo = res;
// Logging the market info data to the console
console.log("getMarketInfo: ", getMarketInfo);
```

#### 7. **Error Handling:**

```typescript
} catch (error) {
        // Handling errors if the API request fails
        console.error('An error occurred:', error);
    }
```

#### 8. **Calling the Main Function:**

```typescript
// Calling the main function and handling potential errors
main().catch(error => {
    console.error('An error occurred:', error);
});
```


# Kana Perps Typescript REST API

## **1. Get Market Info**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getMarketInfo`](#id-1.-get-market-info)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `marketId` (Required) - The ID of the market you want information about.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getMarketInfo?marketId=501
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Market information fetched successfully",
  "data": [
    {
      "__variant__": "V1",
      "base_decimals": 8,
      "base_name": "APT/USDC",
      "counter": "17",
      "creator": "0xb61d7b57333abf8ac036e752f19d0ba0c4baa5404db1cbf868c57dac3628f2bf",
      "lot_size": "100000",
      "maintenance_margin": "250",
      "market_address": "0xfd8d58fdd05dd9d0442a9d555a4f8ed310112eb7d1c297307038a650136e207b",
      "market_id": "501",
      "max_leverage": "20",
      "max_lots": "150000000",
      "min_lots": "500",
      "quote_decimals": 6,
      "quote_precision": 3,
      "tick_size": "1"
    }
  ]
}
```

**Example Code to Fetch Market Information:**

The following TypeScript/Node.js script demonstrates how to call the Get Market Info API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getMarketInfo';
    const params = {
        marketId: 'your_market_id'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getMarketInfo: ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **2.** Get Wallet Account Balance

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getWalletAccountBalance`](https://perps-tradeapi.kanalabs.io/getWalletAccountBalance)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `userAddress` (Required) - The wallet address for which the account balance is being fetched.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getWalletAccountBalance?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched wallet account balance successfully",
  "data": "16391.60"
}
```

**Example Code to Fetch** Wallet Account Balance **Information:**

The following TypeScript/Node.js script demonstrates how to call the Get Wallet Account Balance API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getWalletAccountBalance';
    const params = {
        userAddress: 'your_wallet_address'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getWalletAccountBalance: ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **3.** Get Profile Balance Snapshot

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getProfileBalanceSnpashot`](https://perps-tradeapi.kanalabs.io/getProfileBalanceSnpashot)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `userAddress` (Required) - The wallet address for which the account balance is being fetched.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getProfileBalanceSnpashot?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Profile balance snapshot fetched successfully",
  "data": "44.321972"
}
```

**Example Code to Fetch** Trading Account Balance **Information:**

The following TypeScript/Node.js script demonstrates how to call the Get Trading Account Balance API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {

    const baseURL = 'https://perps-tradeapi.kanalabs.io/getTradingAccountBalance';
    const params = {
        userAddress: 'your_wallet_address'
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    console.log("getTradingAccountBalance: ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **4. Deposit**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/deposit`](https://perps-tradeapi.kanalabs.io/deposit)
* **Method**:\
  `GET`
* **Query Parameters:**
  * `amount` (Required) - The amount of the quote coin to deposit.
  * `userAddress` (Required) - The address of the user making the deposit.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/deposit?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&amount=50000000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Deposit payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::deposit",
    "functionArguments": [
      "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
      50000000
    ],
    "typeArguments": []
  }
}
```

**Example Code to Depsoit a quote coin:**

The following TypeScript/Node.js script demonstrates how to call the Get Deposit API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";


async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/deposit';
    const params = {
        userAddress: 'your_address',
        amount: 'your_amount'
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    const payloadData = res.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **5. Withdraw Specific Market**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket`](https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `marketId` (Required) - The ID of the market you want to withdraw.
  * `amount` (Required) - The amount of the quote coin to withdraw.
  * `userAddress` (Required) - The address of the user making the withdraw.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket?marketId=501&userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&amount=50
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Withdraw specific market payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::withdraw_specific_market",
    "functionArguments": [
      "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
      "501",
      50000000
    ],
    "typeArguments": []
  }
}
```

**Example Code to Withdraw a quote coin:**

The following TypeScript/Node.js script demonstrates how to call the Get Withdraw API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";


async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket';
    const params = {
        userAddress: 'your_address',
        marketId: 'your_market_id',
        amount: 'your_amount'
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    const payloadData = res.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **6. Place Limit Order**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/placeLimitOrder`](https://perps-tradeapi.kanalabs.io/placeLimitOrder)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market where the limit order will be placed.
  * **tradeSide** (Required) - Indicates the trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **direction** (Required) - Indicates the direction of the trade:
    * `false` to open a position.
    * `true` to close a position.
  * **size** (Required) - The size of the order.
  * **price** (Required) - The price at which the order is to be placed.
  * **leverage** (Required) - The leverage to be used for the order.
  * **restriction**  - Specifies the type of order restriction. It is an optional parameter with a default value of `0`.\
    Possible values are:
    * `0` - `NO_RESTRICTION`: Optionally fill as a taker, then post to the book as a maker.
    * `1` - `FILL_OR_ABORT`: Abort if any size posts as a maker (only fill).
    * `3` - `POST_OR_ABORT`: Abort if any size fills as a taker (only post).
    * If `restriction` is not provided, it defaults to `0`. It can either be a number or left undefined.
  * **takeProfit** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
  * **stopLoss** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/placeLimitOrder/?marketId=501&tradeSide=true&direction=false&size=10000&price=3000&leverage=3
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Limit Order payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::place_limit_order",
    "functionArguments": [
      "501",
      "true",
      "false",
      1000000,
      8000000,
      "5",
      0,
      0,
      0
    ],
    "typeArguments": []
  }
}
```

**Example Code to Place a limit order:**

The following TypeScript/Node.js script demonstrates how to call the Get Place Limit Order API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";


async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/limitOrder';
    const params = {
        marketId: 'your_market_id',
        tradeSide: 'your_trade_side',
        direction: 'your_direction',
        size: 'your_size',
        price: 'your_price',
        leverage: 'your_leverage',
        restriction: 'your_restriction', //(Optional, Default: 0)
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    const payloadData = res.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **7. Place Market Order**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/placeMarketOrder`](https://perps-tradeapi.kanalabs.io/placeMarketOrder)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market where the limit order will be placed.
  * **tradeSide** (Required) - Indicates the trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **direction** (Required) - Indicates the direction of the trade:
    * `false` to open a position.
    * `true` to close a position.
  * **size** (Required) - The size of the order.
  * **leverage** (Required) - The leverage to be used for the order.
  * **takeProfit** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
  * **stopLoss** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/placeMarketOrder?marketId=66&tradeSide=false&direction=true&size=1000&leverage=20
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Market Order payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::place_market_order",
    "functionArguments": [
      "501",
      "true",
      "false",
      1000000,
      "5",
      0,
      0
    ],
    "typeArguments": []
  }
}
```

**Example Code to Place a market order:**

The following TypeScript/Node.js script demonstrates how to call the Get Place Market Order API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";


async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/marketOrder';
    const params = {
        marketId: 'your_market_id',
        tradeSide: 'your_trade_side',
        direction: 'your_direction',
        size: 'your_size',
        leverage: 'your_leverage',
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    const payloadData = res.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **8. Cancel Multiple Orders**

* **Endpoint URL**:\
  [`htps://perps-tradeapi.kanalabs.io/cancelMultipleOrders`](#api-overview)
* **Method**:\
  `POST`
* **Request Body**:
  * **marketId**: The ID of the market for which the orders will be canceled.
  * **orderIds**: A list of order IDs to cancel.
  * cancelTradeSides: The sides of the orders to cancel (true for long, false for short).

**Example Request:**

```json
{
  "marketId": 66,
  "cancelOrderIds": ["1077898597726583798162207", "1077880153515406921884445"],
  "orderSides": [true, false]
}
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Cancel Multiple Orders payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::cancel_multiple_orders",
    "functionArguments": [
      501,
      [
        "1077898597726583798162207",
        "1077880153515406921884445"
      ],
      [
        true,
        false
      ]
    ],
    "typeArguments": []
  }
}
```

**Example Code to Cancel multiple orders:**

The following TypeScript/Node.js script demonstrates how to call the Post Cancel Multiple Orders API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";


async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/cancelMultipleOrders';
    const params = {
        marketId: 'your_market_id',
        cancelOrderIds: ['your_cancel_order_ids'],
        orderSides: ['your_order_sides']
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    const payloadData = res.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **8. Place Multiple Orders**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/placeMultipleOrders`](https://perps-tradeapi.kanalabs.io/placeMultipleOrders)
* **Method**:\
  `POST`

Request Body :

* marketId (Required) - The ID of the market where the orders will be placed.
* orderTypes (Required) - An array of order types for each order:
  * true for limit orders.
  * false for market orders.
* tradeSides (Required) - An array indicating the trade sides for each order:
  * true for long positions.
  * false for short positions.
* directions (Required) - An array indicating the direction of each trade:
  * false to open a position.
  * true to close a position.
* sizes (Required) - An array of sizes for each order.
* leverages (Required) - An array of leverages for each order.
* prices (Required) - An array of prices at which each order is to be placed.
* **restriction**  - Specifies the type of order restriction. It is an optional parameter with a default value of `0`.\
  Possible values are:
  * `0` - `NO_RESTRICTION`: Optionally fill as a taker, then post to the book as a maker.
  * `1` - `FILL_OR_ABORT`: Abort if any size posts as a maker (only fill).
  * `3` - `POST_OR_ABORT`: Abort if any size fills as a taker (only post).
  * If `restriction` is not provided, it defaults to `0`. It can either be a number or left undefined.
* **takeProfits** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
* **stopLosses** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```json
{
  "marketId": 66,
  "orderTypes": [true, true],
  "tradeSides": [true, true],
  "directions": [true, true],
  "sizes": [1000, 1000],
  "prices": [1000, 1000],
  "leverages": [2, 2]
}
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Multiple Orders payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::place_multiple_orders",
    "functionArguments": [
      501,
      [
        true,
        true
      ],
      [
        true,
        true
      ],
      [
        true,
        true
      ],
      [
        1000,
        1000
      ],
      [
        4670,
        6780
      ],
      [
        2,
        2
      ],
      [
        0,
        0
      ],
      [
        4600
      ],
      [
        0,
        0
      ]
    ],
    "typeArguments": []
  }
}
```

**Example Code to Place a multiple orders:**

The following TypeScript/Node.js script demonstrates how to call the Get Place Multiple Orders API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";


async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/placeMultipleOrders';
    const params = {
        marketId: 'your_market_id',
        orderTypes: ['your_order_types'],
        tradeSides: ['your_trade_sides'],
        directions: ['your_directions'],
        sizes: ['your_sizes'],
        prices: ['your_prices'],
        leverage: ['your_leverages']
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    const payloadData = res.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **9. Cancel and Place Multiple Orders**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/cancelAndPlaceMultipleOrders`](https://perps-tradeapi.kanalabs.io/cancelAndPlaceMultipleOrders)
* **Method**:\
  `POST`

Request Body :

* marketId (Required) - The ID of the market where the orders will be placed.
* cancelOrderIds **(Required)** - An array of strings representing the IDs of the orders to be canceled.
* orderSides **(Required)** - An array indicating the sides of the orders being canceled:
  * `true` for long sides.
  * `false` for short sides.
* orderTypes (Required) - An array of order types for each order:
  * true for limit orders.
  * false for market orders.
* tradeSides (Required) - An array indicating the trade sides for each order:
  * true for long positions.
  * false for short positions.
* directions (Required) - An array indicating the direction of each trade:
  * false to open a position.
  * true to close a position.
* sizes (Required) - An array of sizes for each order.
* leverages (Required) - An array of leverages for each order.
* prices (Required) - An array of prices at which each order is to be placed.
* **restriction**  - Specifies the type of order restriction. It is an optional parameter with a default value of `0`.\
  Possible values are:
  * `0` - `NO_RESTRICTION`: Optionally fill as a taker, then post to the book as a maker.
  * `1` - `FILL_OR_ABORT`: Abort if any size posts as a maker (only fill).
  * `3` - `POST_OR_ABORT`: Abort if any size fills as a taker (only post).
  * If `restriction` is not provided, it defaults to `0`. It can either be a number or left undefined
* **takeProfits** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
* **stopLosses** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```json
{
  "marketId": 66,
  "cancelOrderIds": [23434565434567", "454345665456],
  "orderSides": [true, true],
  "orderTypes": [true, true],
  "tradeSides": [true, false],
  "directions": [true, true],
  "sizes": [1000, 2000],
  "prices": [5000, 6000],
  "leverages": [2, 2]
}
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Cancel and place multiple Orders payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::cancel_and_place_multiple_orders",
    "functionArguments": [
      501,
      [
        "23434565434567",
        "454345665456"
      ],
      [
        "true",
        "true"
      ],
      [
        true,
        true
      ],
      [
        true,
        false
      ],
      [
        true,
        true
      ],
      [
        1000,
        2000
      ],
      [
        5000,
        6000
      ],
      [
        2,
        2
      ],
      [
        0,
        0
      ],
      [
        0,
        0
      ],
      [
        0,
        0
      ]
    ],
    "typeArguments": []
  }
}
```

**Example Code to cancel and Place a multiple orders:**

The following TypeScript/Node.js script demonstrates how to call the Get Cancel And Place Multiple Orders API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";

async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/cancelAndPlaceMultipleOrders';
    const params = {
        marketId: 'your_market_id',
        cancelOrderIds: ['your_order_ids'],
        orderSides: ['your_cancel_trade_sides'],
        orderTypes: ['your_order_types'],
        tradeSides: ['your_trade_sides'],
        directions: ['your_directions'],
        sizes: ['your_sizes'],
        prices: ['your_prices'],
        leverage: ['your_leverages']
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    const payloadData = res.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **10.** Get Open Orders

* **Endpoint URL**:\
  [h`ttps://perps-tradeapi.kanalabs.io/getOpenOrders`](https://perps-tradeapi.kanalabs.io/getOpenOrders)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve open orders for.
  * **marketId (Optional)** - The ID of the market to filter open orders.  // Optional

```
Note : order_type Explanation:

OPEN_LONG (1): Opens a new long position.
OPEN_SHORT (2): Opens a new short position.
INCREASE_LONG (3): Increases the size of an existing long position.
INCREASE_SHORT (4): Increases the size of an existing short position.
DECREASE_LONG (5): Reduces the size of an existing long position.
DECREASE_SHORT (6): Reduces the size of an existing short position.
CLOSE_LONG (7): Closes an existing long position.
CLOSE_SHORT (8): Closes an existing short position.
```

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOpenOrders?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched open orders successfully",
  "data": [
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": "1741444213",
      "price": "7",
      "total_size": "2",
      "remaining_size": "2",
      "order_value": "14",
      "order_id": "645636324063400958808",
      "trade_id": "295147905179352826357",
      "last_updated": "1741444214"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": "1741445758",
      "price": "7",
      "total_size": "2",
      "remaining_size": "2",
      "order_value": "14",
      "order_id": "682529812245179800408",
      "trade_id": "295147905179352826357",
      "last_updated": "1741445758"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": "1741446786",
      "price": "7",
      "total_size": "2",
      "remaining_size": "2",
      "order_value": "14",
      "order_id": "700976556301709482840",
      "trade_id": "295147905179352826357",
      "last_updated": "1741446786"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": "1741446907",
      "price": "7",
      "total_size": "2",
      "remaining_size": "2",
      "order_value": "14",
      "order_id": "719423300401188838232",
      "trade_id": "295147905179352826357",
      "last_updated": "1741446908"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": "1741447619",
      "price": "0.007",
      "total_size": "1",
      "remaining_size": "1",
      "order_value": "0.007",
      "order_id": "737869903703050289159",
      "trade_id": "295147905179352826357",
      "last_updated": "1741447620"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": "1741447815",
      "price": "0.007",
      "total_size": "1",
      "remaining_size": "1",
      "order_value": "0.007",
      "order_id": "756316647793939709959",
      "trade_id": "295147905179352826357",
      "last_updated": "1741447815"
    }
  ]
}
```

**Example Code to Fetch** Open Order&#x73;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Orders API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/openOrders';
    const params = {
        userAddress: 'your_wallet_address',
        marketId: 'your_market_id'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getOpenOrders : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **11.** Get Order History

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getOrderHistory`](https://perps-tradeapi.kanalabs.io/getOrderHistory)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve the order history for.
  * **marketId** (optional) - The ID of the market to filter the order history.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOrderHistory?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched order history successfully",
  "data": [
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 1,
      "timestamp": "1741167151",
      "is_market_order": false,
      "size": "1.50",
      "price": "4.678",
      "order_value": "7.01700",
      "status": "Open",
      "order_id": "18446884819787846214",
      "trade_id": "18446744073709552117",
      "last_updated": "1741262093"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 1,
      "timestamp": "1741236277",
      "is_market_order": false,
      "size": "1.50",
      "price": "4.678",
      "order_value": "7.01700",
      "status": "Cancelled",
      "order_id": "18446884819787846214",
      "trade_id": "18446744073709552117",
      "last_updated": "1741262168"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 1,
      "timestamp": "1741236468",
      "is_market_order": false,
      "size": "1.50",
      "price": "4.50",
      "order_value": "6.7500",
      "status": "Open",
      "order_id": "36893628893497397652",
      "trade_id": "36893488147419103733",
      "last_updated": "1741262168"
    }
  }
]
```

**Example Code to Fetch Order History:**

The following TypeScript/Node.js script demonstrates how to call the Get Order History API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/orderHistory';
    const params = {
        userAddress: 'your_wallet_address',
        marketId: 'your_market_id'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    const getOrderHistory = res.data;
    console.log("getOrderHistory : ", getOrderHistory);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **12.** Get Positions

* **Endpoint URL**:\
  [h`ttps://perps-tradeapi.kanalabs.io/getPositions`](https://perps-tradeapi.kanalabs.io/getPositions)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address of the user to view positions for.
  * **marketId** (optional) - The ID of the market to filter the positions.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getPositions?marketId=66&userAddress=0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched positions successfully",
  "data": [
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "is_long": true,
      "size": "1",
      "available_order_size": "1",
      "value": "5.678",
      "entry_price": "5.678",
      "liq_price": "2.9117948717948717990163355253",
      "margin": "2.839",
      "tp": "6.012",
      "sl": null,
      "trade_id": "295147905179352826357",
      "last_updated": "1741262185"
    }
  ]
}
```

**Example Code to Fetch** Open Positio&#x6E;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Position API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getPositions';
    const params = {
        marketId: 'your_market_id',
        userAddress: 'your_wallet_address'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getOpenPosition : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **12.** Get All Trades

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAllTrades`](https://perps-tradeapi.kanalabs.io/getAllTrades)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market to retrieve all trades information.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAllTrades?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Recent trades fetched successfully",
  "data": [
    {
      "txn_version": 6297687196,
      "event_idx": 5,
      "emit_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "time": "2024-11-20T20:33:38.600241+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15951655917465922493754983",
      "maker_side": true,
      "market_id": 66,
      "price": 11879,
      "sequence_number_for_trade": 0,
      "size": 10000,
      "taker_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "taker_custodian_id": 28,
      "taker_order_id": "15951748150764039921729536",
      "taker_quote_fees_paid": 59395
    },
    {
      "txn_version": 6297687196,
      "event_idx": 4,
      "emit_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "time": "2024-11-20T20:33:38.600241+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15951655917465922493754983",
      "maker_side": true,
      "market_id": 66,
      "price": 11879,
      "sequence_number_for_trade": 0,
      "size": 10000,
      "taker_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "taker_custodian_id": 28,
      "taker_order_id": "15951748150764039921729536",
      "taker_quote_fees_paid": 59395
    }
  ]
}
```

**Example Code to Fetch** All trade&#x73;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Position API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getAllTrades';
    const params = {
        marketId: 'your_market_id'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    const getAllTrades = res.data;
    console.log("getAllTrades : ", getAllTrades);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **13.** Get Order Status By Order Id

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId`](https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market associated with the order.
  * **orderId** (Required) - The unique identifier of the order to retrieve its status.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId?marketId=66&orderId=15308325717473050761363456
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "status": true,
  "message": "Fetched order status for a given order Id successfully",
  "data": {
    "market_id": 66,
    "order_id": "15308325717473050761363456",
    "created_at": "2024-11-20T11:54:45.957059+00:00",
    "last_updated_at": "2024-11-20T11:54:45.957059+00:00",
    "integrator": "0xee820ab02631dd1a195d3c53fa64f0a8f455dbb9261388e141c3bd3bd3c08363",
    "total_filled": 1000,
    "remaining_size": 0,
    "order_status": "closed",
    "order_type": "market",
    "user": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
    "direction": "buy",
    "price": 0,
    "average_execution_price": 12813,
    "custodian_id": 28,
    "self_match_behavior": 0,
    "restriction": 0,
    "last_increase_stamp": null,
    "min_base": null,
    "max_base": null,
    "min_quote": null,
    "max_quote": null,
    "total_fees_paid_in_quote_subunits": 6406
  }
}
```

**Example Code to Fetch** Order Status B Order I&#x64;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Order Status By Order Id API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId';
    const params = {
        marketId: 'your_market_id',
        orderId: 'your_order_id'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getOrderStatusByOrderId : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **14.** Get Fills

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getFills`](https://perps-tradeapi.kanalabs.io/getFills)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which fills are retrieved.
  * **address** (Optional) - The address of the user to filter fills (if applicable).
  * **from** (Required) - The start time of the range in ISO 8601 format (e.g., `2024-11-21T00:00:00Z`).
  * **to** (Required) - The end time of the range in ISO 8601 format (e.g., `2024-11-21T23:59:59Z`).
  * **orderId** (Required) - The unique identifier of the order to retrieve its status.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getFills?marketId=66&address=0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2&from=2024-11-20T00:00:00Z&to=2024-11-21T23:59:59Z
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched fill trades for a given time range Successfully",
  "data": [
    {
      "txn_version": 6296434935,
      "event_idx": 1,
      "emit_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "time": "2024-11-20T19:23:14.67535+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15891335065048614061485282",
      "maker_side": true,
      "market_id": 66,
      "price": 11490,
      "sequence_number_for_trade": 0,
      "size": 1000,
      "taker_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "taker_custodian_id": 28,
      "taker_order_id": "15891427297643009687945216",
      "taker_quote_fees_paid": 5745
    },
    {
      "txn_version": 6295302625,
      "event_idx": 4,
      "emit_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "time": "2024-11-20T18:19:35.70863+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15812401447297883953966476",
      "maker_side": false,
      "market_id": 66,
      "price": 11660,
      "sequence_number_for_trade": 0,
      "size": 1000,
      "taker_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "taker_custodian_id": 28,
      "taker_order_id": "15812549019983827645235200",
      "taker_quote_fees_paid": 5830
    }
  ]
}
```

**Example Code to Fetch** Order Status B Order IdFills Dat&#x61;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Fills Data API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getFills';
    const params = {
        marketId: 'your_market_id',
        address: 'your_address',
        from: 'your_from_time',
        to: 'your_to_time'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getFillsData : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **14.** Get Market Price

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getMarketPrice`](https://perps-tradeapi.kanalabs.io/getMarketPrice)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the price information is being retrieved.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getMarketPrice?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched Market Price Successfully",
  "data": {
    "bestAskPrice": 6.400,
    "bestBidPrice": 9.880
  }
}
```

**Example Code to Fetch** Market Pric&#x65;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Market Price API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getLastPlacedPrice';
    const params = {
        marketId: 'your_market_id'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getLastExecutionPrice : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **15.** Get Last Execution Price

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getLastPlacedPrice`](https://perps-tradeapi.kanalabs.io/getLastPlacedPrice)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the last execution price information is being retrieved.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getLastPlacedPrice?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched last execution price Successfully",
  "data": 8.989
}
```

**Example Code to Fetch** Last Execution Pric&#x65;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Last Execution Price API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getLastPlacedPrice';
    const params = {
        marketId: 'your_market_id'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getLastExecutionPrice : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **16.** Get All Open Order Ids

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds`](https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds)
* **Method**:\
  `GET`
* **Query Parameters**:
  * userAddress(Required) - The address associated with the orders.
  * **marketId** (optional) - The ID of the market for which open order IDs are being retrieved.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds?marketId=66&userAddress=0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Open order IDs fetched successfully",
  "data": [
    "645636324063400958808",
    "682529812245179800408",
    "700976556301709482840",
    "719423300401188838232",
    "737869903703050289159",
    "756316647793939709959"
  ]
}
```

**Example Code to Fetch** Open Order Id&#x73;**:**

The following TypeScript/Node.js script demonstrates how to call the Get Open Order Ids API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds';
    const params = {
        userAddress: 'your_wallet_address',
        marketId: 'your_market_id'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getOpenOrderIds : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **17. Update Take Profit**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/updateTakeProfit`](https://perps-tradeapi.kanalabs.io/updateTakeProfit)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the take profit values will be updated.
  * **tradeSide** (Required) - The trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **newTakeProfitPrice** (Required) - The new take profit price to be set for the trade.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/updateTakeProfit?marketId=66&tradeSide=true&newTakeProfitPrice=6000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Update take profit payload built succesfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::update_take_profit",
    "functionArguments": [
      "501",
      "true",
      7590
    ],
    "typeArguments": []
  }
}
```

**Example Code to Update take profit price:**

The following TypeScript/Node.js script demonstrates how to call the Get Update Take Profit Price API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";


async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/updateTakeProfit';
    const params = {
        marketId: 'your_market_id',
        tradeSide: 'your_trade_side',
        newTakeProfitPrice: 'your_tp_price'
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    const payloadData = res.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **18.** Get Account Aptos Balance

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAccountAptBalance`](https://perps-tradeapi.kanalabs.io/getAccountAptBalance)
* **Method**:\
  `GET`
* **Query Parameters**:
* **userAddress** (Required) - The address of the account whose balance will be&#x20;

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAccountAptBalance?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched Account Apt Balance Successfully",
  "data": 8.2344617
}
```

**Example Code to Fetch** Wallet Account Aptos Balance **Information:**

The following TypeScript/Node.js script demonstrates how to call the Get Wallet Account Aptos Balance API using the `axios` library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getAccountAptBalance';
    const params = {
        userAddress: 'your_wallet_address'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    console.log("getWalletAccountAptosBalance : ", res);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **19. Update Stop Loss**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/updateStopLoss`](https://perps-tradeapi.kanalabs.io/updateStopLoss)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the take profit values will be updated.
  * **tradeSide** (Required) - The trade side:
    * `true` for the long side.
    * `false` for the short side.
  * newStopLossPrice (Required) - The new stop loss price to be set for the trade.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/updateStopLoss?marketId=66&tradeSide=true&newStopLossPrice=6000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Update stop loss payload built succesfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::update_stop_loss",
    "functionArguments": [
      "501",
      "true",
      7590
    ],
    "typeArguments": []
  }
}
```

**Example Code to Update stop loss price:**

The following TypeScript/Node.js script demonstrates how to call the Get Update Stop Loss Price API using the `axios` library.

```typescript
import { AptosConfig, Aptos, Network, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
import axios from "axios";


async function main(): Promise<void> {
    const config = new AptosConfig({ network: Network.TESTNET });
    const aptos = new Aptos(config);
    const formattedPrivateKey = PrivateKey.formatPrivateKey(
    process.env.APTOS_PRIVATEKEY || '',
    'ed25519' as PrivateKeyVariants
    );
    const account = Account.fromPrivateKey({
    privateKey: new Ed25519PrivateKey(formattedPrivateKey),
    });
    const baseURL = 'https://perps-tradeapi.kanalabs.io/updateStopLoss';
    const params = {
        marketId: 'your_market_id',
        tradeSide: 'your_trade_side',
        newStopLossPrice: 'your_sl_price'
    };
    const res = await axios.get(baseURL, {
        params, headers: {
            'x-api-key': "your_api_key",
        },
    });
    const payloadData = res.data;
    const transactionPayload = await aptos.transaction.build.simple({
        sender: account.accountAddress,
        data: payloadData
    });
    const committedTxn = await aptos.transaction.signAndSubmitTransaction({
        transaction: transactionPayload,
        signer: account,
    });
    await aptos.waitForTransaction({
        transactionHash: committedTxn.hash,
    });
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```


# Kana Perps Websocket API

Overview of supported trading markets and installation prerequisites for using the Websocket API.

## Websocket Overview

### Supported Markets

This Websocket API provides information for the following trading markets:

<table data-header-hidden><thead><tr><th></th><th width="282"></th><th></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td><td><strong>Description</strong></td></tr><tr><td>APT/USDC</td><td>301</td><td>Aptos-based trading market.</td></tr><tr><td>BTC/USDC</td><td>302</td><td>Bitcoin-based trading market.</td></tr><tr><td>ETH/USDC</td><td>303</td><td>Ethereum-based trading market.</td></tr></tbody></table>

### Prerequisites

#### Install Required Packages

Before you begin, install the following dependencies:

```bash
npm install ws
```

This documentation explains how to connect and receive data from the WebSocket streams:  You can connect order book  stream using client initialization code in TypeScript.

### **Endpoint URL :**

* Order Book Stream : [`wss://perps-sdk-ws.kanalabs.io/wsOrderBook`](#endpoints)

**Example Request:**\
\
`wss://perps-sdk-ws.kanalabs.io/wsOrderBook/marketId=301`\
\
Here is the steps to initialize the client code in typescript :\
\
Example code to fetch the Order Book Client Initialization Code:

```typescript
import WebSocket from 'ws';

const marketId = 'your_market_id';

const ws = new WebSocket(`wss://perps-sdk-ws.kanalabs.io/wsOrderBook?marketId=${marketId}`);

ws.on('open', () => {
    console.log('[client] Connected to the server');
    ws.send('Request data from endpoint');
});

ws.on('message', (data) => {
    console.log(`Received a message from the server:, ${data}`);
});

ws.on('close', () => {
    console.log('[client] Disconnected from the server');
});
```


# Kana Perps Python Websocket API

### Supported Markets

<table data-header-hidden><thead><tr><th></th><th width="282"></th><th></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td><td><strong>Description</strong></td></tr><tr><td>APT/USDC</td><td>501</td><td>Aptos-based trading market.</td></tr><tr><td>BTC/USDC</td><td>502</td><td>Bitcoin-based trading market.</td></tr><tr><td>ETH/USDC</td><td>503</td><td>Ethereum-based trading market.</td></tr></tbody></table>

#### WebSocket Client Documentation

**Installation:**

1. **Install Dependencies**: You will need the `websocket-client` library. Install it using pip:

```python
pip install websocket-client
```

### 1. WebSocket Client for Subscribing to Position Updates

**WebSocket URL:**

`wss://perpetuals-indexer-ws.kanalabs.io/ws`&#x20;

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "positions",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is `positions` in this case.
* **address**: The address to track for position updates.

**Example Response:**

After subscribing, you will receive position updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "positions", "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"}
[client] Received message: {"data":[{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","entry_price":"6050","is_long":false,"last_updated":"1739788459","leverage":2,"liq_price":"8853.658536585366","margin":"3025000","market_id":"396","size":"1000","sl":null,"tp":null,"trade_id":"16509835945970048696716","value":"6050000"}],"message":"positions"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to position updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws.kanalabs.io/ws'

# Address to subscribe to
address = 'your_address'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'positions',
        'address': address,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 2. WebSocket Client for Subscribing to Order Fills Updates

**WebSocket URL:**

`wss://perpetuals-indexer-ws.kanalabs.io/ws`&#x20;

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "trade_history",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is trade\_history in this case.
* **address**: The address to track for order fills updates.

**Example Response:**

After subscribing, you will receive order fills updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "trade_history", "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"}
[client] Received message: {"data":[{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","fee":"3025","last_updated":"1739788459","market_id":"396","order_type":2,"pnl":"0","price":"6050","size":"1000","timestamp":"1739788459","trade_id":"16509835945970048696716"},"message":"trade_history"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to order fills updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws.kanalabs.io/ws'

# Address to subscribe to
address = 'your_address'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'trade_history',
        'address': address,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 3. WebSocket Client for Subscribing to Open Orders Updates

**WebSocket URL:**

`wss://perpetuals-indexer-ws.kanalabs.io/ws`&#x20;

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "open_orders",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is open\_orders in this case.
* **address**: The address to track for open orders updates.

**Example Response:**

After subscribing, you will receive open orders updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "open_orders", "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"}
[client] Received message: {"data":[],"message":"open_orders"}
[client] Received message: {"data":[{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","last_updated":"1739790733","leverage":2,"market_id":"396","order_id":"12907057702855018828273522","order_type":1,"order_value":"6002000","price":"6002","remaining_size":"1000","timestamp":"1739790733","total_size":"1000","trade_id":"16528282690043758248332"}],"message":"open_orders"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to open orders updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws.kanalabs.io/ws'

# Address to subscribe to
address = 'your_address'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'open_orders',
        'address': address,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 4. WebSocket Client for Subscribing to Order history Updates

**WebSocket URL:**

`wss://perpetuals-indexer-ws.kanalabs.io/ws`&#x20;

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "order_history",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is order\_history in this case.
* **address**: The address to track for order history updates.

**Example Response:**

After subscribing, you will receive order history updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "order_history", "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"}
[client] Received message: {"data":[{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","is_market_order":false,"last_updated":"1739790733","leverage":2,"market_id":"396","order_id":"12907057702855018828273522","order_type":1,"order_value":"6002000","price":"6002","size":"1000","status":"Open","timestamp":"1739790733","trade_id":"16528282690043758248332"},{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","is_market_order":false,"last_updated":"1739790700","leverage":2,"market_id":"396","order_id":"12906965467445688751095808","order_type":4,"order_value":"6002000","price":"6002","size":"1000","status":"Filled","timestamp":"1739790700","trade_id":"16509835945970048696716"}],"message":"order_history"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to order history updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws.kanalabs.io/ws'

# Address to subscribe to
address = 'your_address'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'order_history',
        'address': address,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 5. WebSocket Client for Subscribing to Order Book Updates

**WebSocket URL:**

`wss://perpetuals-indexer-ws.kanalabs.io/ws`&#x20;

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "orderbook",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is orderbook in this case.
* **address**: The address to track for order book updates.

**Example Response:**

After subscribing, you will receive order book updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "orderbook", "market_id": "396"}
[client] Received message: {"data":[{"is_ask":true,"last_updated":"1739790988","market_id":"396","price":"6036","size":"169320"},{"is_ask":true,"last_updated":"1739790988","market_id":"396","price":"6037","size":"253735"},{"is_ask":true,"last_updated":"1739790988","market_id":"396","price":"6040","size":"230485"},{"is_ask":true,"last_updated":"1739790996","market_id":"396","price":"6044","size":"255685"},{"is_ask":true,"last_updated":"1739790996","market_id":"396","price":"6051","size":"264082"},{"is_ask":true,"last_updated":"1739790990","market_id":"396","price":"6053","size":"235088"},{"is_ask":true,"last_updated":"1739790996","market_id":"396","price":"6057","size":"230868"},{"is_ask":true,"last_updated":"1739790990","market_id":"396","price":"6059","size":"487477"},{"is_ask":true,"last_updated":"1739758360","market_id":"396","price":"8000","size":"500"},{"is_ask":false,"last_updated":"1739790988","market_id":"396","price":"6031","size":"174998"},{"is_ask":false,"last_updated":"1739790988","market_id":"396","price":"6027","size":"225183"},{"is_ask":false,"last_updated":"1739790988","market_id":"396","price":"6024","size":"244770"},{"is_ask":false,"last_updated":"1739790996","market_id":"396","price":"6019","size":"238312"},{"is_ask":false,"last_updated":"1739790987","market_id":"396","price":"6018","size":"260393"},{"is_ask":false,"last_updated":"1739790996","market_id":"396","price":"6014","size":"267821"},{"is_ask":false,"last_updated":"1739790996","market_id":"396","price":"6011","size":"234869"},{"is_ask":false,"last_updated":"1739790990","market_id":"396","price":"6006","size":"447877"},{"is_ask":false,"last_updated":"1739790990","market_id":"396","price":"6002","size":"1000"},{"is_ask":false,"last_updated":"1739779575","market_id":"396","price":"5800","size":"103303"}],"message":"orderbook"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to order book updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws.kanalabs.io/ws'

# Address to subscribe to
market_id= 'your_market_id'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'orderbook',
        'market_id': market_id,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()    

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```


# Kana Perps Python REST API

## **1. Get Market Info**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getMarketInfo`](#id-1.-get-market-info)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `marketId` (Required) - The ID of the market you want information about.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getMarketInfo?marketId=501
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Market information fetched successfully",
  "data": [
    {
      "__variant__": "V1",
      "base_decimals": 8,
      "base_name": "APT/USDC",
      "counter": "17",
      "creator": "0xb61d7b57333abf8ac036e752f19d0ba0c4baa5404db1cbf868c57dac3628f2bf",
      "lot_size": "100000",
      "maintenance_margin": "250",
      "market_address": "0xfd8d58fdd05dd9d0442a9d555a4f8ed310112eb7d1c297307038a650136e207b",
      "market_id": "501",
      "max_leverage": "20",
      "max_lots": "150000000",
      "min_lots": "500",
      "quote_decimals": 6,
      "quote_precision": 3,
      "tick_size": "1"
    }
  ]
}
```

**Example Code to Fetch Market Information:**

The following Python script demonstrates how to call the Get Market Info API using the requests library.

```python
import requests
import os
from dotenv import load_dotenv
load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getMarketInfo'
        params = {
            'marketId': 'your_market_id'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_market_info = response.json()
        print("getMarketInfo: ", get_market_info)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **2.** Get Wallet Account Balance

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getWalletAccountBalance`](https://perps-tradeapi.kanalabs.io/getWalletAccountBalance)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `userAddress` (Required) - The wallet address for which the account balance is being fetched.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getWalletAccountBalance?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched wallet account balance successfully",
  "data": "16391.60"
}
```

**Example Code to Fetch** Wallet Account Balance **Information:**

The following Python script demonstrates how to call the Get Wallet Account Balance API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv
load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getWalletAccountBalance'
        params = {
            'userAddress': 'your_wallet_address'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_wallet_account_balance = response.json()
        print("getWalletAccountBalance: ", get_wallet_account_balance)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **3.** Get Profile Balance Snapshot

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getProfileBalanceSnpashot`](https://perps-tradeapi.kanalabs.io/getProfileBalanceSnpashot)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `userAddress` (Required) - The wallet address for which the account balance is being fetched.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getProfileBalanceSnpashot?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Profile balance snapshot fetched successfully",
  "data": "44.321972"
}
```

**Example Code to Fetch** Trading Account Balance **Information:**

The following Python script demonstrates how to call the Get Trading Account Balance API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv
load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getProfileBalanceSnpashot'
        params = {
            'userAddress': 'your_wallet_address'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_trading_account_balance = response.json()
        print("getTradingAccountBalance: ", get_trading_account_balance)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **4. Deposit**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/deposit`](https://perps-tradeapi.kanalabs.io/deposit)
* **Method**:\
  `GET`
* **Query Parameters:**
  * `amount` (Required) - The amount of the quote coin to deposit.
  * `userAddress` (Required) - The address of the user making the deposit.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/deposit?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&amount=50000000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Deposit payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::deposit",
    "functionArguments": [
      "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
      50000000
    ],
    "typeArguments": []
  }
}
```

**Example Code to Depsoit a quote coin:**

The following Python script demonstrates how to call the Get Deposit API using the requests library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.account_address import AccountAddress  # Import this
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List
load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/deposit"
    PARAMS = {
        "userAddress":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
        "amount": 50
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)
    
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            AccountAddress.from_str(payload_data["functionArguments"][0]),  
            int(payload_data["functionArguments"][1]),
        ]
        payload_data["argumentTypes"] = [Serializer.struct, Serializer.u64]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **5. Withdraw Specific Market**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket`](https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket)
* **Method**:\
  `GET`
* **Query Parameters**:
  * `marketId` (Required) - The ID of the market you want to withdraw.
  * `amount` (Required) - The amount of the quote coin to withdraw.
  * `userAddress` (Required) - The address of the user making the withdraw.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket?marketId=501&userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&amount=50
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Withdraw specific market payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::withdraw_specific_market",
    "functionArguments": [
      "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
      "501",
      50000000
    ],
    "typeArguments": []
  }
}
```

**Example Code to Withdraw a quote coin:**

The following Python script demonstrates how to call the Get Withdraw API using the requests library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.account_address import AccountAddress  # Import this
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List
load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/withdrawSpecifiMarket"
    PARAMS = {
        "userAddress": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
        "marketId": 501,
        "amount": 50
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)
    
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            AccountAddress.from_str(payload_data["functionArguments"][0]),  
            int(payload_data["functionArguments"][1]),
            int(payload_data["functionArguments"][1]),
        ]
        payload_data["argumentTypes"] = [Serializer.struct, Serializer.u64, Serializer.u64]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **6. Place Limit Order**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/placeLimitOrder`](https://perps-tradeapi.kanalabs.io/placeLimitOrder)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market where the limit order will be placed.
  * **tradeSide** (Required) - Indicates the trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **direction** (Required) - Indicates the direction of the trade:
    * `false` to open a position.
    * `true` to close a position.
  * **size** (Required) - The size of the order.
  * **price** (Required) - The price at which the order is to be placed.
  * **leverage** (Required) - The leverage to be used for the order.
  * **restriction**  - Specifies the type of order restriction. It is an optional parameter with a default value of `0`.\
    Possible values are:
    * `0` - `NO_RESTRICTION`: Optionally fill as a taker, then post to the book as a maker.
    * `1` - `FILL_OR_ABORT`: Abort if any size posts as a maker (only fill).
    * `3` - `POST_OR_ABORT`: Abort if any size fills as a taker (only post).
    * If `restriction` is not provided, it defaults to `0`. It can either be a number or left undefined.
  * **takeProfit** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
  * **stopLoss** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/placeLimitOrder/?marketId=501&tradeSide=true&direction=false&size=10000&price=3000&leverage=3
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Limit Order payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::place_limit_order",
    "functionArguments": [
      "501",
      "true",
      "false",
      1000000,
      8000000,
      "5",
      0,
      0,
      0
    ],
    "typeArguments": []
  }
}
```

**Example Code to Place a limit order:**

The following Python script demonstrates how to call the Get Place Limit Order API using the requests library.

```python
import asyncio
import os
import requests
from dotenv import load_dotenv
from typing import List
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag

load_dotenv()

class AptosTransactionHandler:
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List, types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            module, function_id = "::".join(payload["function"].split("::")[:-1]), payload["function"].split("::")[-1]
            function_arguments = self.create_transaction_function_arguments(payload["functionArguments"], payload["argumentTypes"])
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            
            entry_function = EntryFunction.natural(module=module, function=function_id, ty_args=type_arguments, args=function_arguments)
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction = await self.rest_client.create_bcs_signed_transaction(self.account, transaction_payload)
            txn_hash = await self.rest_client.submit_bcs_transaction(signed_transaction)
            await self.rest_client.wait_for_transaction(txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')

    if not private_key_hex:
        print("Error: APTOS_PRIVATEKEY is missing in .env file.")
        return

    account = Account.load_key(bytes.fromhex(private_key_hex[2:] if private_key_hex.startswith("0x") else private_key_hex))
    rest_client = RestClient(NODE_URL)

    API_URL = "https://perps-tradeapi.kanalabs.io/placeLimitOrder"
    PARAMS = {"marketId": 501, "tradeSide": True, "direction": False, "size": 2, "price": 7, "leverage": 2}
    HEADERS = {"x-api-key": os.getenv('API_KEY')}

    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)

    if not payload_data:
        print("Failed to fetch payload data.")
        return

    try:
        payload_data["functionArguments"] = [
            int(payload_data["functionArguments"][0]),
            payload_data["functionArguments"][1].lower() == "true",
            payload_data["functionArguments"][2].lower() == "true",
            *map(int, payload_data["functionArguments"][3:])
        ]

        payload_data["argumentTypes"] = [
            Serializer.u64, Serializer.bool, Serializer.bool, Serializer.u64,
            Serializer.u64, Serializer.u64, Serializer.u8, Serializer.u64, Serializer.u64
        ]

        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Hash: {txn_hash}")

    except Exception as e:
        print(f"Transaction process error: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **7. Place Market Order**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/placeMarketOrder`](https://perps-tradeapi.kanalabs.io/placeMarketOrder)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market where the limit order will be placed.
  * **tradeSide** (Required) - Indicates the trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **direction** (Required) - Indicates the direction of the trade:
    * `false` to open a position.
    * `true` to close a position.
  * **size** (Required) - The size of the order.
  * **leverage** (Required) - The leverage to be used for the order.
  * **takeProfit** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
  * **stopLoss** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/placeMarketOrder?marketId=66&tradeSide=false&direction=true&size=1000&leverage=20
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Market Order payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::place_market_order",
    "functionArguments": [
      "501",
      "true",
      "false",
      1000000,
      "5",
      0,
      0
    ],
    "typeArguments": []
  }
}
```

**Example Code to Place a market order:**

The following Python script demonstrates how to call the Get Place Market Order API using the requests library.

```python
import asyncio
import os
import requests
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag
from dotenv import load_dotenv
from typing import List

load_dotenv()

class AptosTransactionHandler:
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url: str, params: dict, headers: dict) -> dict | None:
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            module, function_id = "::".join(payload["function"].split("::")[:-1]), payload["function"].split("::")[-1]
            type_arguments = [TypeTag(StructTag.from_str(arg)) for arg in payload["typeArguments"]]
            function_arguments = [TransactionArgument(arg, serializer) for arg, serializer in zip(payload["functionArguments"], payload["argumentTypes"])]

            return TransactionPayload(payload=EntryFunction.natural(module, function_id, type_arguments, function_arguments))
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_txn = await self.rest_client.create_bcs_signed_transaction(sender=self.account, payload=transaction_payload)
            txn_hash = await self.rest_client.submit_bcs_transaction(signed_transaction=signed_txn)
            await self.rest_client.wait_for_transaction(txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    API_URL = "https://perps-tradeapi.kanalabs.io/placeMarketOrder"
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    PARAMS = {"marketId": 501, "tradeSide": True, "direction": False, "size": 2, "leverage": 2}

    rest_client = RestClient(NODE_URL)
    private_key = os.getenv('APTOS_PRIVATEKEY', "").lstrip("0x")
    
    if not private_key:
        print("Error: APTOS_PRIVATEKEY is missing in .env file.")
        return

    account = Account.load_key(bytes.fromhex(private_key))
    handler = AptosTransactionHandler(rest_client, account)
    
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)
    if not payload_data:
        print("Failed to fetch payload data.")
        return

    try:
        payload_data["functionArguments"] = [
            int(payload_data["functionArguments"][0]),
            payload_data["functionArguments"][1].lower() == "true",
            payload_data["functionArguments"][2].lower() == "true",
            *map(int, payload_data["functionArguments"][3:])
        ]

        payload_data["argumentTypes"] = [Serializer.u64, Serializer.bool, Serializer.bool] + [Serializer.u64] * (len(payload_data["functionArguments"]) - 3)

        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")

        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Hash: {txn_hash}")

    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())

```

## **8. Cancel Multiple Orders**

* **Endpoint URL**:\
  [`htps://perps-tradeapi.kanalabs.io/cancelMultipleOrders`](#api-overview)
* **Method**:\
  `POST`
* **Request Body**:
  * **marketId**: The ID of the market for which the orders will be canceled.
  * **orderIds**: A list of order IDs to cancel.
  * cancelTradeSides: The sides of the orders to cancel (true for long, false for short).

**Example Request:**

```json
{
  "marketId": 66,
  "cancelOrderIds": ["1077898597726583798162207", "1077880153515406921884445"],
  "orderSides": [true, false]
}
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Cancel Multiple Orders payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::cancel_multiple_orders",
    "functionArguments": [
      501,
      [
        "1077898597726583798162207",
        "1077880153515406921884445"
      ],
      [
        true,
        false
      ]
    ],
    "typeArguments": []
  }
}
```

**Example Code to Cancel multiple orders:**

The following Python script demonstrates how to call the Post Cancel Multiple Orders API using the requests library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List

load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, json_data, headers):
        try:
            response = requests.post(api_url, json=json_data, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        try:
            return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]
        except Exception as e:
            print(f"Error creating transaction arguments: {e}")
            raise

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    
    API_URL = "https://perps-tradeapi.kanalabs.io/cancelMultipleOrders"
    BODY = {
        "marketId": 501,
        "cancelOrderIds": [627189579998281341784],
        "orderSides": [True]
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, BODY, HEADERS)
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            BODY["marketId"], 
            BODY["cancelOrderIds"], 
            BODY["orderSides"]
        ]
        payload_data["argumentTypes"] = [
            Serializer.u64,
            Serializer.sequence_serializer(Serializer.u128),
            Serializer.sequence_serializer(Serializer.bool)
        ]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **8. Place Multiple Orders**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/placeMultipleOrders`](https://perps-tradeapi.kanalabs.io/placeMultipleOrders)
* **Method**:\
  `POST`

Request Body :

* marketId (Required) - The ID of the market where the orders will be placed.
* orderTypes (Required) - An array of order types for each order:
  * true for limit orders.
  * false for market orders.
* tradeSides (Required) - An array indicating the trade sides for each order:
  * true for long positions.
  * false for short positions.
* directions (Required) - An array indicating the direction of each trade:
  * false to open a position.
  * true to close a position.
* sizes (Required) - An array of sizes for each order.
* leverages (Required) - An array of leverages for each order.
* prices (Required) - An array of prices at which each order is to be placed.
* **restriction**  - Specifies the type of order restriction. It is an optional parameter with a default value of `0`.\
  Possible values are:
  * `0` - `NO_RESTRICTION`: Optionally fill as a taker, then post to the book as a maker.
  * `1` - `FILL_OR_ABORT`: Abort if any size posts as a maker (only fill).
  * `3` - `POST_OR_ABORT`: Abort if any size fills as a taker (only post).
  * If `restriction` is not provided, it defaults to `0`. It can either be a number or left undefined.
* **takeProfits** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
* **stopLosses** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```json
{
  "marketId": 66,
  "orderTypes": [true, true],
  "tradeSides": [true, true],
  "directions": [true, true],
  "sizes": [1000, 1000],
  "prices": [1000, 1000],
  "leverages": [2, 2]
}
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Multiple Orders payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::place_multiple_orders",
    "functionArguments": [
      501,
      [
        true,
        true
      ],
      [
        true,
        true
      ],
      [
        true,
        true
      ],
      [
        1000,
        1000
      ],
      [
        4670,
        6780
      ],
      [
        2,
        2
      ],
      [
        0,
        0
      ],
      [
        4600
      ],
      [
        0,
        0
      ]
    ],
    "typeArguments": []
  }
}
```

**Example Code to Place a multiple orders:**

The following Python script demonstrates how to call the Get Place Multiple Orders API using the requests library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List

load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url: str, json_data: dict, headers: dict) -> dict:
     try:
        response = requests.post(api_url, json=json_data, headers=headers)
        response.raise_for_status()
        payload_data = response.json().get("data")
        if payload_data is None:
            print("No data returned from API.")
            return {}
        # Dynamically ensure the length matches the sizes provided
        payload_data["takeProfits"] = payload_data.get("takeProfits", [0] * len(json_data["sizes"]))
        payload_data["stopLosses"] = payload_data.get("stopLosses", [0] * len(json_data["sizes"]))
        payload_data["restrictions"] = payload_data.get("restrictions", [0] * len(json_data["sizes"]))
        return payload_data
     except requests.exceptions.RequestException as e:
        print(f"Error fetching payload: {e}")
        return {}

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        try:
            return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]
        except Exception as e:
            print(f"Error creating transaction arguments: {e}")
            raise

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/placeMultipleOrders"
    BODY = {
        "marketId": 501,
        "orderTypes": [True],
        "tradeSides": [True],
        "directions": [False],
        "sizes": [1000],
        "prices": [7],
        "leverages": [2]
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, BODY, HEADERS)
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            BODY["marketId"], 
            BODY["orderTypes"], 
            BODY["tradeSides"],
            BODY["directions"], 
            BODY["sizes"], 
            BODY["prices"],
            BODY["leverages"],
            payload_data["restrictions"],
            payload_data["takeProfits"], 
            payload_data["stopLosses"]
        ]
        payload_data["argumentTypes"] = [
            Serializer.u64,
            Serializer.sequence_serializer(Serializer.bool),
            Serializer.sequence_serializer(Serializer.bool),
            Serializer.sequence_serializer(Serializer.bool),
            Serializer.sequence_serializer(Serializer.u64),
            Serializer.sequence_serializer(Serializer.u64),
            Serializer.sequence_serializer(Serializer.u64),
            Serializer.sequence_serializer(Serializer.u8),
            Serializer.sequence_serializer(Serializer.u64),
            Serializer.sequence_serializer(Serializer.u64)
        ]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **9. Cancel and Place Multiple Orders**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/cancelAndPlaceMultipleOrders`](https://perps-tradeapi.kanalabs.io/cancelAndPlaceMultipleOrders)
* **Method**:\
  `POST`

Request Body :

* marketId (Required) - The ID of the market where the orders will be placed.
* cancelOrderIds **(Required)** - An array of strings representing the IDs of the orders to be canceled.
* orderSides **(Required)** - An array indicating the sides of the orders being canceled:
  * `true` for long sides.
  * `false` for short sides.
* orderTypes (Required) - An array of order types for each order:
  * true for limit orders.
  * false for market orders.
* tradeSides (Required) - An array indicating the trade sides for each order:
  * true for long positions.
  * false for short positions.
* directions (Required) - An array indicating the direction of each trade:
  * false to open a position.
  * true to close a position.
* sizes (Required) - An array of sizes for each order.
* leverages (Required) - An array of leverages for each order.
* prices (Required) - An array of prices at which each order is to be placed.
* **restriction**  - Specifies the type of order restriction. It is an optional parameter with a default value of `0`.\
  Possible values are:
  * `0` - `NO_RESTRICTION`: Optionally fill as a taker, then post to the book as a maker.
  * `1` - `FILL_OR_ABORT`: Abort if any size posts as a maker (only fill).
  * `3` - `POST_OR_ABORT`: Abort if any size fills as a taker (only post).
  * If `restriction` is not provided, it defaults to `0`. It can either be a number or left undefined
* **takeProfits** - The take profit value is optional. If not provided, it defaults to `0`. It can either be a number or left undefined.
* **stopLosses** - The stop loss value is also optional. If not provided, it defaults to `0`. It can either be a number or left undefined.

**Example Request:**

```json
{
  "marketId": 66,
  "cancelOrderIds": [23434565434567", "454345665456],
  "orderSides": [true, true],
  "orderTypes": [true, true],
  "tradeSides": [true, false],
  "directions": [true, true],
  "sizes": [1000, 2000],
  "prices": [5000, 6000],
  "leverages": [2, 2]
}
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Cancel and place multiple Orders payload has been built successfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::cancel_and_place_multiple_orders",
    "functionArguments": [
      501,
      [
        "23434565434567",
        "454345665456"
      ],
      [
        "true",
        "true"
      ],
      [
        true,
        true
      ],
      [
        true,
        false
      ],
      [
        true,
        true
      ],
      [
        1000,
        2000
      ],
      [
        5000,
        6000
      ],
      [
        2,
        2
      ],
      [
        0,
        0
      ],
      [
        0,
        0
      ],
      [
        0,
        0
      ]
    ],
    "typeArguments": []
  }
}
```

**Example Code to cancel and Place a multiple orders:**

The following TypeScript/Node.js script demonstrates how to call the Get Cancel And Place Multiple Orders API using the `axios` library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List

load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url: str, json_data: dict, headers: dict) -> dict:
     try:
        response = requests.post(api_url, json=json_data, headers=headers)
        response.raise_for_status()
        payload_data = response.json().get("data")
        if payload_data is None:
            print("No data returned from API.")
            return {}
        # Dynamically ensure the length matches the sizes provided
        payload_data["takeProfits"] = payload_data.get("takeProfits", [0] * len(json_data["sizes"]))
        payload_data["stopLosses"] = payload_data.get("stopLosses", [0] * len(json_data["sizes"]))
        payload_data["restrictions"] = payload_data.get("restrictions", [0] * len(json_data["sizes"]))
        return payload_data
     except requests.exceptions.RequestException as e:
        print(f"Error fetching payload: {e}")
        return {}

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        try:
            return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]
        except Exception as e:
            print(f"Error creating transaction arguments: {e}")
            raise

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/cancelAndPlaceMultipleOrders"
    BODY = {
        "marketId": 501,
        "cancelOrderIds": [664083068162880314200],
        "orderSides": [True],
        "orderTypes": [True],
        "tradeSides": [True],
        "directions": [False],
        "sizes": [1000],
        "prices": [7],
        "leverages": [2]
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, BODY, HEADERS)
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            BODY["marketId"],
            BODY["cancelOrderIds"], 
            BODY["orderSides"],
            BODY["orderTypes"], 
            BODY["tradeSides"],
            BODY["directions"], 
            BODY["sizes"], 
            BODY["prices"],
            BODY["leverages"],
            payload_data["restrictions"],
            payload_data["takeProfits"], 
            payload_data["stopLosses"]
        ]
        payload_data["argumentTypes"] = [
            Serializer.u64,
            Serializer.sequence_serializer(Serializer.u128),
            Serializer.sequence_serializer(Serializer.bool),
            Serializer.sequence_serializer(Serializer.bool),
            Serializer.sequence_serializer(Serializer.bool),
            Serializer.sequence_serializer(Serializer.bool),
            Serializer.sequence_serializer(Serializer.u64),
            Serializer.sequence_serializer(Serializer.u64),
            Serializer.sequence_serializer(Serializer.u64),
            Serializer.sequence_serializer(Serializer.u8),
            Serializer.sequence_serializer(Serializer.u64),
            Serializer.sequence_serializer(Serializer.u64)
        ]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **10.** Get Open Orders

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getOpenOrders`](https://perps-tradeapi.kanalabs.io/getOpenOrders)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve open orders for.
  * **marketId** - The ID of the market to filter open orders.  // Optional

```
Note : order_type Explanation:

OPEN_LONG (1): Opens a new long position.
OPEN_SHORT (2): Opens a new short position.
INCREASE_LONG (3): Increases the size of an existing long position.
INCREASE_SHORT (4): Increases the size of an existing short position.
DECREASE_LONG (5): Reduces the size of an existing long position.
DECREASE_SHORT (6): Reduces the size of an existing short position.
CLOSE_LONG (7): Closes an existing long position.
CLOSE_SHORT (8): Closes an existing short position.
```

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOpenOrders?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched open orders successfully",
  "data": [
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": "1741444213",
      "price": "7",
      "total_size": "2",
      "remaining_size": "2",
      "order_value": "14",
      "order_id": "645636324063400958808",
      "trade_id": "295147905179352826357",
      "last_updated": "1741444214"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": "1741445758",
      "price": "7",
      "total_size": "2",
      "remaining_size": "2",
      "order_value": "14",
      "order_id": "682529812245179800408",
      "trade_id": "295147905179352826357",
      "last_updated": "1741445758"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": "1741446786",
      "price": "7",
      "total_size": "2",
      "remaining_size": "2",
      "order_value": "14",
      "order_id": "700976556301709482840",
      "trade_id": "295147905179352826357",
      "last_updated": "1741446786"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": "1741446907",
      "price": "7",
      "total_size": "2",
      "remaining_size": "2",
      "order_value": "14",
      "order_id": "719423300401188838232",
      "trade_id": "295147905179352826357",
      "last_updated": "1741446908"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": "1741447619",
      "price": "0.007",
      "total_size": "1",
      "remaining_size": "1",
      "order_value": "0.007",
      "order_id": "737869903703050289159",
      "trade_id": "295147905179352826357",
      "last_updated": "1741447620"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 3,
      "timestamp": "1741447815",
      "price": "0.007",
      "total_size": "1",
      "remaining_size": "1",
      "order_value": "0.007",
      "order_id": "756316647793939709959",
      "trade_id": "295147905179352826357",
      "last_updated": "1741447815"
    }
  ]
}
```

**Example Code to Fetch** Open Order&#x73;**:**

The following Python script demonstrates how to call the Get Open Orders API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getOpenOrders'
        params = {
            'marketId': 501,
            'userAddress': "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_open_orders = response.json()
        print("getOpenOrders: ", get_open_orders)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **11.** Get Order History

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getOrderHistory`](https://perps-tradeapi.kanalabs.io/getOrderHistory)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address to retrieve the order history for.
  * **marketId** (optional) - The ID of the market to filter the order history.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOrderHistory?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770&marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched order history successfully",
  "data": [
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 1,
      "timestamp": "1741167151",
      "is_market_order": false,
      "size": "1.50",
      "price": "4.678",
      "order_value": "7.01700",
      "status": "Open",
      "order_id": "18446884819787846214",
      "trade_id": "18446744073709552117",
      "last_updated": "1741262093"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 1,
      "timestamp": "1741236277",
      "is_market_order": false,
      "size": "1.50",
      "price": "4.678",
      "order_value": "7.01700",
      "status": "Cancelled",
      "order_id": "18446884819787846214",
      "trade_id": "18446744073709552117",
      "last_updated": "1741262168"
    },
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "order_type": 1,
      "timestamp": "1741236468",
      "is_market_order": false,
      "size": "1.50",
      "price": "4.50",
      "order_value": "6.7500",
      "status": "Open",
      "order_id": "36893628893497397652",
      "trade_id": "36893488147419103733",
      "last_updated": "1741262168"
    }
  }
]
```

**Example Code to Fetch Order History:**

The following Python script demonstrates how to call the Get Order History API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getOrderHistory'
        params = {
            'marketId': 501,
            'userAddress': "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_order_history = response.json()
        print("getOrderHistory: ", get_order_history)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **12.** Get Positions

* **Endpoint URL**:\
  [h`ttps://perps-tradeapi.kanalabs.io/getPositions`](https://perps-tradeapi.kanalabs.io/getPositions)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **userAddress** (Required) - The wallet address of the user to view positions for.
  * **marketId** (optional) - The ID of the market to filter the positions.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getPositions?marketId=66&userAddress=0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched positions successfully",
  "data": [
    {
      "address": "0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e",
      "market_id": "501",
      "leverage": 2,
      "is_long": true,
      "size": "1",
      "available_order_size": "1",
      "value": "5.678",
      "entry_price": "5.678",
      "liq_price": "2.9117948717948717990163355253",
      "margin": "2.839",
      "tp": "6.012",
      "sl": null,
      "trade_id": "295147905179352826357",
      "last_updated": "1741262185"
    }
  ]
}
```

**Example Code to Fetch** Open Positio&#x6E;**:**

The following Python script demonstrates how to call the Get Open Position API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getPositions'
        params = {
            'marketId': 501,
            'userAddress': "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_open_position = response.json()
        print("getOpenPosition: ", get_open_position)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **12.** Get All Trades

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAllTrades`](https://perps-tradeapi.kanalabs.io/getAllTrades)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market to retrieve all trades information.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAllTrades?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Recent trades fetched successfully",
  "data": [
    {
      "txn_version": 6297687196,
      "event_idx": 5,
      "emit_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "time": "2024-11-20T20:33:38.600241+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15951655917465922493754983",
      "maker_side": true,
      "market_id": 66,
      "price": 11879,
      "sequence_number_for_trade": 0,
      "size": 10000,
      "taker_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "taker_custodian_id": 28,
      "taker_order_id": "15951748150764039921729536",
      "taker_quote_fees_paid": 59395
    },
    {
      "txn_version": 6297687196,
      "event_idx": 4,
      "emit_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "time": "2024-11-20T20:33:38.600241+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15951655917465922493754983",
      "maker_side": true,
      "market_id": 66,
      "price": 11879,
      "sequence_number_for_trade": 0,
      "size": 10000,
      "taker_address": "0x13eb7ea6b62c6cd791b5c4e0e2ef1dfbe59d1cf4823929343a273274c288bc8a",
      "taker_custodian_id": 28,
      "taker_order_id": "15951748150764039921729536",
      "taker_quote_fees_paid": 59395
    }
  ]
}
```

**Example Code to Fetch** All trade&#x73;**:**

The following Python script demonstrates how to call the Get Open Position API using the requests library.

```typescript
import axios from "axios";

async function main(): Promise<void> {
    const baseURL = 'https://perps-tradeapi.kanalabs.io/getAllTrades';
    const params = {
        marketId: 'your_market_id'
    };
    const res = await axios.get(baseURL, {
        params, 
        headers: {
            'x-api-key': process.env.API_KEY,
        },
    });
    const getAllTrades = res.data;
    console.log("getAllTrades : ", getAllTrades);
}

main().catch(error => {
    console.error('An error occurred:', error);
});
```

## **13.** Get Order Status By Order Id

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId`](https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market associated with the order.
  * **orderId** (Required) - The unique identifier of the order to retrieve its status.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId?marketId=66&orderId=15308325717473050761363456
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "status": true,
  "message": "Fetched order status for a given order Id successfully",
  "data": {
    "market_id": 66,
    "order_id": "15308325717473050761363456",
    "created_at": "2024-11-20T11:54:45.957059+00:00",
    "last_updated_at": "2024-11-20T11:54:45.957059+00:00",
    "integrator": "0xee820ab02631dd1a195d3c53fa64f0a8f455dbb9261388e141c3bd3bd3c08363",
    "total_filled": 1000,
    "remaining_size": 0,
    "order_status": "closed",
    "order_type": "market",
    "user": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770",
    "direction": "buy",
    "price": 0,
    "average_execution_price": 12813,
    "custodian_id": 28,
    "self_match_behavior": 0,
    "restriction": 0,
    "last_increase_stamp": null,
    "min_base": null,
    "max_base": null,
    "min_quote": null,
    "max_quote": null,
    "total_fees_paid_in_quote_subunits": 6406
  }
}
```

**Example Code to Fetch** Order Status B Order I&#x64;**:**

The following Python script demonstrates how to call the Get Order Status By Order Id API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getOrderStatusByOrderId'
        params = {
            'marketId': 'your_market_id',
            'orderId': 'your_order_id'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_order_status_by_order_id = response.json()
        print("getOrderStatusByOrderId: ", get_order_status_by_order_id)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **14.** Get Fills

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getFills`](https://perps-tradeapi.kanalabs.io/getFills)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which fills are retrieved.
  * **address** (Optional) - The address of the user to filter fills (if applicable).
  * **from** (Required) - The start time of the range in ISO 8601 format (e.g., `2024-11-21T00:00:00Z`).
  * **to** (Required) - The end time of the range in ISO 8601 format (e.g., `2024-11-21T23:59:59Z`).
  * **orderId** (Required) - The unique identifier of the order to retrieve its status.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getFills?marketId=66&address=0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2&from=2024-11-20T00:00:00Z&to=2024-11-21T23:59:59Z
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched fill trades for a given time range Successfully",
  "data": [
    {
      "txn_version": 6296434935,
      "event_idx": 1,
      "emit_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "time": "2024-11-20T19:23:14.67535+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15891335065048614061485282",
      "maker_side": true,
      "market_id": 66,
      "price": 11490,
      "sequence_number_for_trade": 0,
      "size": 1000,
      "taker_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "taker_custodian_id": 28,
      "taker_order_id": "15891427297643009687945216",
      "taker_quote_fees_paid": 5745
    },
    {
      "txn_version": 6295302625,
      "event_idx": 4,
      "emit_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "time": "2024-11-20T18:19:35.70863+00:00",
      "maker_address": "0x2eda5777ed2bf68cbcc67359dd00ae5fa73b1d5fa160b7c3aeb42d748d485387",
      "maker_custodian_id": 28,
      "maker_order_id": "15812401447297883953966476",
      "maker_side": false,
      "market_id": 66,
      "price": 11660,
      "sequence_number_for_trade": 0,
      "size": 1000,
      "taker_address": "0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2",
      "taker_custodian_id": 28,
      "taker_order_id": "15812549019983827645235200",
      "taker_quote_fees_paid": 5830
    }
  ]
}
```

**Example Code to Fetch** Order Status B Order IdFills Dat&#x61;**:**

The following Python script demonstrates how to call the Get Fills Data API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getFills'
        params = {
            'marketId': 'your_market_id',
            'address': 'your_address',
            'from': 'your_from_time',
            'to': 'your_to_time'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_fills_data = response.json()
        print("getFillsData: ", get_fills_data)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **14.** Get Market Price

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getMarketPrice`](https://perps-tradeapi.kanalabs.io/getMarketPrice)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the price information is being retrieved.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getMarketPrice?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched Market Price Successfully",
  "data": {
    "bestAskPrice": 6.400,
    "bestBidPrice": 9.880
  }
}
```

**Example Code to Fetch** Market Pric&#x65;**:**

The following Python script demonstrates how to call the Get Market Price API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getMarketPrice'
        params = {
            'marketId': 501
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_market_price = response.json()
        print("getMarketPrice: ", get_market_price)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **15.** Get Last Execution Price

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getLastPlacedPrice`](https://perps-tradeapi.kanalabs.io/getLastPlacedPrice)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the last execution price information is being retrieved.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getLastPlacedPrice?marketId=66
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched last execution price Successfully",
  "data": 8.989
}
```

**Example Code to Fetch** Last Execution Pric&#x65;**:**

The following Python script demonstrates how to call the Get Last Execution Price API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getLastPlacedPrice'
        params = {
            'marketId': '501'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_last_execution_price = response.json()
        print("getLastExecutionPrice: ", get_last_execution_price)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **16.** Get All Open Order Ids

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds`](https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds)
* **Method**:\
  `GET`
* **Query Parameters**:
  * userAddress(Required) - The address associated with the orders.
  * **marketId** (optional) - The ID of the market for which open order IDs are being retrieved.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds?marketId=66&userAddress=0x3a6b332c7889784fe57ea61f507b5056e386db8f56c6323b4d898485f468f0c2
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Open order IDs fetched successfully",
  "data": [
    "645636324063400958808",
    "682529812245179800408",
    "700976556301709482840",
    "719423300401188838232",
    "737869903703050289159",
    "756316647793939709959"
  ]
}
```

**Example Code to Fetch** Open Order Id&#x73;**:**

The following Python script demonstrates how to call the Get Open Order Ids API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getAllOpenOrderIds'
        params = {
            'userAddress': 'your_wallet_address',
            'marketId': 'your_market_id'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_open_order_ids = response.json()
        print("getOpenOrderIds: ", get_open_order_ids)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **17. Update Take Profit**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/updateTakeProfit`](https://perps-tradeapi.kanalabs.io/updateTakeProfit)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the take profit values will be updated.
  * **tradeSide** (Required) - The trade side:
    * `true` for the long side.
    * `false` for the short side.
  * **newTakeProfitPrice** (Required) - The new take profit price to be set for the trade.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/updateTakeProfit?marketId=66&tradeSide=true&newTakeProfitPrice=6000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Update take profit payload built succesfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::update_take_profit",
    "functionArguments": [
      "501",
      "true",
      7590
    ],
    "typeArguments": []
  }
}
```

**Example Code to Update take profit price:**

The following Python script demonstrates how to call the Get Update Take Profit Price API using the requests library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List
load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/updateTakeProfit"
    PARAMS = {
        "marketId": 501,
        "tradeSide": True,
        "newTakeProfitPrice": 6.89
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)
    
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            int(payload_data["functionArguments"][0]),
            payload_data["functionArguments"][1].lower() == "true",
            int(payload_data["functionArguments"][2]),
        ]
        payload_data["argumentTypes"] = [Serializer.u64, Serializer.bool, Serializer.u64]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```

## **18.** Get Account Aptos Balance

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/getAccountAptBalance`](https://perps-tradeapi.kanalabs.io/getAccountAptBalance)
* **Method**:\
  `GET`
* **Query Parameters**:
* **userAddress** (Required) - The address of the account whose balance will be&#x20;

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/getAccountAptBalance?userAddress=0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Fetched Account Apt Balance Successfully",
  "data": 8.2344617
}
```

**Example Code to Fetch** Wallet Account Aptos Balance **Information:**

The following Python script demonstrates how to call the Get Wallet Account Aptos Balance API using the requests library.

```python
import os
import requests
from dotenv import load_dotenv

load_dotenv()

def main():
    try:
        base_url = 'https://perps-tradeapi.kanalabs.io/getAccountAptBalance'
        params = {
            'userAddress': 'your_wallet_address'
        }
        api_key = os.getenv('API_KEY')
        headers = {
            'x-api-key': api_key
        }
        response = requests.get(base_url, params=params, headers=headers)
        response.raise_for_status()
        get_wallet_account_aptos_balance = response.json()
        print("getWalletAccountAptosBalance: ", get_wallet_account_aptos_balance)
    except requests.exceptions.RequestException as error:
        print('An error occurred:', error)

if __name__ == "__main__":
    main()
```

## **19. Update Stop Loss**

* **Endpoint URL**:\
  [`https://perps-tradeapi.kanalabs.io/updateStopLoss`](https://perps-tradeapi.kanalabs.io/updateStopLoss)
* **Method**:\
  `GET`
* **Query Parameters**:
  * **marketId** (Required) - The ID of the market for which the take profit values will be updated.
  * **tradeSide** (Required) - The trade side:
    * `true` for the long side.
    * `false` for the short side.
  * newStopLossPrice (Required) - The new stop loss price to be set for the trade.

**Example Request:**

```http
GET https://perps-tradeapi.kanalabs.io/updateStopLoss?marketId=66&tradeSide=true&newStopLossPrice=6000
```

**Example Response:**

* **Status Code**: `200 OK`
* **Response Body**:

```json
{
  "success": true,
  "message": "Update stop loss payload built succesfully",
  "data": {
    "function": "0xabbf40e0c31cbedf182f3e6e9c3570f3f91629424723da876becb514bf5d9fc6::perpetual_scripts::update_stop_loss",
    "functionArguments": [
      "501",
      "true",
      7590
    ],
    "typeArguments": []
  }
}
```

**Example Code to Update stop loss price:**

The following Python script demonstrates how to call the Get Update Stop Loss Price API using the requests library.

```python
import asyncio
import os
from aptos_sdk.account import Account
from aptos_sdk.async_client import RestClient
from aptos_sdk.transactions import EntryFunction, TransactionArgument, TransactionPayload
from aptos_sdk.bcs import Serializer
from aptos_sdk.type_tag import TypeTag, StructTag
import requests
from dotenv import load_dotenv
from typing import Any, List
load_dotenv()

class AptosTransactionHandler:
    
    def __init__(self, rest_client: RestClient, account: Account):
        self.rest_client = rest_client
        self.account = account

    def fetch_payload(self, api_url, params, headers):
        try:
            response = requests.get(api_url, params=params, headers=headers)
            response.raise_for_status()
            return response.json().get("data")
        except requests.exceptions.RequestException as e:
            print(f"Error fetching payload: {e}")
            return None

    def create_transaction_function_arguments(self, arguments: List[Any], types: List[Serializer]) -> List[TransactionArgument]:
        if len(arguments) != len(types):
            raise ValueError("Arguments and types length mismatch.")
        
        return [TransactionArgument(arg, serializer) for arg, serializer in zip(arguments, types)]

    def create_transaction_payload(self, payload: dict) -> TransactionPayload:
        try:
            function_information = payload["function"].split("::")
            module = "::".join(function_information[:-1])
            function_id = function_information[-1]
            function_arguments = self.create_transaction_function_arguments(
                payload["functionArguments"],
                payload["argumentTypes"]
            )
            type_arguments = [TypeTag(StructTag.from_str(argument)) for argument in payload["typeArguments"]]
            entry_function = EntryFunction.natural(
                module=module,
                function=function_id,
                ty_args=type_arguments,
                args=function_arguments,
            )
            return TransactionPayload(payload=entry_function)
        except Exception as e:
            print(f"Error creating transaction payload: {e}")
            raise

    async def submit_transaction(self, transaction_payload: TransactionPayload) -> str:
        try:
            signed_transaction_request = await self.rest_client.create_bcs_signed_transaction(
                sender=self.account, payload=transaction_payload
            )
            txn_hash = await self.rest_client.submit_bcs_transaction(
                signed_transaction=signed_transaction_request
            )
            await self.rest_client.wait_for_transaction(txn_hash=txn_hash)
            return txn_hash
        except Exception as e:
            print(f"Error during transaction submission: {e}")
            raise

async def main():
    NODE_URL = "https://api.testnet.aptoslabs.com/v1"
    rest_client = RestClient(NODE_URL)
    private_key_hex = os.getenv('APTOS_PRIVATEKEY')
    if private_key_hex.startswith("0x"):
        private_key_hex = private_key_hex[2:]
    private_key_bytes = bytes.fromhex(private_key_hex)
    account = Account.load_key(private_key_bytes)
    API_URL = "https://perps-tradeapi.kanalabs.io/updateStopLoss"
    PARAMS = {
        "marketId": 501,
        "tradeSide": True,
        "newStopLossPrice": 6.89
    }
    HEADERS = {"x-api-key": os.getenv('API_KEY')}
    handler = AptosTransactionHandler(rest_client, account)
    payload_data = handler.fetch_payload(API_URL, PARAMS, HEADERS)
    
    if not payload_data:
        print("Failed to fetch payload data.")
        return
    
    try:
        payload_data["functionArguments"] = [
            int(payload_data["functionArguments"][0]),
            payload_data["functionArguments"][1].lower() == "true",
            int(payload_data["functionArguments"][2]),
        ]
        payload_data["argumentTypes"] = [Serializer.u64, Serializer.bool, Serializer.u64]
        transaction_payload = handler.create_transaction_payload(payload_data)
        print("Transaction payload created successfully.")
        txn_hash = await handler.submit_transaction(transaction_payload)
        print(f"Transaction submitted successfully. Transaction hash: {txn_hash}")
        
    except Exception as e:
        print(f"Error during transaction process: {e}")

if __name__ == "__main__":
    asyncio.run(main())
```


# Steps to place an order

## **Typescript**

1\. Faucet a usdt to your wallet account\
\
You can check here to faucet the usdt\
usdt\_faucet: <https://explorer.aptoslabs.com/object/0x24246c14448a5994d9f23e3b978da2a354e64b6dfe54220d[>…]c448cc/modules/run/usdt/faucet\_to\_address?network=testnet\
\
2\. After faucet you have to deposit that into your trading account :\
\
<https://docs.kanalabs.io/products-and-features/trading-apis/kana-perps-api/kana-perps-rest-api#id-4.-deposit>\
\
3\. After deposited you have to place the limit or market order:\
\
<https://docs.kanalabs.io/products-and-features/trading-apis/kana-perps-api/kana-perps-arest-api#id-6.-place-limit-order>

## **Python**

1\. Faucet a usdt to your wallet account\
\
You can check here to faucet the usdt\
usdt\_faucet: <https://explorer.aptoslabs.com/object/0x24246c14448a5994d9f23e3b978da2a354e64b6dfe54220d[>…]c448cc/modules/run/usdt/faucet\_to\_address?network=testnet\
\
2\. After faucet you have to deposit that into your trading account :\
\
<https://docs.kanalabs.io/~/changes/JpxQ3y4p9AD4BHUqimHx/products-and-features/trading-apis/kana-perps-api/kana-perps-python-rest-api#id-4.-deposit>\
\
3\. After deposited you have to place the limit or market order:\
\
<https://docs.kanalabs.io/~/changes/JpxQ3y4p9AD4BHUqimHx/products-and-features/trading-apis/kana-perps-api/kana-perps-python-rest-api#id-6.-place-limit-order>


# Kana Labs Build - Blockchain Infra

Kana Labs Build provides developers and businesses with a diverse suite of Web2 -ready tools to simplify blockchain integration and unlock broader markets. Designed to improve user experience, these tools abstract technical complexities to make Web3 more accessible and user-friendly. With efficient growth-focused solutions, Kana Labs supports platforms in adopting Web3 technologies and expanding their reach.

**List of Products -**

* Web3 Aggregator SDK aka Kana Crosschain SDK: Simplify cross-chain integration with unified tools connecting bridges and liquidity sources.
* Paymaster SDK aka Gas Station: Enable gasless transactions to lower entry barriers for users.
* Kana Crosschain Widget: A plug-and-play solution for effortless cross-chain swap integration.
* Mirai SDK (Smart Wallet): Streamline wallet management with account abstraction and keyless onboarding.


# Web3 Aggregator SDK aka Kana Crosschain SDK

This SDK is a toolkit that sits on top of a multi-chain-focused foundational layer and is made of three components -multiple liquidity sources (DEXs & Liquidity Aggregators), a bridge and messaging protocol aggregator and a smart routing algorithm.

The foundational layer consists of 9 different chains from both EVM and non-EVM blockchains. By combining all these components into one unit, we offer an easy-to-use plug-and-play-type SDK that enables a product to instantly gain industry-leading Web3 transaction capabilities.

<figure><img src="/files/spLfMKH9DyqAAABbf6QD" alt=""><figcaption><p>Web 3 Middleware aka Aggregator SDk Design Architecture</p></figcaption></figure>

For more details check out ->&#x20;

{% embed url="<https://docs.kanalabs.io/web3-middleware-sdk/web3-middleware-sdk-aggregator-sdk>" %}


# Mirai SDK – EIP 4337 Based Smart Wallet

This SDK allows dApps and businesses to provide their users with a crypto smart wallet created adhering to the EIP 4337-based account abstraction concept. It has various features that help simplify and abstract away the technical challenges a user faces when making transactions and navigating the crypto world.

Furthermore, this SDK has been created with a focus on real-time application ensuring that it can be used by not only Web3 participants but also Web2 entities across different industries thus ensuring mass adoption and migration from Web2 to Web3 world.

Our smart wallet can be used across DeFi, GameFi, SocialFi and Payment-focused businesses and retail entities.

<figure><img src="/files/mPnyIcJkNaO4hl12TSh7" alt=""><figcaption><p>Smart Wallet Use Cases &#x26; Wofkflow</p></figcaption></figure>

For more details, check out ->

{% embed url="<https://docs.kanalabs.io/smart-wallet-sdk/mirai-sdk-the-evm-smart-wallet-and-paymaster>" %}


# Paymaster SDK

Paymaster technology allows dApps and third-party entities to sponsor gas fees for transactions performed on their platform. It helps business owners and third-party entities to allocate funds for gas fees in a separate account from which gas fees are deducted for transactions carried out by their clients.

The lack of necessity to own source tokens when performing transactions in the Web3 space helps users save money and time and also encourages them to actively make more transactions in the products with sponsored transaction capabilities.

<figure><img src="/files/gybwXNI2A0Hb4qGRn7Y8" alt=""><figcaption><p>Paymaster workflow</p></figcaption></figure>

For more details, check out ->&#x20;

{% embed url="<https://docs.kanalabs.io/paymaster-service/kana-paymaster-for-aptos>" %}


# Kana Crosschain Widget

The Kana Widget is a UI element plug-in tool that helps businesses easily gain secure cross-chain capabilities. This allows businesses to directly integrate with our AMM swap aggregator allowing their clients to swap tokens across 9 different chains with the best price and fast transaction execution timing.

<figure><img src="/files/eKqRiOBFD5OA5XQYsry4" alt=""><figcaption><p>Screenshot of Kana Widget integrated by Liquid Swap</p></figcaption></figure>

For more details, check out->&#x20;

{% embed url="<https://docs.kanalabs.io/integrate-kana-widget/kana-widget>" %}


# Mirai SDK - The EVM Smart Wallet & Paymaster

Elevating the Web3 Experience with Account Abstraction and Multi-Chain Efficiency

Mirai SDK, powered by Kana Labs, represents a revolutionary leap in the Crypto & Web3 landscape, specifically designed to streamline onboarding processes and enhance user experiences within the realms of decentralized applications (dApps) in the DeFi and GameFi sectors, along with crypto wallets. Our innovative smart wallet has been designed as a middleware SDK that acts as a self-custody smart wallet, prioritizing account abstraction features and a robust multi-chain relayer infrastructure. Our SDK is the key to unlocking a more user-centric, efficient, and versatile crypto experience. Join us in redefining the future of crypto adoption and interaction.&#x20;

### Key Features at a Glance - Discover the possibilities with Mirai SDK.

1. **Seamless Multi-Chain Ecosystem**: Mirai SDK empowers users to seamlessly transact across various blockchain networks, including both EVM (Ethereum Virtual Machine) and Non-EVM chains, all through a unified and user-friendly interface. By integrating our smart wallet SDK with our Web3 middleware SDK, developers gain access to a unique environment for crafting efficient dApps. The smart contract wallet empowers users with full control over their assets, while the Web3 middleware facilitates dApp deployment across multiple chains simultaneously, providing users with unparalleled flexibility in managing their DeFi and GameFi operations.
2. **Email/Social Login**: Simplify the user onboarding process by offering login options through email and social media accounts, mirroring the familiar Web2 experience. This feature is pivotal in bridging the gap and onboarding the next wave of users from the Web2 to Web3 ecosystem.
3. **Gasless Transactions**: Users can conveniently cover their transaction gas fees with the same tokens they are transacting, irrespective of the supported blockchain network. In our comprehensive DeFi and GameFi ecosystem, users can use any token from any chain to pay transaction fees.
4. **Larger NFT Ecosystem**: Facilitate a genuine multi-chain environment, fostering a more expansive NFT marketplace. Users can engage with NFTs with greater ease and accessibility, unlocking new opportunities within the NFT space.
5. **Sponsored Transactions**: Enable third-party entities and project backers to cover gas fees for users conducting transactions within their dApps or upon their request. This feature enhances user engagement and encourages participation.
6. **Transaction Batching / Multi-Call**: Simplify transaction handling for users by batching multiple transactions into a single, one-click approval process. Activities such as Approve, Deposit, Borrow, and Stake can be executed seamlessly within a single transaction.
7. **Cross-Chain Bridging**: Achieve true cross-chain transactions effortlessly through a unified interface. Transfer tokens across different chains, including both EVM and Non-EVM chains, and vice versa, all from a single user interface. This functionality is made possible by Kana Labs' Web3 middleware, equipped with multiple third-party messaging protocols and proprietary asset bridges.

### Supported Networks

#### **Mainnets:**

**EVM Chains -**

```
01. mainnet (Ethereum)
02. polygon
03. optimism
04. linea
05. gnosis
06. mantle
07. avalanche
08. base
09. bsc
10. klaytn
11. scroll
12. flare
13. arbitrum
14. bifrost
```

**Non-EVM Chains -**

```
01- aptos 
```

#### Testnets:

**EVM Chains -**

```
01. bscTestnet
02. KlaytnTestnet
03. ScrollSepolia
04. FuseSparknet
05. goerli
06. mumbai
07. sepolia
08. flareTestnet
09. bifrostTestnet
```

**Non- EVM Chains -**

```
01. aptosTestnet
```


# SDK Gateway Functions

<table><thead><tr><th>Functions</th><th>Description</th></tr></thead><tbody><tr><td><p></p><p></p><pre class="language-typescript"><code class="lang-typescript">async initialize(network?: NetworkNames)
</code></pre></td><td><p>To initialize the SDK instance specify a network, and return the result of initialization.</p><p>Returns KanaWallet address</p></td></tr><tr><td><p></p><p></p><pre class="language-typescript"><code class="lang-typescript">async destroy(network?: NetworkNames)
</code></pre></td><td>To destroy the SDK instance specifying a network for destruction, or destroying all instances if no network is provided.</td></tr><tr><td><p></p><p></p><p></p><pre class="language-typescript"><code class="lang-typescript">async getNativeBalance(network?: NetworkNames)
</code></pre></td><td>To get the native token balance of the smart wallet. Returns native token balance</td></tr><tr><td><p></p><p></p><pre class="language-typescript"><code class="lang-typescript">erc1155(collectionAddress: string, network?: NetworkNames)
</code></pre></td><td>To get the ERC1155 collection instance for building ERC1155 transactions. Returns the ERC1155 contract instance</td></tr><tr><td><p></p><p></p><pre class="language-typescript"><code class="lang-typescript">erc20(tokenAddress: string, network?: NetworkNames)
</code></pre></td><td>To get the ERC20 token instance for building ERC20 transactions. Returns the ERC20 contract instance</td></tr><tr><td><p></p><p></p><pre class="language-typescript"><code class="lang-typescript">erc721(collectionAddress: string, network?: NetworkNames)
</code></pre></td><td>To get the ERC721 collection instance for building ERC721 transactions. Returns the ERC721 contract instance</td></tr><tr><td><p></p><p></p><pre class="language-typescript"><code class="lang-typescript">getAptosInstance(network: NetworkNames)
</code></pre></td><td>Retrieve the Aptos SDK instance</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getProvider(network: NetworkNames): providers.JsonRpcProvider 
</code></pre></td><td><p></p><p>To get the RPC Provider for the given network. Returns providers.JsonRpcProvider</p><p><strong>Example</strong> <code>const provider = getProvider(networkName)</code></p></td></tr><tr><td></td><td></td></tr><tr><td><p></p><p></p><pre class="language-typescript"><code class="lang-typescript">isNetworkActive(networkName: string): boolean
</code></pre></td><td><p>To check if the given network is available and active. Returns bool</p><p><strong>Example</strong> <code>const isActive = isNetworkActive(networkName)</code></p></td></tr><tr><td><p></p><p></p><pre class="language-typescript"><code class="lang-typescript">setCurrentInstance(network: NetworkNames)
</code></pre></td><td>To set the default SDK instance and retrieve the SDK instance associated with the specified network  </td></tr><tr><td></td><td></td></tr></tbody></table>


# EVM SDK Functions

Available Methods in SDK

<table><thead><tr><th>Methods</th><th>Description</th></tr></thead><tbody><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getCounterFactualAddress(): Promise&#x3C;string>;
</code></pre></td><td>To get the KanaWallet address</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">signMessage(dto: SignMessageDto): Promise&#x3C;string>;
</code></pre></td><td>To sign a message</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getNativeBalance(): Promise&#x3C;string>;
</code></pre></td><td>To get the native token balance of the wallet</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">addUserOpsToBatch(tx: UserOpsRequest): Promise&#x3C;BatchUserOpsRequest>;
</code></pre></td><td>To add transactions to the batch</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">clearUserOpsFromBatch(): Promise&#x3C;void>;
</code></pre></td><td>To clear the transactions in the batch</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">estimate(gasDetails?: TransactionGasInfoForUserOp): Promise&#x3C;UserOperationStruct>;
</code></pre></td><td>To estimate transactions added to the batch and get the fee data for the UserOp. Returns UserOperationStruct</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">send(userOp: UserOperationStruct): Promise&#x3C;string>;
</code></pre></td><td>To sign the UserOp and send it to the bundler. Returns userOp hash</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">createSession(dto?: CreateSessionDto): Promise&#x3C;Session>
</code></pre></td><td>To sign create a session</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getUserOpReceipt(userOpHash: string): Promise&#x3C;any>
</code></pre></td><td>To get the transaction hash</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getGasFee(): Promise&#x3C;import("./common").Gas>;
</code></pre></td><td>To get the Gas data</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">destroy(): void;
</code></pre></td><td>To destroy the SDK instance</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getUserOpHash(userOp: UserOperationStruct): Promise&#x3C;string>;
</code></pre></td><td>To get the UserOp Hash</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getAccountContract(): Promise&#x3C;import("./contracts").EtherspotWallet>;
</code></pre></td><td>To get the account contract</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">totalGasEstimated(userOp: UserOperationStruct): Promise&#x3C;BigNumber>;
</code></pre></td><td>To estimate the gas for the transactions</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getCrossChainQuotes(dto: GetExchangeCrossChainQuoteDto): Promise&#x3C;BridgingQuotes>;
</code></pre></td><td>To get the crosschain quotes</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getAdvanceRoutesLiFi(dto: GetAdvanceRoutesLiFiDto): Promise&#x3C;AdvanceRoutesLiFi>
</code></pre></td><td>To get the routes for the LiFi</td></tr><tr><td></td><td></td></tr></tbody></table>


# Aptos SDK Functions

<table><thead><tr><th>Methods</th><th>Description</th></tr></thead><tbody><tr><td><pre class="language-typescript"><code class="lang-typescript">addAccountFeePayers(walletAddress: string, feePayers: string[]): Promise&#x3C;TransactionResponse>;
</code></pre></td><td>To add fee payers to the account</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">removeAccountFeePayers(walletAddress: string, feePayers: string[]): Promise&#x3C;TransactionResponse>;
</code></pre></td><td>To remove fee payers from the account</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getWalletBalance(wallet?: string): Promise&#x3C;TokenBalance[]>;
</code></pre></td><td>To get the token balance of the wallet</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">getSmartWalletDetails(wallet?: string): Promise&#x3C;SmartWalletDetails>;
</code></pre></td><td>To get the wallet details</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">computeAccountAddress(): Promise&#x3C;string>;    
</code></pre></td><td>To compute smart wallet address</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">getAccountAddress(controller?: string): Promise&#x3C;string>;
</code></pre></td><td>To get smart wallet address </td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">createAccount(seed: string, guardians: string[], feePayers: string[]): Promise&#x3C;TransactionResponse>;
</code></pre></td><td>To create smart wallet</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">createAccountSponsored(seed: string, guardians: string[], feePayers: string[]): Promise&#x3C;TransactionResponse>;
</code></pre></td><td>To create a sponsored smart wallet</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">changeControllerAccount(walletAddress: string, newController: string): Promise&#x3C;TransactionResponse>;
</code></pre></td><td>To change the controller of the account</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">recoverAccount(walletAddress: string, newController: string): Promise&#x3C;TransactionResponse>;
</code></pre></td><td>To recover the account. (Guardians can recover account in case when the controller key is lost)</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">addAccountGuardians(walletAddress: string, guardians: string[]): Promise&#x3C;TransactionResponse>;
</code></pre></td><td>To add guardians to the smart wallet</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">removeAccountGuardians(walletAddress: string, guardians: string[]): Promise&#x3C;TransactionResponse>;
</code></pre></td><td>To remove guardians from the smart wallet.</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">depositToAccount(walletAddress: string, coinType: string, amount: number): Promise&#x3C;TransactionResponse>;
</code></pre></td><td>To deposit any coin to smart wallet (Doesn't need to register coins before sending when using this method)</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">withdrawFromAccount(walletAddress: string, coinType: string, amount: number): Promise&#x3C;TransactionResponse>;
</code></pre></td><td>To withdraw coins smart wallet. (Only controller can call this method)</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">transferFromAccount(walletAddress: string, coinType: string, amount: number): Promise&#x3C;TransactionResponse>;
</code></pre></td><td>To transfer coins to other addresses</td></tr><tr><td><pre class="language-typescript"><code class="lang-typescript">executeAptosFunction(wallAddress: string, coinTypes: string[], payload: any[]): Promise&#x3C;TransactionResponse>;
</code></pre></td><td>To execute swap, stake, crosschain swap</td></tr></tbody></table>


# Data Service

Along with using the Mirai SDK, developers can make use of the data service to retreive information such as Account Balances.

For making these api-calls, you’ll need to get a data service api key.

\
Without passing one in, there is a default key which is very heavily rate limited.

<table><thead><tr><th>Methods</th><th>Description</th></tr></thead><tbody><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getAccountBalances(accountAddress: string, chainId: number, dataApiKey: string): Promise&#x3C;any>
</code></pre></td><td>Returns the Account Balance.</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getTransaction(hash: string, chainId: number, dataApiKey: string): Promise&#x3C;any>;
</code></pre></td><td>Returns details about a transaction.</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getNftsList(tokenAddress: string, chainId: number, dataApiKey: string): Promise&#x3C;any>;
</code></pre></td><td>Returns a list of NFTs that the account owns.</td></tr></tbody></table>

```typescript
 * @param dataApiKey- Contact kanalabs to obtain the API key for authentication.
```


# Get Account Balances

Returns the Account Balance.

```typescript
import 'dotenv/config';
import { DataService } from '@kanalabs/mirai';

(async () => {
   
   // Define the accountAddress and chainId
   const accountAddress = '0xD783e00389a7d25E5e7c00f4Ea1F90800636d423';
   const chainId = 80001;
   const dataApiKey = process.env.DATASERVICE_API_KEY || '' as string; 
   
   // initializating DataService...
   const dataService = new DataService();
   
   // Retrieve account balances using the specified accountAddress and chainId with your api key
   const response = await dataService.getAccountBalances(accountAddress, chainId, dataApiKey);
   
   // Log the account balances response
   console.log('response', response);
})()
```


# Get Transactions Details

Returns details about a transaction.

```typescript
import 'dotenv/config';
import { DataService } from '@kanalabs/mirai';

(async () => {

   // Define the transaction hash and chainId
   const hash = '';
   const chainId = 80001;
   const dataApiKey = process.env.DATASERVICE_API_KEY || '' as string;
   
  // initializating DataService...
  const dataService = new DataService();
   
   // Retrieve transaction details using the specified hash and chainId with your api key
   const response = await dataService.getTransaction(hash, chainId, dataApiKey);
   
   // Log the transaction response
   console.log('response', response);
})()
```


# Get NFTs List

Returns a list of NFTs that the account owns.

```typescript
import 'dotenv/config';
import { DataService } from '@kanalabs/mirai';

(async () => {

      // Define the accountAddress and chainId
   const accountAddress = '';
   const chainId = 80001;
   const dataApiKey = process.env.DATASERVICE_API_KEY || '' as string;
   
   // initializating DataService...
   const dataService = new DataService();

   // Retrieve nfts list using the specified accountAddress and chainId with your api key
   const response = await dataService.getNftsList(accountAddress, chainId, dataApiKey);
   
   // Log the nfts list response
   console.log('response', response);
})()
```


# Paymaster

Paymaster is a system designed to allow a company or organization to cover the transaction fees, commonly known as gas fees, for a whitelisted users.

1. **User Transaction Initiation**: A whitelisted user initiates a transaction on the blockchain but does not supply the gas fee.
2. **Paymaster Intervention**: The Paymaster account detects this transaction. It verifies if the user is on the whitelist and the transaction is valid.
3. **Gas Fee Payment**: If the conditions are met, the Paymaster uses its funds to pay the gas fee required for the transaction.
4. **Transaction Completion**: The transaction is processed on the blockchain, thanks to the Paymaster covering the cost.&#x20;

The main advantage of the Paymaster feature is that it removes the burden of gas fees from individual users, especially beneficial in scenarios where users might not have the means or wish to spend their own cryptocurrency on transaction fees. This system is particularly advantageous for companies looking to onboard new users who are unfamiliar with blockchain technology or for applications aiming to provide a more user-friendly experience. By covering transaction fees, companies can encourage more frequent and frictionless interactions on their platform.

<figure><img src="/files/VuzcHF87yuWRTNylkhAv" alt=""><figcaption><p>How gas fees is sponsored using Paymaster in Mirai Smart Wallet</p></figcaption></figure>

<table><thead><tr><th>Methods</th><th>Description</th></tr></thead><tbody><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">addWhitelist(accountAddress: string, chainId: number): Promise&#x3C;any>
</code></pre></td><td>To add a whitelist using the specified accountAddress and chainId.</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">checkWhitelist(accountAddress: string, sponsorAddress: string, chainId: number)
</code></pre></td><td>To check a whitelist using the specified accountAddress, sponsorAddress and chainId.</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">deposit(amount: string, chainId: number)
</code></pre></td><td>To deposit using the specified amount and chainId.</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">getSponsorBalance(sponsorAddress: string, chainId: number): Promise&#x3C;any>
</code></pre></td><td>To get a sponsor balance using the specified sponsorAddress and chainId.</td></tr><tr><td><p></p><pre class="language-typescript"><code class="lang-typescript">removeWhitelist(accountAddress: string, chainId: number)
</code></pre></td><td>To remove a whitelist using the specified accountAddress, sponsorAddress and chainId.</td></tr></tbody></table>

```typescript
 * @param apiKey - Contact kanalabs to obtain the API key for authentication.
```


# Get Sponsor Balance

Using this API call we can get a sponsor balance.

```typescript
import 'dotenv/config';
import { PaymasterUtils } from '@kanalabs/mirai';

(async () => {
   
   // Define the sponsorAddress and chainId
   const sponsorAddress = '0x7305B1a9bDD8247DeB288BC2d271626159cB8c4c'; // bifrost -> 0x8ffdf51ebf23761d762f028a6e1cb88db25a85bf
   const chainId = 80001;
   const apiKey = process.env.PAYMASTER_API_KEY || '';

   // initializating Paymaster service using the apiKey...
   const paymasterService = new PaymasterUtils(apiKey);
   
   // get a sponsor balance using the specified sponsorAddress and chainId
   const response = await paymasterService.getSponsorBalance(sponsorAddress, chainId);

   // Log the get sponsor balance response
   console.log('response', response);
})()
```


# Deposit

Using this API call we can deposit funds to a paymaster address.

```typescript
import 'dotenv/config';
import { Paymaster } from '@kanalabs/mirai';

(async () => {
   
   // Define the amount, chainId and apiKey
   const amount = '0.0001';
   const chainId = 80001;
   const apiKey = process.env.PAYMASTER_API_KEY || ''

  // initializating Paymaster service using the apiKey...
   const paymasterService = new Paymaster(apiKey);
   
   // Deposit using the specified amount and chainId
   const response = await paymasterService.deposit(amount, chainId);

   // Log the deposit response
   console.log('response', response);
})()
```


# Check Whitelist

Using this API call we can check if an accountAddress is whitelisted for a specific paymaster address.

```typescript
import 'dotenv/config';
import { Paymaster } from '@kanalabs/mirai';

(async () => {
   
   // Define the accountAddress, sponsorAddress, chainId and apiKey
   const accountAddress = '0x2DA84874572d7F0b80c8375BE5dE438Ff2247805';
   const sponsorAddress = '0x7305B1a9bDD8247DeB288BC2d271626159cB8c4c';
   const chainId = 80001;
   const apiKey = process.env.PAYMASTER_API_KEY || '';

   // initializating Paymaster service using the apiKey...
   const paymasterService = new Paymaster(apiKey);

  // Check a whitelist paymaster using the specified accountAddress, sponsorAddress and chainId
   const response = await paymasterService.checkWhitelist(accountAddress, sponsorAddress, chainId);

   // Log the check whitelist paymaster response
   console.log('response', response);
})()
```


# Remove From Whitelist

Using this API call we can remove the address from the whitelisting.

```typescript
import 'dotenv/config';
import { Paymaster } from '@kanalabs/mirai';

(async () => {
   
   // Define the accountAddress, chainId and apiKey
   const accountAddress = '0xf141413684395e0174f14ab8fe2414106f79f2f9';
   const chainId = 80001;
   const apiKey = process.env.PAYMASTER_API_KEY || ''

   // initializating Paymaster service using the apiKey...
   const paymasterService = new Paymaster(apiKey);
   
   // remove a whitelist using the specified accountAddress and chainId
   const response = await paymasterService.removeWhitelist(accountAddress, chainId);

   // Log the remove whitelist response
   console.log('response', response);
})()
```


# Add To Whitelist

Using this API call we can whitelisting the address.

```typescript
import 'dotenv/config';
import { Paymaster } from '@kanalabs/mirai';

(async () => {
   
   // Define the accountAddress, chainId and apiKey
   const accountAddress = '0x87c9B02A10eC2CB4dcB3b2e573e26169CF3cd9Bf';
   const chainId = 80001;
   const apiKey = process.env.PAYMASTER_API_KEY || '';

   // initializating Paymaster service using the apiKey...
   const paymasterService = new Paymaster(apiKey);
   
   // Add a whitelist paymaster using the specified accountAddress and chainId
   const response = await paymasterService.addWhitelist(accountAddress, chainId);

   // Log the add whitelist paymaster response
   console.log('response', response);
})()
```


# Sponsor Transactions

Using this API call we sponsor a transactions.

To sponsor a transaction, you need to whitelist the address beforehand.

```typescript
import { utils } from 'ethers';
import 'dotenv/config';
import { NetworkNames, initializeSdkGateway } from '@kanalabs/mirai';
import { sleep } from '@etherspot/prime-sdk/dist/sdk/common';

const receiverAddress = '0x97a57d9CE2889E2E8DFb6019f8Eb51F5d119Bde3'; // Receiver address
const value = '0.0001';

(async () => {

    // initializating sdk...
    const sdk = await initializeSdkGateway(
        { privateKey: process.env.PRIVATE_KEY as string },
        {
            networks: [NetworkNames.Mumbai],
            bundlerApiKey: process.env.BUNDLER_API_KEY
        },
    );
    
    // Retrieve the chainId corresponding to the network name
    const chainId = networkNameToChainId(NetworkNames.Mumbai)

    // set mumbai as default current instance
    const networkInstance = sdk.setCurrentInstance(NetworkNames.Mumbai);

    // clear the transaction batch
    await networkInstance.clearUserOpsFromBatch();

    // add transactions to the batch
    await networkInstance.addUserOpsToBatch({ to: receiverAddress, value: utils.parseEther(value) });
    
    // get balance of the account address
    const balance = await networkInstance.getNativeBalance();
    console.log('balances: ', balance);

    // Estimate transaction details using paymaster for sponsorship mode.
    const op = await networkInstance.estimate({
        paymasterDetails: {
            url: `https://evm-paymaster.kanalabs.io?apiKey=${process.env.PAYMASTER_API_KEY}&chainId=${chainId}`,
            context: { mode: 'sponsor' },
        },
    });
    console.log("op: ", op);

    // sign the UserOp and sending to the bundler...
    const uoHash = await networkInstance.send(op);

    // log the uoHash
    console.log(`UserOpHash: ${uoHash}`)

    let userOpsReceipt = null;
    const timeout = Date.now() + 60000 // 1 minute timeout
    while (userOpsReceipt == null && Date.now() < timeout) {
        await sleep(2)
        userOpsReceipt = await networkInstance.getUserOpReceipt(uoHash);
    }
    console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt);
})()
```

```typescript
 * PAYMASTER_API_KEY - Contact kanalabs to obtain the API key for authentication.
```


# Implementation Guide

Step by step guide for implementing our SDK

### Install Mirai Package

`npm i @kanalabs/mirai`

`or`

`yarn add @kanalabs/mirai`

## Social Login Using Web3Auth

### Installation&#x20;

First, let us create a wallet using Web3Auth for Social Login. For this, we have to sign up at <https://dashboard.web3auth.io/> to create an account to create a web3Auth Client ID which is available after you are signed into the dashboard and create a project under 'Plug and Play'. Copy the Client ID shown and keep it ready before continuing.

> You can view a detailed steps on how to get started with Web3Auth : <https://web3auth.io/docs/integration-builder?lang=REACT&chain=ETH&evmFramework=ETHERS&customAuth=NONE&mfa=DEFAULT&whitelabel=NO&useModal=NO&web3AuthNetwork=TESTNET&rnMode=EXPO&stepIndex=0&stepIndex=10#step-10>

### Install Web3Auth Packages

```typescript
npm: npm install --save @web3auth/no-modal @web3auth/openlogin-adapter

yarn: yarn add @web3auth/no-modal @web3auth/openlogin-adapter
```

```typescript
import { Web3AuthNoModal } from "@web3auth/no-modal";
import {
  CHAIN_NAMESPACES,
  WALLET_ADAPTERS,
  ADAPTER_EVENTS,
  CONNECTED_EVENT_DATA,
} from "@web3auth/base";
import { OpenloginAdapter } from "@web3auth/openlogin-adapter";

```

## Whitelisting

The Client ID is unique for each project, if we use different Client IDs the same account login will give us different private keys. So if anyone uses our client ID, it will give a private key similar to the one we give. So it is necessary to add website links before allowing it to share our web3auth login.

## Initialise web3auth

```typescript
  const web3auth = new Web3AuthNoModal({
          clientId,
          web3AuthNetwork: "testnet", // mainnet, aqua,  cyan or testnet
          chainConfig: {
            chainNamespace: CHAIN_NAMESPACES.EIP155,
            chainId: "0x13881",
            rpcTarget: "https://rpc.ankr.com/polygon_mumbai", // This is the public RPC we have added, please pass on your own endpoint while creating an app
          },
        });
```

Defining the Web3Auth openLogin Adapter which is responsible for sign-in options. You can see the list of all sign-in options provided :  <https://web3auth.io/docs/auth-provider-setup/social-providers/>

<pre class="language-typescript"><code class="lang-typescript"><strong>        const openloginAdapter = new OpenloginAdapter({
</strong>          adapterSettings: {
            network: "testnet",
            clientId: clientId,
          },
          loginSettings: {
            mfaLevel: "none",
          },
        });
        web3auth.configureAdapter(openloginAdapter);
</code></pre>

Listen to events emitted by the Web3Auth Adapter

<pre class="language-typescript"><code class="lang-typescript"><strong>// Emits an event when connection completed
</strong><strong>web3auth.on(ADAPTER_EVENTS.CONNECTED, () => {
</strong>  if (!web3AuthInstance?.provider) {
    return
  }
})

// Emits an event when an error occurs during connection
web3auth.on(ADAPTER_EVENTS.ERRORED, (error) => {
  console.log(error);
})
</code></pre>

Initialize the web3Auth instance after setting up the Adapter Configuration

```typescript
await web3auth.init();
```

## Login with web3auth

Now, log in to web3Auth with valid credentials from any of the supported social platforms that web3auth supports..

For this example, Let us take Google as the social platform that we are looking to login

```typescript
try {
  if (!web3auth) {
      console.log("web3auth not initialized yet");
      return;
    }
  const web3authProvider = await web3auth.connectTo(
      WALLET_ADAPTERS.OPENLOGIN,
      {
        mfaLevel: "default", 
        loginProvider: "google",
      }
    );
    const privateKey = (await web3auth.provider?.request({
      method: "private_key",
    })) as string;
}
catch (e) {
  console.log(`Failed to login! Reason: ${e instanceof Error && e?.message ? e.message : 'unknown'}.`)
  return
}

if (!web3authProvider) {
  console.log(`Failed to get the provider connected`)
  return
}
```

After completing the login process, you can obtain the private key. Before initializing the Mirai SDK with it, it is necessary to format the private key.

#### Format privateKey

```typescript
  function formatPrivateKey(privateKey: any): string {
    if (privateKey.startsWith("0x")) {
      return privateKey;
    } else {
      return "0x" + privateKey;
    }
  }
```

## Initialize Mirai SDK

To initialize the wallet SDK - specify the required networks and it will be initialize SDK for all networks.

```typescript
    const sdk = await initializeSdkGateway(
      { privateKey: process.env.PRIVATE_KEY as string },
      {
        networks: [NetworkNames.Mumbai],
        bundlerApiKey: process.env.BUNDLER_API_KEY
      },
    );
```

```typescript
 * @param bundlerApiKey - Contact kanalabs to obtain the bundlerApiKey for authentication.
```

### Set Current SDK Instance

After initializing the sdk with the array required chains, we can set the default instance of SDK for any initialized network. with this function

#### Example

```typescript
const networkInstance = sdk.setCurrentInstance(NetworkNames.Mumbai);
```

To get the smart wallet address

```typescript
const address = await networkInstance.getCounterFactualAddress();    
```

## Destroy Instances

To destroy all SDK instances for the session

```typescript
await sdk.destroy();
```


# Examples

Practical examples which show how to use our Mirai SDK for various use cases.

{% content-ref url="/pages/2W8O99jSMMKVbC4EKKqa" %}
[Initialize SDK](/smart-wallet-sdk/mirai-sdk-the-evm-smart-wallet-and-paymaster/examples/initialize-sdk)
{% endcontent-ref %}

{% content-ref url="/pages/n5c3BgTxeZ0IZXZaY2GW" %}
[Transfer Native Tokens](/smart-wallet-sdk/mirai-sdk-the-evm-smart-wallet-and-paymaster/examples/transfer-native-tokens)
{% endcontent-ref %}

{% content-ref url="/pages/wRBAVzgEBHqRW3dnXXxF" %}
[Transfer ERC20 Tokens](/smart-wallet-sdk/mirai-sdk-the-evm-smart-wallet-and-paymaster/examples/transfer-erc20-tokens)
{% endcontent-ref %}

{% content-ref url="/pages/CsOIN5vwajaard0g2EgA" %}
[Transfer ERC721 Tokens](/smart-wallet-sdk/mirai-sdk-the-evm-smart-wallet-and-paymaster/examples/transfer-erc721-tokens)
{% endcontent-ref %}

{% content-ref url="/pages/fPmxLjcqkQDdeZtuCetP" %}
[Transfer ERC1155 Tokens](/smart-wallet-sdk/mirai-sdk-the-evm-smart-wallet-and-paymaster/examples/transfer-erc1155-tokens)
{% endcontent-ref %}

{% content-ref url="/pages/naJFFf1tpbyWJzAIhCPK" %}
[Create Aptos Sponsored](/smart-wallet-sdk/mirai-sdk-the-evm-smart-wallet-and-paymaster/examples/create-aptos-sponsored)
{% endcontent-ref %}

{% content-ref url="/pages/5nFCBCAIcepErtyW4eLj" %}
[Broken mention](broken://pages/5nFCBCAIcepErtyW4eLj)
{% endcontent-ref %}

{% content-ref url="/pages/aRSXhcgN0KcVDE8ylEeW" %}
[Get Transactions Details](/smart-wallet-sdk/mirai-sdk-the-evm-smart-wallet-and-paymaster/data-service/get-transactions-details)
{% endcontent-ref %}

{% content-ref url="/pages/ACphr894QYSKYPZlZrXQ" %}
[Broken mention](broken://pages/ACphr894QYSKYPZlZrXQ)
{% endcontent-ref %}


# React Implementation

The sample implementation code using web3auth and Mirai SDK.

<https://github.com/kanalabs/mirai-sdk-example>


# Initialize SDK

```typescript
import 'dotenv/config';
import { NetworkNames, initializeSdkGateway } from '@kanalabs/mirai';

(async () => {

    // initializating sdk...
    const sdk = await initializeSdkGateway(
      { privateKey: process.env.PRIVATE_KEY as string },
      {
        networks: [NetworkNames.Mumbai],
        bundlerApiKey: process.env.BUNDLER_API_KEY
      },
    );

    // set mumbai as default current instance
    const networkInstance = sdk.setCurrentInstance(NetworkNames.Mumbai);
    console.log("networkInstance: ", networkInstance);

    // get address of KanaWallet
    const address = await networkInstance.getCounterFactualAddress();

    // log the KanaWallet address
    console.log('\x1b[35m%s\x1b[0m', `KanaWallet address : ${address}`);
})()
```


# Transfer Native Tokens

```typescript
import { utils } from 'ethers';
import 'dotenv/config';
import { NetworkNames, initializeSdkGateway } from '@kanalabs/mirai';
import { sleep } from '@etherspot/prime-sdk/dist/sdk/common';

const receiverAddress = '0x97a57d9CE2889E2E8DFb6019f8Eb51F5d119Bde3'; // Receiver address
const value = '0.01';

(async () => {

    // initializating sdk...
    const sdk = await initializeSdkGateway(
        { privateKey: process.env.PRIVATE_KEY as string },
        {
          networks: [NetworkNames.Mumbai],
          bundlerApiKey: process.env.BUNDLER_API_KEY
        },
    );

    // set mumbai as default current instance
    const networkInstance = sdk.setCurrentInstance(NetworkNames.Mumbai);

    // clear the transaction batch
    await networkInstance.clearUserOpsFromBatch();

    // add transactions to the batch
    await networkInstance.addUserOpsToBatch({ to: receiverAddress, value: utils.parseEther(value) });

    // estimate transactions added to the batch and get the fee data for the UserOp
    const op = await networkInstance.estimate();
    console.log("op: ", op);

    // sign the UserOp and sending to the bundler...
    const uoHash = await networkInstance.send(op);

    // log the uoHash
    console.log(`UserOpHash: ${uoHash}`)

    let userOpsReceipt = null;
    const timeout = Date.now() + 60000 // 1 minute timeout
    while (userOpsReceipt == null && Date.now() < timeout) {
        await sleep(2)
        userOpsReceipt = await networkInstance.getUserOpReceipt(uoHash);
    }
    console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt);
})()
```


# Transfer ERC20 Tokens

```typescript
import { BigNumber } from 'ethers';
import 'dotenv/config';
import { NetworkNames, initializeSdkGateway } from '@kanalabs/mirai';

const tokenAddress = '0xc2132D05D31c914a87C6611C10748AEb04B58e8F'; // Sender address
const receiverAddress = '0x97a57d9CE2889E2E8DFb6019f8Eb51F5d119Bde3'; // Receiver address

(async () => {

    // initializating sdk...
    const sdk = await initializeSdkGateway(
        { privateKey: process.env.PRIVATE_KEY as string },
        {
          networks: [NetworkNames.Mumbai],
          bundlerApiKey: process.env.BUNDLER_API_KEY
        },
      );

    // set mumbai as default current instance
    const networkInstance = sdk.setCurrentInstance(NetworkNames.Mumbai);

    //initialize erc20 sdk instance
    const erc20 = sdk.erc20(tokenAddress, NetworkNames.Mumbai);

    const native = await sdk.getNativeBalance();
    console.log('native: ', native);

    // clear any previous transactions in batch
    await networkInstance.clearUserOpsFromBatch();

    // add erc20 transfer function to the batch
    await erc20.transfer(receiverAddress, 1000000 as unknown as BigNumber);

    // estimate transactions added to the batch and get the fee data for the UserOp
    const op = await networkInstance.estimate();
    console.log('op: ', op);

    //sign the UserOp and sending to the bundler...
    const uoHash = await networkInstance.send(op);

    // log the uoHash
    console.log(`UserOpHash: ${uoHash}`);
})()
```


# Transfer ERC721 Tokens

```typescript
import 'dotenv/config';
import { NetworkNames, initializeSdkGateway } from '@kanalabs/mirai';

const collectionAddress = '0xc2132D05D31c914a87C6611C10748AEb04B58e8F'; // Sender address
const receiverAddress = '0x97a57d9CE2889E2E8DFb6019f8Eb51F5d119Bde3'; // Receiver address

(async () => {

    // initializating sdk...
    const sdk = await initializeSdkGateway(
        { privateKey: process.env.PRIVATE_KEY as string },
        {
          networks: [NetworkNames.Mumbai],
          bundlerApiKey: process.env.BUNDLER_API_KEY
        },
      );

    // set mumbai as default current instance
    const networkInstance = sdk.setCurrentInstance(NetworkNames.Mumbai);

    // get address of KanaWallet
    const sender = await networkInstance.getCounterFactualAddress();

    //initialize erc721 sdk instance
    const erc721 = sdk.erc721(collectionAddress);

    // clear any previous transactions in batch
    await networkInstance.clearUserOpsFromBatch();

    // add erc721 transferFrom function to the batch
    await erc721.transferFrom(sender, receiverAddress, 10);

    // estimate transactions added to the batch and get the fee data for the UserOp
    const op = await networkInstance.estimate();

    // sign the UserOp and sending to the bundler...
    const uoHash = await networkInstance.send(op);

    // log the uoHash
    console.log(`UserOpHash: ${uoHash}`);
})()
```


# Transfer ERC1155 Tokens

```typescript
import 'dotenv/config';
import { NetworkNames, initializeSdkGateway } from '@kanalabs/mirai';

const collectionAddress = '0xc2132D05D31c914a87C6611C10748AEb04B58e8F'; // Sender address
const receiverAddress = '0x97a57d9CE2889E2E8DFb6019f8Eb51F5d119Bde3'; // Receiver address

(async () => {

    // initializating sdk...
    const sdk = await initializeSdkGateway(
        { privateKey: process.env.PRIVATE_KEY as string },
        {
          networks: [NetworkNames.Mumbai],
          bundlerApiKey: process.env.BUNDLER_API_KEY
        },
      );
      
    // set mumbai as default current instance
    const networkInstance = sdk.setCurrentInstance(NetworkNames.Mumbai);

    // get address of KanaWallet
    const sender = await networkInstance.getCounterFactualAddress();

    //initialize erc721 sdk instance
    const erc1155 = sdk.erc1155(collectionAddress);

    // clear any previous transactions in batch
    await networkInstance.clearUserOpsFromBatch();

    // add erc721 transferFrom function to the batch
    await erc1155.safeTransferFrom(sender, receiverAddress, 1, 10, '0x');

    // estimate transactions added to the batch and get the fee data for the UserOp
    const op = await networkInstance.estimate();

    // sign the UserOp and sending to the bundler...
    const uoHash = await networkInstance.send(op);

    // log the uoHash
    console.log(`UserOpHash: ${uoHash}`);
})()
```




---

[Next Page](/llms-full.txt/1)

