UNPKG

@meteora-ag/dlmm

Version:

<p align="center"> <img align="center" src="https://app.meteora.ag/icons/logo.svg" width="180" height="180" /> </p> <br>

23,339 lines 684 kB
// src/dlmm/index.ts
import { BN as BN24 } from "@coral-xyz/anchor";
import {
  AccountLayout,
  NATIVE_MINT as NATIVE_MINT2,
  TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID4,
  createAssociatedTokenAccountIdempotentInstruction as createAssociatedTokenAccountIdempotentInstruction2,
  createTransferCheckedInstruction as createTransferCheckedInstruction2,
  getAssociatedTokenAddressSync as getAssociatedTokenAddressSync2,
  unpackAccount,
  unpackMint as unpackMint2
} from "@solana/spl-token";
import {
  ComputeBudgetProgram as ComputeBudgetProgram3,
  LAMPORTS_PER_SOL as LAMPORTS_PER_SOL2,
  PublicKey as PublicKey10,
  SYSVAR_CLOCK_PUBKEY as SYSVAR_CLOCK_PUBKEY2,
  SYSVAR_RENT_PUBKEY as SYSVAR_RENT_PUBKEY2,
  SystemProgram as SystemProgram2,
  Transaction
} from "@solana/web3.js";
import Decimal11 from "decimal.js";

// src/dlmm/constants/index.ts
import { LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js";
import { BN } from "@coral-xyz/anchor";

// src/dlmm/idl/idl.json
var idl_default = {
  address: "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo",
  metadata: {
    name: "lb_clmm",
    version: "0.12.0",
    spec: "0.1.0",
    description: "Created with Anchor"
  },
  instructions: [
    {
      name: "add_liquidity",
      discriminator: [181, 157, 89, 67, 143, 182, 52, 72],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: [
            "position",
            "bin_array_bitmap_extension",
            "bin_array_lower",
            "bin_array_upper"
          ]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_x_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "token_y_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "liquidity_parameter",
          type: {
            defined: {
              name: "LiquidityParameter"
            }
          }
        }
      ]
    },
    {
      name: "add_liquidity2",
      discriminator: [228, 162, 78, 28, 70, 219, 116, 115],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: ["position", "bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_x_program"
        },
        {
          name: "token_y_program"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "liquidity_parameter",
          type: {
            defined: {
              name: "LiquidityParameter"
            }
          }
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "add_liquidity_by_strategy",
      discriminator: [7, 3, 150, 127, 148, 40, 61, 200],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: [
            "position",
            "bin_array_bitmap_extension",
            "bin_array_lower",
            "bin_array_upper"
          ]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_x_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "token_y_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "liquidity_parameter",
          type: {
            defined: {
              name: "LiquidityParameterByStrategy"
            }
          }
        }
      ]
    },
    {
      name: "add_liquidity_by_strategy2",
      discriminator: [3, 221, 149, 218, 111, 141, 118, 213],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: ["position", "bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_x_program"
        },
        {
          name: "token_y_program"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "liquidity_parameter",
          type: {
            defined: {
              name: "LiquidityParameterByStrategy"
            }
          }
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "add_liquidity_by_strategy_one_side",
      discriminator: [41, 5, 238, 175, 100, 225, 6, 205],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: [
            "position",
            "bin_array_bitmap_extension",
            "bin_array_lower",
            "bin_array_upper"
          ]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token",
          writable: true
        },
        {
          name: "reserve",
          writable: true
        },
        {
          name: "token_mint"
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "liquidity_parameter",
          type: {
            defined: {
              name: "LiquidityParameterByStrategyOneSide"
            }
          }
        }
      ]
    },
    {
      name: "add_liquidity_by_weight",
      discriminator: [28, 140, 238, 99, 231, 162, 21, 149],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: [
            "position",
            "bin_array_bitmap_extension",
            "bin_array_lower",
            "bin_array_upper"
          ]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_x_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "token_y_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "liquidity_parameter",
          type: {
            defined: {
              name: "LiquidityParameterByWeight"
            }
          }
        }
      ]
    },
    {
      name: "add_liquidity_by_weight2",
      discriminator: [209, 59, 63, 91, 111, 200, 153, 228],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: ["position", "bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_x_program"
        },
        {
          name: "token_y_program"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "liquidity_parameter",
          type: {
            defined: {
              name: "LiquidityParameterByWeight"
            }
          }
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "add_liquidity_one_side",
      discriminator: [94, 155, 103, 151, 70, 95, 220, 165],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: [
            "position",
            "bin_array_bitmap_extension",
            "bin_array_lower",
            "bin_array_upper"
          ]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token",
          writable: true
        },
        {
          name: "reserve",
          writable: true
        },
        {
          name: "token_mint"
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "liquidity_parameter",
          type: {
            defined: {
              name: "LiquidityOneSideParameter"
            }
          }
        }
      ]
    },
    {
      name: "add_liquidity_one_side_precise",
      discriminator: [161, 194, 103, 84, 171, 71, 250, 154],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: [
            "position",
            "bin_array_bitmap_extension",
            "bin_array_lower",
            "bin_array_upper"
          ]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token",
          writable: true
        },
        {
          name: "reserve",
          writable: true
        },
        {
          name: "token_mint"
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "parameter",
          type: {
            defined: {
              name: "AddLiquiditySingleSidePreciseParameter"
            }
          }
        }
      ]
    },
    {
      name: "add_liquidity_one_side_precise2",
      discriminator: [33, 51, 163, 201, 117, 98, 125, 231],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: ["position", "bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token",
          writable: true
        },
        {
          name: "reserve",
          writable: true
        },
        {
          name: "token_mint"
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_program"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "liquidity_parameter",
          type: {
            defined: {
              name: "AddLiquiditySingleSidePreciseParameter2"
            }
          }
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "cancel_limit_order",
      discriminator: [132, 156, 132, 31, 67, 40, 232, 97],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["bin_array_bitmap_extension", "limit_order"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "limit_order",
          writable: true
        },
        {
          name: "owner_token_x",
          docs: [
            "When dont set it tokenAccount to prevent unnecessary create token account (rent fee) when user only withdraw token y"
          ],
          writable: true
        },
        {
          name: "owner_token_y",
          writable: true
        },
        {
          name: "owner",
          signer: true
        },
        {
          name: "token_x_program"
        },
        {
          name: "token_y_program"
        },
        {
          name: "memo_program",
          address: "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "bins",
          type: {
            vec: "i32"
          }
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "claim_fee",
      discriminator: [169, 32, 79, 137, 136, 232, 70, 137],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["position", "bin_array_lower", "bin_array_upper"]
        },
        {
          name: "position",
          writable: true
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: []
    },
    {
      name: "claim_fee2",
      discriminator: [112, 191, 101, 171, 28, 144, 127, 187],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["position"]
        },
        {
          name: "position",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_program_x"
        },
        {
          name: "token_program_y"
        },
        {
          name: "memo_program",
          address: "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "min_bin_id",
          type: "i32"
        },
        {
          name: "max_bin_id",
          type: "i32"
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "claim_reward",
      discriminator: [149, 95, 181, 242, 94, 90, 158, 162],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["position", "bin_array_lower", "bin_array_upper"]
        },
        {
          name: "position",
          writable: true
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "reward_vault",
          writable: true
        },
        {
          name: "reward_mint"
        },
        {
          name: "user_token_account",
          writable: true
        },
        {
          name: "token_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "reward_index",
          type: "u64"
        }
      ]
    },
    {
      name: "claim_reward2",
      discriminator: [190, 3, 127, 119, 178, 87, 157, 183],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["position"]
        },
        {
          name: "position",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "reward_vault",
          writable: true
        },
        {
          name: "reward_mint"
        },
        {
          name: "user_token_account",
          writable: true
        },
        {
          name: "token_program"
        },
        {
          name: "memo_program",
          address: "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "reward_index",
          type: "u64"
        },
        {
          name: "min_bin_id",
          type: "i32"
        },
        {
          name: "max_bin_id",
          type: "i32"
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "close_bin_array",
      discriminator: [68, 174, 88, 80, 181, 204, 19, 224],
      accounts: [
        {
          name: "lb_pair",
          relations: ["bin_array"]
        },
        {
          name: "bin_array",
          writable: true
        },
        {
          name: "rent_receiver",
          writable: true,
          signer: true
        },
        {
          name: "signer",
          signer: true
        }
      ],
      args: []
    },
    {
      name: "close_claim_fee_operator_account",
      discriminator: [184, 213, 88, 31, 179, 101, 130, 36],
      accounts: [
        {
          name: "claim_fee_operator",
          writable: true
        },
        {
          name: "rent_receiver",
          writable: true
        },
        {
          name: "signer",
          signer: true
        }
      ],
      args: []
    },
    {
      name: "close_limit_order_if_empty",
      discriminator: [57, 124, 36, 155, 126, 249, 93, 171],
      accounts: [
        {
          name: "limit_order",
          writable: true
        },
        {
          name: "owner",
          signer: true
        },
        {
          name: "rent_receiver",
          writable: true
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: []
    },
    {
      name: "close_operator_account",
      discriminator: [171, 9, 213, 74, 120, 23, 3, 29],
      accounts: [
        {
          name: "operator",
          writable: true
        },
        {
          name: "signer",
          signer: true
        },
        {
          name: "rent_receiver",
          writable: true
        }
      ],
      args: []
    },
    {
      name: "close_position",
      discriminator: [123, 134, 81, 0, 49, 68, 98, 98],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "rent_receiver",
          writable: true
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: []
    },
    {
      name: "close_position2",
      discriminator: [174, 90, 35, 115, 186, 40, 147, 226],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "rent_receiver",
          writable: true
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: []
    },
    {
      name: "close_position_if_empty",
      discriminator: [59, 124, 212, 118, 91, 152, 110, 157],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "rent_receiver",
          writable: true
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: []
    },
    {
      name: "close_preset_parameter",
      discriminator: [4, 148, 145, 100, 134, 26, 181, 61],
      accounts: [
        {
          name: "preset_parameter",
          writable: true
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          signer: true
        },
        {
          name: "rent_receiver",
          writable: true
        }
      ],
      args: []
    },
    {
      name: "close_preset_parameter2",
      discriminator: [39, 25, 95, 107, 116, 17, 115, 28],
      accounts: [
        {
          name: "preset_parameter",
          writable: true
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          signer: true
        },
        {
          name: "rent_receiver",
          writable: true
        }
      ],
      args: []
    },
    {
      name: "close_token_badge",
      discriminator: [108, 146, 86, 110, 179, 254, 10, 104],
      accounts: [
        {
          name: "token_badge",
          writable: true
        },
        {
          name: "rent_receiver",
          writable: true
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          signer: true
        }
      ],
      args: []
    },
    {
      name: "create_operator_account",
      discriminator: [221, 64, 246, 149, 240, 153, 229, 163],
      accounts: [
        {
          name: "operator",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [111, 112, 101, 114, 97, 116, 111, 114]
              },
              {
                kind: "account",
                path: "whitelisted_signer"
              }
            ]
          }
        },
        {
          name: "whitelisted_signer"
        },
        {
          name: "signer",
          signer: true
        },
        {
          name: "payer",
          writable: true,
          signer: true
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        }
      ],
      args: [
        {
          name: "permission",
          type: "u128"
        }
      ]
    },
    {
      name: "decrease_position_length",
      discriminator: [194, 219, 136, 32, 25, 96, 105, 37],
      accounts: [
        {
          name: "rent_receiver",
          writable: true
        },
        {
          name: "position",
          writable: true
        },
        {
          name: "owner",
          signer: true,
          relations: ["position"]
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "length_to_remove",
          type: "u16"
        },
        {
          name: "side",
          type: "u8"
        }
      ]
    },
    {
      name: "for_idl_type_generation_do_not_call",
      discriminator: [180, 105, 69, 80, 95, 50, 73, 108],
      accounts: [
        {
          name: "dummy_zc_account"
        }
      ],
      args: [
        {
          name: "_ix",
          type: {
            defined: {
              name: "DummyIx"
            }
          }
        }
      ]
    },
    {
      name: "fund_reward",
      discriminator: [188, 50, 249, 165, 93, 151, 38, 63],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["bin_array"]
        },
        {
          name: "reward_vault",
          writable: true
        },
        {
          name: "reward_mint"
        },
        {
          name: "funder_token_account",
          writable: true
        },
        {
          name: "funder",
          signer: true
        },
        {
          name: "bin_array",
          writable: true
        },
        {
          name: "token_program"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "reward_index",
          type: "u64"
        },
        {
          name: "amount",
          type: "u64"
        },
        {
          name: "carry_forward",
          type: "bool"
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "go_to_a_bin",
      discriminator: [146, 72, 174, 224, 40, 253, 84, 174],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: [
            "bin_array_bitmap_extension",
            "from_bin_array",
            "to_bin_array"
          ]
        },
        {
          name: "bin_array_bitmap_extension",
          optional: true
        },
        {
          name: "from_bin_array",
          optional: true
        },
        {
          name: "to_bin_array",
          optional: true
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "bin_id",
          type: "i32"
        }
      ]
    },
    {
      name: "increase_oracle_length",
      discriminator: [190, 61, 125, 87, 103, 79, 158, 173],
      accounts: [
        {
          name: "oracle",
          writable: true
        },
        {
          name: "funder",
          writable: true,
          signer: true
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "length_to_add",
          type: "u64"
        }
      ]
    },
    {
      name: "increase_position_length",
      discriminator: [80, 83, 117, 211, 66, 13, 33, 149],
      accounts: [
        {
          name: "funder",
          writable: true,
          signer: true
        },
        {
          name: "lb_pair",
          relations: ["position"]
        },
        {
          name: "position",
          writable: true
        },
        {
          name: "owner",
          signer: true,
          relations: ["position"]
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "length_to_add",
          type: "u16"
        },
        {
          name: "side",
          type: "u8"
        }
      ]
    },
    {
      name: "increase_position_length2",
      discriminator: [255, 210, 204, 71, 115, 137, 225, 113],
      accounts: [
        {
          name: "funder",
          writable: true,
          signer: true
        },
        {
          name: "lb_pair",
          relations: ["position"]
        },
        {
          name: "position",
          writable: true
        },
        {
          name: "owner",
          signer: true,
          relations: ["position"]
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "minimum_upper_bin_id",
          type: "i32"
        }
      ]
    },
    {
      name: "initialize_bin_array",
      discriminator: [35, 86, 19, 185, 78, 212, 75, 211],
      accounts: [
        {
          name: "lb_pair"
        },
        {
          name: "bin_array",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [98, 105, 110, 95, 97, 114, 114, 97, 121]
              },
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "arg",
                path: "index"
              }
            ]
          }
        },
        {
          name: "funder",
          writable: true,
          signer: true
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        }
      ],
      args: [
        {
          name: "index",
          type: "i64"
        }
      ]
    },
    {
      name: "initialize_bin_array_bitmap_extension",
      discriminator: [47, 157, 226, 180, 12, 240, 33, 71],
      accounts: [
        {
          name: "lb_pair"
        },
        {
          name: "bin_array_bitmap_extension",
          docs: [
            "Initialize an account to store if a bin array is initialized."
          ],
          writable: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [98, 105, 116, 109, 97, 112]
              },
              {
                kind: "account",
                path: "lb_pair"
              }
            ]
          }
        },
        {
          name: "funder",
          writable: true,
          signer: true
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "rent"
        }
      ],
      args: []
    },
    {
      name: "initialize_customizable_permissionless_lb_pair",
      discriminator: [46, 39, 41, 135, 111, 183, 200, 64],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [98, 105, 116, 109, 97, 112]
              },
              {
                kind: "account",
                path: "lb_pair"
              }
            ]
          }
        },
        {
          name: "token_mint_x"
        },
        {
          name: "token_mint_y"
        },
        {
          name: "reserve_x",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "account",
                path: "token_mint_x"
              }
            ]
          }
        },
        {
          name: "reserve_y",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "account",
                path: "token_mint_y"
              }
            ]
          }
        },
        {
          name: "oracle",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [111, 114, 97, 99, 108, 101]
              },
              {
                kind: "account",
                path: "lb_pair"
              }
            ]
          }
        },
        {
          name: "user_token_x"
        },
        {
          name: "funder",
          writable: true,
          signer: true
        },
        {
          name: "token_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "user_token_y"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "params",
          type: {
            defined: {
              name: "CustomizableParams"
            }
          }
        }
      ]
    },
    {
      name: "initialize_customizable_permissionless_lb_pair2",
      discriminator: [243, 73, 129, 126, 51, 19, 241, 107],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [98, 105, 116, 109, 97, 112]
              },
              {
                kind: "account",
                path: "lb_pair"
              }
            ]
          }
        },
        {
          name: "token_mint_x"
        },
        {
          name: "token_mint_y"
        },
        {
          name: "reserve_x",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "account",
                path: "token_mint_x"
              }
            ]
          }
        },
        {
          name: "reserve_y",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "account",
                path: "token_mint_y"
              }
            ]
          }
        },
        {
          name: "oracle",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [111, 114, 97, 99, 108, 101]
              },
              {
                kind: "account",
                path: "lb_pair"
              }
            ]
          }
        },
        {
          name: "user_token_x"
        },
        {
          name: "funder",
          writable: true,
          signer: true
        },
        {
          name: "token_badge_x",
          optional: true
        },
        {
          name: "token_badge_y",
          optional: true
        },
        {
          name: "token_program_x"
        },
        {
          name: "token_program_y"
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "user_token_y"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "params",
          type: {
            defined: {
              name: "CustomizableParams"
            }
          }
        }
      ]
    },
    {
      name: "initialize_lb_pair",
      discriminator: [45, 154, 237, 210, 221, 15, 166, 92],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [98, 105, 116, 109, 97, 112]
              },
              {
                kind: "account",
                path: "lb_pair"
              }
            ]
          }
        },
        {
          name: "token_mint_x"
        },
        {
          name: "token_mint_y"
        },
        {
          name: "reserve_x",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "account",
                path: "token_mint_x"
              }
            ]
          }
        },
        {
          name: "reserve_y",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "account",
                path: "token_mint_y"
              }
            ]
          }
        },
        {
          name: "oracle",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [111, 114, 97, 99, 108, 101]
              },
              {
                kind: "account",
                path: "lb_pair"
              }
            ]
          }
        },
        {
          name: "preset_parameter"
        },
        {
          name: "funder",
          writable: true,
          signer: true
        },
        {
          name: "token_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "rent"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "active_id",
          type: "i32"
        },
        {
          name: "bin_step",
          type: "u16"
        }
      ]
    },
    {
      name: "initialize_lb_pair2",
      discriminator: [73, 59, 36, 120, 237, 83, 108, 198],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [98, 105, 116, 109, 97, 112]
              },
              {
                kind: "account",
                path: "lb_pair"
              }
            ]
          }
        },
        {
          name: "token_mint_x"
        },
        {
          name: "token_mint_y"
        },
        {
          name: "reserve_x",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "account",
                path: "token_mint_x"
              }
            ]
          }
        },
        {
          name: "reserve_y",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "account",
                path: "token_mint_y"
              }
            ]
          }
        },
        {
          name: "oracle",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [111, 114, 97, 99, 108, 101]
              },
              {
                kind: "account",
                path: "lb_pair"
              }
            ]
          }
        },
        {
          name: "preset_parameter"
        },
        {
          name: "funder",
          writable: true,
          signer: true
        },
        {
          name: "token_badge_x",
          optional: true
        },
        {
          name: "token_badge_y",
          optional: true
        },
        {
          name: "token_program_x"
        },
        {
          name: "token_program_y"
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "params",
          type: {
            defined: {
              name: "InitializeLbPair2Params"
            }
          }
        }
      ]
    },
    {
      name: "initialize_permission_lb_pair",
      discriminator: [108, 102, 213, 85, 251, 3, 53, 21],
      accounts: [
        {
          name: "base",
          signer: true
        },
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [98, 105, 116, 109, 97, 112]
              },
              {
                kind: "account",
                path: "lb_pair"
              }
            ]
          }
        },
        {
          name: "token_mint_x"
        },
        {
          name: "token_mint_y"
        },
        {
          name: "reserve_x",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "account",
                path: "token_mint_x"
              }
            ]
          }
        },
        {
          name: "reserve_y",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "account",
                path: "token_mint_y"
              }
            ]
          }
        },
        {
          name: "oracle",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [111, 114, 97, 99, 108, 101]
              },
              {
                kind: "account",
                path: "lb_pair"
              }
            ]
          }
        },
        {
          name: "payer",
          writable: true,
          signer: true
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          signer: true
        },
        {
          name: "token_badge_x",
          optional: true
        },
        {
          name: "token_badge_y",
          optional: true
        },
        {
          name: "token_program_x"
        },
        {
          name: "token_program_y"
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "ix_data",
          type: {
            defined: {
              name: "InitPermissionPairIx"
            }
          }
        }
      ]
    },
    {
      name: "initialize_position",
      discriminator: [219, 192, 234, 71, 190, 191, 102, 80],
      accounts: [
        {
          name: "payer",
          writable: true,
          signer: true
        },
        {
          name: "position",
          writable: true,
          signer: true
        },
        {
          name: "lb_pair"
        },
        {
          name: "owner",
          signer: true
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "rent"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "lower_bin_id",
          type: "i32"
        },
        {
          name: "width",
          type: "i32"
        }
      ]
    },
    {
      name: "initialize_position2",
      discriminator: [143, 19, 242, 145, 213, 15, 104, 115],
      accounts: [
        {
          name: "payer",
          writable: true,
          signer: true
        },
        {
          name: "position",
          writable: true,
          signer: true
        },
        {
          name: "lb_pair"
        },
        {
          name: "owner",
          signer: true
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "lower_bin_id",
          type: "i32"
        },
        {
          name: "width",
          type: "i32"
        }
      ]
    },
    {
      name: "initialize_position_by_operator",
      discriminator: [251, 189, 190, 244, 117, 254, 35, 148],
      accounts: [
        {
          name: "payer",
          writable: true,
          signer: true
        },
        {
          name: "base",
          signer: true
        },
        {
          name: "position",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [112, 111, 115, 105, 116, 105, 111, 110]
              },
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "account",
                path: "base"
              },
              {
                kind: "arg",
                path: "lower_bin_id"
              },
              {
                kind: "arg",
                path: "width"
              }
            ]
          }
        },
        {
          name: "lb_pair"
        },
        {
          name: "owner"
        },
        {
          name: "operator",
          docs: ["operator"],
          signer: true
        },
        {
          name: "operator_token_x"
        },
        {
          name: "owner_token_x"
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "lower_bin_id",
          type: "i32"
        },
        {
          name: "width",
          type: "i32"
        },
        {
          name: "fee_owner",
          type: "pubkey"
        },
        {
          name: "lock_release_point",
          type: "u64"
        }
      ]
    },
    {
      name: "initialize_position_pda",
      discriminator: [46, 82, 125, 146, 85, 141, 228, 153],
      accounts: [
        {
          name: "payer",
          writable: true,
          signer: true
        },
        {
          name: "base",
          signer: true
        },
        {
          name: "position",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [112, 111, 115, 105, 116, 105, 111, 110]
              },
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "account",
                path: "base"
              },
              {
                kind: "arg",
                path: "lower_bin_id"
              },
              {
                kind: "arg",
                path: "width"
              }
            ]
          }
        },
        {
          name: "lb_pair"
        },
        {
          name: "owner",
          docs: ["owner"],
          signer: true
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "rent"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "lower_bin_id",
          type: "i32"
        },
        {
          name: "width",
          type: "i32"
        }
      ]
    },
    {
      name: "initialize_preset_parameter",
      discriminator: [66, 188, 71, 211, 98, 109, 14, 186],
      accounts: [
        {
          name: "preset_parameter",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  112,
                  114,
                  101,
                  115,
                  101,
                  116,
                  95,
                  112,
                  97,
                  114,
                  97,
                  109,
                  101,
                  116,
                  101,
                  114,
                  50
                ]
              },
              {
                kind: "arg",
                path: "ix.index"
              }
            ]
          }
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          signer: true
        },
        {
          name: "payer",
          writable: true,
          signer: true
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        }
      ],
      args: [
        {
          name: "ix",
          type: {
            defined: {
              name: "InitPresetParametersIx"
            }
          }
        }
      ]
    },
    {
      name: "initialize_reward",
      discriminator: [95, 135, 192, 196, 242, 129, 230, 68],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "reward_vault",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "account",
                path: "lb_pair"
              },
              {
                kind: "arg",
                path: "reward_index"
              }
            ]
          }
        },
        {
          name: "reward_mint"
        },
        {
          name: "token_badge",
          optional: true
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          signer: true
        },
        {
          name: "payer",
          writable: true,
          signer: true
        },
        {
          name: "token_program"
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "reward_index",
          type: "u64"
        },
        {
          name: "reward_duration",
          type: "u64"
        },
        {
          name: "funder",
          type: "pubkey"
        }
      ]
    },
    {
      name: "initialize_token_badge",
      discriminator: [253, 77, 205, 95, 27, 224, 89, 223],
      accounts: [
        {
          name: "token_mint"
        },
        {
          name: "token_badge",
          writable: true,
          pda: {
            seeds: [
              {
                kind: "const",
                value: [116, 111, 107, 101, 110, 95, 98, 97, 100, 103, 101]
              },
              {
                kind: "account",
                path: "token_mint"
              }
            ]
          }
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          signer: true
        },
        {
          name: "payer",
          writable: true,
          signer: true
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        }
      ],
      args: []
    },
    {
      name: "place_limit_order",
      discriminator: [108, 176, 33, 186, 146, 229, 1, 197],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "reserve",
          writable: true
        },
        {
          name: "token_mint"
        },
        {
          name: "limit_order",
          writable: true,
          signer: true
        },
        {
          name: "payer",
          writable: true,
          signer: true
        },
        {
          name: "owner"
        },
        {
          name: "user_token",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_program"
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "params",
          type: {
            defined: {
              name: "PlaceLimitOrderParams"
            }
          }
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "rebalance_liquidity",
      discriminator: [92, 4, 176, 193, 119, 185, 83, 9],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: ["position", "bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "owner",
          signer: true,
          relations: ["position"]
        },
        {
          name: "rent_payer",
          writable: true,
          signer: true
        },
        {
          name: "token_x_program"
        },
        {
          name: "token_y_program"
        },
        {
          name: "memo_program",
          address: "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
        },
        {
          name: "system_program",
          address: "11111111111111111111111111111111"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "params",
          type: {
            defined: {
              name: "RebalanceLiquidityParams"
            }
          }
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "remove_all_liquidity",
      discriminator: [10, 51, 61, 35, 112, 105, 24, 85],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: [
            "position",
            "bin_array_bitmap_extension",
            "bin_array_lower",
            "bin_array_upper"
          ]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_x_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "token_y_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: []
    },
    {
      name: "remove_liquidity",
      discriminator: [80, 85, 209, 72, 24, 206, 177, 108],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: [
            "position",
            "bin_array_bitmap_extension",
            "bin_array_lower",
            "bin_array_upper"
          ]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_x_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "token_y_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "bin_liquidity_removal",
          type: {
            vec: {
              defined: {
                name: "BinLiquidityReduction"
              }
            }
          }
        }
      ]
    },
    {
      name: "remove_liquidity2",
      discriminator: [230, 215, 82, 127, 241, 101, 227, 146],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: ["position", "bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_x_program"
        },
        {
          name: "token_y_program"
        },
        {
          name: "memo_program",
          address: "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "bin_liquidity_removal",
          type: {
            vec: {
              defined: {
                name: "BinLiquidityReduction"
              }
            }
          }
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "remove_liquidity_by_range",
      discriminator: [26, 82, 102, 152, 240, 74, 105, 26],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: [
            "position",
            "bin_array_bitmap_extension",
            "bin_array_lower",
            "bin_array_upper"
          ]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_x_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "token_y_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "from_bin_id",
          type: "i32"
        },
        {
          name: "to_bin_id",
          type: "i32"
        },
        {
          name: "bps_to_remove",
          type: "u16"
        }
      ]
    },
    {
      name: "remove_liquidity_by_range2",
      discriminator: [204, 2, 195, 145, 53, 145, 145, 205],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: ["position", "bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "user_token_x",
          writable: true
        },
        {
          name: "user_token_y",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "sender",
          signer: true
        },
        {
          name: "token_x_program"
        },
        {
          name: "token_y_program"
        },
        {
          name: "memo_program",
          address: "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "from_bin_id",
          type: "i32"
        },
        {
          name: "to_bin_id",
          type: "i32"
        },
        {
          name: "bps_to_remove",
          type: "u16"
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "set_activation_point",
      discriminator: [91, 249, 15, 165, 26, 129, 254, 125],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "signer",
          signer: true
        }
      ],
      args: [
        {
          name: "activation_point",
          type: "u64"
        }
      ]
    },
    {
      name: "set_pair_status",
      discriminator: [67, 248, 231, 137, 154, 149, 217, 174],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          signer: true
        }
      ],
      args: [
        {
          name: "status",
          type: "u8"
        }
      ]
    },
    {
      name: "set_pair_status_permissionless",
      discriminator: [78, 59, 152, 211, 70, 183, 46, 208],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "signer",
          signer: true
        }
      ],
      args: [
        {
          name: "status",
          type: "u8"
        }
      ]
    },
    {
      name: "set_permissionless_operation_bits",
      discriminator: [84, 58, 203, 139, 163, 81, 190, 186],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "owner",
          signer: true,
          relations: ["position"]
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "bits",
          type: "u8"
        }
      ]
    },
    {
      name: "set_pre_activation_duration",
      discriminator: [165, 61, 201, 244, 130, 159, 22, 100],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "signer",
          signer: true
        }
      ],
      args: [
        {
          name: "pre_activation_duration",
          type: "u64"
        }
      ]
    },
    {
      name: "set_pre_activation_swap_address",
      discriminator: [57, 139, 47, 123, 216, 80, 223, 10],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "signer",
          signer: true
        }
      ],
      args: [
        {
          name: "pre_activation_swap_address",
          type: "pubkey"
        }
      ]
    },
    {
      name: "swap",
      discriminator: [248, 198, 158, 145, 225, 117, 135, 200],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "user_token_in",
          writable: true
        },
        {
          name: "user_token_out",
          writable: true
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "oracle",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "host_fee_in",
          writable: true,
          optional: true
        },
        {
          name: "user",
          signer: true
        },
        {
          name: "token_x_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "token_y_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "amount_in",
          type: "u64"
        },
        {
          name: "min_amount_out",
          type: "u64"
        }
      ]
    },
    {
      name: "swap2",
      discriminator: [65, 75, 63, 76, 235, 91, 91, 136],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "user_token_in",
          writable: true
        },
        {
          name: "user_token_out",
          writable: true
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "oracle",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "host_fee_in",
          writable: true,
          optional: true
        },
        {
          name: "user",
          signer: true
        },
        {
          name: "token_x_program"
        },
        {
          name: "token_y_program"
        },
        {
          name: "memo_program",
          address: "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "amount_in",
          type: "u64"
        },
        {
          name: "min_amount_out",
          type: "u64"
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "swap_exact_out",
      discriminator: [250, 73, 101, 33, 38, 207, 75, 184],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "user_token_in",
          writable: true
        },
        {
          name: "user_token_out",
          writable: true
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "oracle",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "host_fee_in",
          writable: true,
          optional: true
        },
        {
          name: "user",
          signer: true
        },
        {
          name: "token_x_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "token_y_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "max_in_amount",
          type: "u64"
        },
        {
          name: "out_amount",
          type: "u64"
        }
      ]
    },
    {
      name: "swap_exact_out2",
      discriminator: [43, 215, 247, 132, 137, 60, 243, 81],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "user_token_in",
          writable: true
        },
        {
          name: "user_token_out",
          writable: true
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "oracle",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "host_fee_in",
          writable: true,
          optional: true
        },
        {
          name: "user",
          signer: true
        },
        {
          name: "token_x_program"
        },
        {
          name: "token_y_program"
        },
        {
          name: "memo_program",
          address: "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "max_in_amount",
          type: "u64"
        },
        {
          name: "out_amount",
          type: "u64"
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "swap_with_price_impact",
      discriminator: [56, 173, 230, 208, 173, 228, 156, 205],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "user_token_in",
          writable: true
        },
        {
          name: "user_token_out",
          writable: true
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "oracle",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "host_fee_in",
          writable: true,
          optional: true
        },
        {
          name: "user",
          signer: true
        },
        {
          name: "token_x_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "token_y_program",
          address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "amount_in",
          type: "u64"
        },
        {
          name: "active_id",
          type: {
            option: "i32"
          }
        },
        {
          name: "max_price_impact_bps",
          type: "u16"
        }
      ]
    },
    {
      name: "swap_with_price_impact2",
      discriminator: [74, 98, 192, 214, 177, 51, 75, 51],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["bin_array_bitmap_extension"]
        },
        {
          name: "bin_array_bitmap_extension",
          writable: true,
          optional: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "user_token_in",
          writable: true
        },
        {
          name: "user_token_out",
          writable: true
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "oracle",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "host_fee_in",
          writable: true,
          optional: true
        },
        {
          name: "user",
          signer: true
        },
        {
          name: "token_x_program"
        },
        {
          name: "token_y_program"
        },
        {
          name: "memo_program",
          address: "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "amount_in",
          type: "u64"
        },
        {
          name: "active_id",
          type: {
            option: "i32"
          }
        },
        {
          name: "max_price_impact_bps",
          type: "u16"
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "update_base_fee_parameters",
      discriminator: [75, 168, 223, 161, 16, 195, 3, 47],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          signer: true
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "fee_parameter",
          type: {
            defined: {
              name: "BaseFeeParameter"
            }
          }
        }
      ]
    },
    {
      name: "update_dynamic_fee_parameters",
      discriminator: [92, 161, 46, 246, 255, 189, 22, 22],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          signer: true
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "fee_parameter",
          type: {
            defined: {
              name: "DynamicFeeParameter"
            }
          }
        }
      ]
    },
    {
      name: "update_fees_and_reward2",
      discriminator: [32, 142, 184, 154, 103, 65, 184, 88],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: ["position"]
        },
        {
          name: "owner",
          signer: true
        }
      ],
      args: [
        {
          name: "min_bin_id",
          type: "i32"
        },
        {
          name: "max_bin_id",
          type: "i32"
        }
      ]
    },
    {
      name: "update_fees_and_rewards",
      discriminator: [154, 230, 250, 13, 236, 209, 75, 223],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "lb_pair",
          writable: true,
          relations: ["position", "bin_array_lower", "bin_array_upper"]
        },
        {
          name: "bin_array_lower",
          writable: true
        },
        {
          name: "bin_array_upper",
          writable: true
        },
        {
          name: "owner",
          signer: true
        }
      ],
      args: []
    },
    {
      name: "update_position_operator",
      discriminator: [202, 184, 103, 143, 180, 191, 116, 217],
      accounts: [
        {
          name: "position",
          writable: true
        },
        {
          name: "owner",
          signer: true,
          relations: ["position"]
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "operator",
          type: "pubkey"
        }
      ]
    },
    {
      name: "update_reward_duration",
      discriminator: [138, 174, 196, 169, 213, 235, 254, 107],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["bin_array"]
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          signer: true
        },
        {
          name: "bin_array",
          writable: true
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "reward_index",
          type: "u64"
        },
        {
          name: "new_duration",
          type: "u64"
        }
      ]
    },
    {
      name: "update_reward_funder",
      discriminator: [211, 28, 48, 32, 215, 160, 35, 23],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          signer: true
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "reward_index",
          type: "u64"
        },
        {
          name: "new_funder",
          type: "pubkey"
        }
      ]
    },
    {
      name: "withdraw_ineligible_reward",
      discriminator: [148, 206, 42, 195, 247, 49, 103, 8],
      accounts: [
        {
          name: "lb_pair",
          writable: true,
          relations: ["bin_array"]
        },
        {
          name: "reward_vault",
          writable: true
        },
        {
          name: "reward_mint"
        },
        {
          name: "funder_token_account",
          writable: true
        },
        {
          name: "funder",
          signer: true
        },
        {
          name: "bin_array",
          writable: true
        },
        {
          name: "token_program"
        },
        {
          name: "memo_program",
          address: "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
        },
        {
          name: "event_authority",
          pda: {
            seeds: [
              {
                kind: "const",
                value: [
                  95,
                  95,
                  101,
                  118,
                  101,
                  110,
                  116,
                  95,
                  97,
                  117,
                  116,
                  104,
                  111,
                  114,
                  105,
                  116,
                  121
                ]
              }
            ]
          }
        },
        {
          name: "program"
        }
      ],
      args: [
        {
          name: "reward_index",
          type: "u64"
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "withdraw_protocol_fee",
      discriminator: [158, 201, 158, 189, 33, 93, 162, 103],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "reserve_x",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "reserve_y",
          writable: true,
          relations: ["lb_pair"]
        },
        {
          name: "token_x_mint",
          relations: ["lb_pair"]
        },
        {
          name: "token_y_mint",
          relations: ["lb_pair"]
        },
        {
          name: "receiver_token_x",
          writable: true
        },
        {
          name: "receiver_token_y",
          writable: true
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          docs: ["operator"],
          signer: true
        },
        {
          name: "token_x_program"
        },
        {
          name: "token_y_program"
        }
      ],
      args: [
        {
          name: "max_amount_x",
          type: "u64"
        },
        {
          name: "max_amount_y",
          type: "u64"
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    },
    {
      name: "zap_protocol_fee",
      discriminator: [213, 155, 187, 34, 56, 182, 91, 240],
      accounts: [
        {
          name: "lb_pair",
          writable: true
        },
        {
          name: "reserve",
          writable: true
        },
        {
          name: "token_mint"
        },
        {
          name: "receiver_token",
          writable: true
        },
        {
          name: "operator"
        },
        {
          name: "signer",
          docs: ["operator"],
          signer: true
        },
        {
          name: "token_program"
        },
        {
          name: "sysvar_instructions",
          address: "Sysvar1nstructions1111111111111111111111111"
        }
      ],
      args: [
        {
          name: "max_amount",
          type: "u64"
        },
        {
          name: "remaining_accounts_info",
          type: {
            defined: {
              name: "RemainingAccountsInfo"
            }
          }
        }
      ]
    }
  ],
  accounts: [
    {
      name: "BinArray",
      discriminator: [92, 142, 92, 220, 5, 148, 70, 181]
    },
    {
      name: "BinArrayBitmapExtension",
      discriminator: [80, 111, 124, 113, 55, 237, 18, 5]
    },
    {
      name: "ClaimFeeOperator",
      discriminator: [166, 48, 134, 86, 34, 200, 188, 150]
    },
    {
      name: "DummyZcAccount",
      discriminator: [94, 107, 238, 80, 208, 48, 180, 8]
    },
    {
      name: "LbPair",
      discriminator: [33, 11, 49, 98, 181, 101, 177, 13]
    },
    {
      name: "LimitOrder",
      discriminator: [137, 183, 212, 91, 115, 29, 141, 227]
    },
    {
      name: "Operator",
      discriminator: [219, 31, 188, 145, 69, 139, 204, 117]
    },
    {
      name: "Oracle",
      discriminator: [139, 194, 131, 179, 140, 179, 229, 244]
    },
    {
      name: "PositionV2",
      discriminator: [117, 176, 212, 199, 245, 180, 133, 182]
    },
    {
      name: "PresetParameter",
      discriminator: [242, 62, 244, 34, 181, 112, 58, 170]
    },
    {
      name: "PresetParameter2",
      discriminator: [171, 236, 148, 115, 162, 113, 222, 174]
    },
    {
      name: "TokenBadge",
      discriminator: [116, 219, 204, 229, 249, 116, 255, 150]
    }
  ],
  events: [
    {
      name: "AddLiquidity",
      discriminator: [31, 94, 125, 90, 227, 52, 61, 186]
    },
    {
      name: "CancelLimitOrderEvt",
      discriminator: [131, 234, 194, 133, 9, 14, 189, 209]
    },
    {
      name: "ClaimFee",
      discriminator: [75, 122, 154, 48, 140, 74, 123, 163]
    },
    {
      name: "ClaimFee2",
      discriminator: [232, 171, 242, 97, 58, 77, 35, 45]
    },
    {
      name: "ClaimReward",
      discriminator: [148, 116, 134, 204, 22, 171, 85, 95]
    },
    {
      name: "ClaimReward2",
      discriminator: [27, 143, 244, 33, 80, 43, 110, 146]
    },
    {
      name: "CloseLimitOrderEvt",
      discriminator: [142, 135, 8, 76, 92, 63, 118, 83]
    },
    {
      name: "CompositionFee",
      discriminator: [128, 151, 123, 106, 17, 102, 113, 142]
    },
    {
      name: "DecreasePositionLength",
      discriminator: [52, 118, 235, 85, 172, 169, 15, 128]
    },
    {
      name: "DynamicFeeParameterUpdate",
      discriminator: [88, 88, 178, 135, 194, 146, 91, 243]
    },
    {
      name: "FeeParameterUpdate",
      discriminator: [48, 76, 241, 117, 144, 215, 242, 44]
    },
    {
      name: "FundReward",
      discriminator: [246, 228, 58, 130, 145, 170, 79, 204]
    },
    {
      name: "GoToABin",
      discriminator: [59, 138, 76, 68, 138, 131, 176, 67]
    },
    {
      name: "IncreaseObservation",
      discriminator: [99, 249, 17, 121, 166, 156, 207, 215]
    },
    {
      name: "IncreasePositionLength",
      discriminator: [157, 239, 42, 204, 30, 56, 223, 46]
    },
    {
      name: "InitializeReward",
      discriminator: [211, 153, 88, 62, 149, 60, 177, 70]
    },
    {
      name: "LbPairCreate",
      discriminator: [185, 74, 252, 125, 27, 215, 188, 111]
    },
    {
      name: "PlaceLimitOrderEvt",
      discriminator: [43, 79, 27, 169, 244, 28, 225, 63]
    },
    {
      name: "PositionClose",
      discriminator: [255, 196, 16, 107, 28, 202, 53, 128]
    },
    {
      name: "PositionCreate",
      discriminator: [144, 142, 252, 84, 157, 53, 37, 121]
    },
    {
      name: "Rebalancing",
      discriminator: [0, 109, 117, 179, 61, 91, 199, 200]
    },
    {
      name: "RemoveLiquidity",
      discriminator: [116, 244, 97, 232, 103, 31, 152, 58]
    },
    {
      name: "SetPositionPermissionlessOperationBitsEvt",
      discriminator: [195, 229, 147, 245, 29, 125, 48, 168]
    },
    {
      name: "Swap",
      discriminator: [81, 108, 227, 190, 205, 208, 10, 196]
    },
    {
      name: "Swap2Evt",
      discriminator: [46, 116, 82, 215, 148, 27, 84, 77]
    },
    {
      name: "UpdatePositionLockReleasePoint",
      discriminator: [133, 214, 66, 224, 64, 12, 7, 191]
    },
    {
      name: "UpdatePositionOperator",
      discriminator: [39, 115, 48, 204, 246, 47, 66, 57]
    },
    {
      name: "UpdateRewardDuration",
      discriminator: [223, 245, 224, 153, 49, 29, 163, 172]
    },
    {
      name: "UpdateRewardFunder",
      discriminator: [224, 178, 174, 74, 252, 165, 85, 180]
    },
    {
      name: "WithdrawIneligibleReward",
      discriminator: [231, 189, 65, 149, 102, 215, 154, 244]
    }
  ],
  errors: [
    {
      code: 6e3,
      name: "InvalidStartBinIndex",
      msg: "Invalid start bin index"
    },
    {
      code: 6001,
      name: "InvalidBinId",
      msg: "Invalid bin id"
    },
    {
      code: 6002,
      name: "InvalidInput",
      msg: "Invalid input data"
    },
    {
      code: 6003,
      name: "ExceededAmountSlippageTolerance",
      msg: "Exceeded amount slippage tolerance"
    },
    {
      code: 6004,
      name: "ExceededBinSlippageTolerance",
      msg: "Exceeded bin slippage tolerance"
    },
    {
      code: 6005,
      name: "CompositionFactorFlawed",
      msg: "Composition factor flawed"
    },
    {
      code: 6006,
      name: "NonPresetBinStep",
      msg: "Non preset bin step"
    },
    {
      code: 6007,
      name: "ZeroLiquidity",
      msg: "Zero liquidity"
    },
    {
      code: 6008,
      name: "InvalidPosition",
      msg: "Invalid position"
    },
    {
      code: 6009,
      name: "BinArrayNotFound",
      msg: "Bin array not found"
    },
    {
      code: 6010,
      name: "InvalidTokenMint",
      msg: "Invalid token mint"
    },
    {
      code: 6011,
      name: "InvalidAccountForSingleDeposit",
      msg: "Invalid account for single deposit"
    },
    {
      code: 6012,
      name: "PairInsufficientLiquidity",
      msg: "Pair insufficient liquidity"
    },
    {
      code: 6013,
      name: "InvalidFeeOwner",
      msg: "Invalid fee owner"
    },
    {
      code: 6014,
      name: "InvalidFeeWithdrawAmount",
      msg: "Invalid fee withdraw amount"
    },
    {
      code: 6015,
      name: "InvalidAdmin",
      msg: "Invalid admin"
    },
    {
      code: 6016,
      name: "IdenticalFeeOwner",
      msg: "Identical fee owner"
    },
    {
      code: 6017,
      name: "InvalidBps",
      msg: "Invalid basis point"
    },
    {
      code: 6018,
      name: "MathOverflow",
      msg: "Math operation overflow"
    },
    {
      code: 6019,
      name: "TypeCastFailed",
      msg: "Type cast error"
    },
    {
      code: 6020,
      name: "InvalidRewardIndex",
      msg: "Invalid reward index"
    },
    {
      code: 6021,
      name: "InvalidRewardDuration",
      msg: "Invalid reward duration"
    },
    {
      code: 6022,
      name: "RewardInitialized",
      msg: "Reward already initialized"
    },
    {
      code: 6023,
      name: "RewardUninitialized",
      msg: "Reward not initialized"
    },
    {
      code: 6024,
      name: "IdenticalFunder",
      msg: "Identical funder"
    },
    {
      code: 6025,
      name: "RewardCampaignInProgress",
      msg: "Reward campaign in progress"
    },
    {
      code: 6026,
      name: "IdenticalRewardDuration",
      msg: "Reward duration is the same"
    },
    {
      code: 6027,
      name: "InvalidBinArray",
      msg: "Invalid bin array"
    },
    {
      code: 6028,
      name: "NonContinuousBinArrays",
      msg: "Bin arrays must be continuous"
    },
    {
      code: 6029,
      name: "InvalidRewardVault",
      msg: "Invalid reward vault"
    },
    {
      code: 6030,
      name: "NonEmptyPosition",
      msg: "Position is not empty"
    },
    {
      code: 6031,
      name: "UnauthorizedAccess",
      msg: "Unauthorized access"
    },
    {
      code: 6032,
      name: "InvalidFeeParameter",
      msg: "Invalid fee parameter"
    },
    {
      code: 6033,
      name: "MissingOracle",
      msg: "Missing oracle account"
    },
    {
      code: 6034,
      name: "InsufficientSample",
      msg: "Insufficient observation sample"
    },
    {
      code: 6035,
      name: "InvalidLookupTimestamp",
      msg: "Invalid lookup timestamp"
    },
    {
      code: 6036,
      name: "BitmapExtensionAccountIsNotProvided",
      msg: "Bitmap extension account is not provided"
    },
    {
      code: 6037,
      name: "CannotFindNonZeroLiquidityBinArrayId",
      msg: "Cannot find non-zero liquidity binArrayId"
    },
    {
      code: 6038,
      name: "BinIdOutOfBound",
      msg: "Bin id out of bound"
    },
    {
      code: 6039,
      name: "InsufficientOutAmount",
      msg: "Insufficient amount in for minimum out"
    },
    {
      code: 6040,
      name: "InvalidPositionWidth",
      msg: "Invalid position width"
    },
    {
      code: 6041,
      name: "ExcessiveFeeUpdate",
      msg: "Excessive fee update"
    },
    {
      code: 6042,
      name: "PoolDisabled",
      msg: "Pool disabled"
    },
    {
      code: 6043,
      name: "InvalidPoolType",
      msg: "Invalid pool type"
    },
    {
      code: 6044,
      name: "ExceedMaxWhitelist",
      msg: "Whitelist for wallet is full"
    },
    {
      code: 6045,
      name: "InvalidIndex",
      msg: "Invalid index"
    },
    {
      code: 6046,
      name: "RewardNotEnded",
      msg: "Reward not ended"
    },
    {
      code: 6047,
      name: "MustWithdrawnIneligibleReward",
      msg: "Must withdraw ineligible reward"
    },
    {
      code: 6048,
      name: "UnauthorizedAddress",
      msg: "Unauthorized address"
    },
    {
      code: 6049,
      name: "OperatorsAreTheSame",
      msg: "Cannot update because operators are the same"
    },
    {
      code: 6050,
      name: "WithdrawToWrongTokenAccount",
      msg: "Withdraw to wrong token account"
    },
    {
      code: 6051,
      name: "WrongRentReceiver",
      msg: "Wrong rent receiver"
    },
    {
      code: 6052,
      name: "AlreadyPassActivationPoint",
      msg: "Already activated"
    },
    {
      code: 6053,
      name: "ExceedMaxSwappedAmount",
      msg: "Swapped amount is exceeded max swapped amount"
    },
    {
      code: 6054,
      name: "InvalidStrategyParameters",
      msg: "Invalid strategy parameters"
    },
    {
      code: 6055,
      name: "LiquidityLocked",
      msg: "Liquidity locked"
    },
    {
      code: 6056,
      name: "BinRangeIsNotEmpty",
      msg: "Bin range is not empty"
    },
    {
      code: 6057,
      name: "NotExactAmountOut",
      msg: "Amount out is not matched with exact amount out"
    },
    {
      code: 6058,
      name: "InvalidActivationType",
      msg: "Invalid activation type"
    },
    {
      code: 6059,
      name: "InvalidActivationDuration",
      msg: "Invalid activation duration"
    },
    {
      code: 6060,
      name: "MissingTokenAmountAsTokenLaunchProof",
      msg: "Missing token amount as token launch owner proof"
    },
    {
      code: 6061,
      name: "InvalidQuoteToken",
      msg: "Quote token must be SOL or USDC"
    },
    {
      code: 6062,
      name: "InvalidBinStep",
      msg: "Invalid bin step"
    },
    {
      code: 6063,
      name: "InvalidBaseFee",
      msg: "Invalid base fee"
    },
    {
      code: 6064,
      name: "InvalidPreActivationDuration",
      msg: "Invalid pre-activation duration"
    },
    {
      code: 6065,
      name: "AlreadyPassPreActivationSwapPoint",
      msg: "Already pass pre-activation swap point"
    },
    {
      code: 6066,
      name: "InvalidStatus",
      msg: "Invalid status"
    },
    {
      code: 6067,
      name: "ExceededMaxOracleLength",
      msg: "Exceed max oracle length"
    },
    {
      code: 6068,
      name: "InvalidMinimumLiquidity",
      msg: "Invalid minimum liquidity"
    },
    {
      code: 6069,
      name: "NotSupportMint",
      msg: "Not support token_2022 mint extension"
    },
    {
      code: 6070,
      name: "UnsupportedMintExtension",
      msg: "Unsupported mint extension"
    },
    {
      code: 6071,
      name: "UnsupportNativeMintToken2022",
      msg: "Unsupported native mint token2022"
    },
    {
      code: 6072,
      name: "UnmatchTokenMint",
      msg: "Unmatch token mint"
    },
    {
      code: 6073,
      name: "UnsupportedTokenMint",
      msg: "Unsupported token mint"
    },
    {
      code: 6074,
      name: "InsufficientRemainingAccounts",
      msg: "Insufficient remaining accounts"
    },
    {
      code: 6075,
      name: "InvalidRemainingAccountSlice",
      msg: "Invalid remaining account slice"
    },
    {
      code: 6076,
      name: "DuplicatedRemainingAccountTypes",
      msg: "Duplicated remaining account types"
    },
    {
      code: 6077,
      name: "MissingRemainingAccountForTransferHook",
      msg: "Missing remaining account for transfer hook"
    },
    {
      code: 6078,
      name: "NoTransferHookProgram",
      msg: "Remaining account was passed for transfer hook but there's no hook program"
    },
    {
      code: 6079,
      name: "ZeroFundedAmount",
      msg: "Zero funded amount"
    },
    {
      code: 6080,
      name: "InvalidSide",
      msg: "Invalid side"
    },
    {
      code: 6081,
      name: "InvalidResizeLength",
      msg: "Invalid resize length"
    },
    {
      code: 6082,
      name: "NotSupportAtTheMoment",
      msg: "Not support at the moment"
    },
    {
      code: 6083,
      name: "InvalidRebalanceParameters",
      msg: "Invalid rebalance parameters"
    },
    {
      code: 6084,
      name: "InvalidRewardAccounts",
      msg: "Invalid reward accounts"
    },
    {
      code: 6085,
      name: "UndeterminedError",
      msg: "Undetermined error"
    },
    {
      code: 6086,
      name: "ReallocExceedMaxLengthPerInstruction",
      msg: "Realloc exceed max length per instruction"
    },
    {
      code: 6087,
      name: "InvalidBaseFeeMantissa",
      msg: "Mantissa cannot more than two significant digits"
    },
    {
      code: 6088,
      name: "InvalidPositionOwner",
      msg: "Invalid position owner"
    },
    {
      code: 6089,
      name: "InvalidPoolAddress",
      msg: "Invalid pool address"
    },
    {
      code: 6090,
      name: "InvalidTokenBadgeType",
      msg: "Invalid token badge type"
    },
    {
      code: 6091,
      name: "InvalidTransferHookAuthority",
      msg: "Invalid transfer hook authority"
    },
    {
      code: 6092,
      name: "AmountXIsNegative",
      msg: "Amount x is negative"
    },
    {
      code: 6093,
      name: "AmountYIsNegative",
      msg: "Amount y is negative"
    },
    {
      code: 6094,
      name: "InvalidPoolCreator",
      msg: "Invalid pool creator"
    },
    {
      code: 6095,
      name: "InvalidFunctionType",
      msg: "Invalid function type"
    },
    {
      code: 6096,
      name: "InvalidPermission",
      msg: "Invalid permission"
    },
    {
      code: 6097,
      name: "IncorrectATA",
      msg: "Incorrect ATA"
    },
    {
      code: 6098,
      name: "InvalidWithdrawProtocolFeeZapAccounts",
      msg: "Invalid withdraw protocol fee zap accounts"
    },
    {
      code: 6099,
      name: "MintRestrictedFromZap",
      msg: "SOL,USDC protocol fee cannot be withdrawn via zap"
    },
    {
      code: 6100,
      name: "CpiDisabled",
      msg: "CPI disabled"
    },
    {
      code: 6101,
      name: "MissingZapOutInstruction",
      msg: "Missing zap out instruction"
    },
    {
      code: 6102,
      name: "InvalidZapAccounts",
      msg: "Invalid zap accounts"
    },
    {
      code: 6103,
      name: "InvalidZapOutParameters",
      msg: "Invalid zap out parameters"
    },
    {
      code: 6104,
      name: "InsufficientInAmount",
      msg: "Insufficient in amount"
    },
    {
      code: 6105,
      name: "InvalidPlaceLimitOrderParameters",
      msg: "Invalid place limit order parameters"
    },
    {
      code: 6106,
      name: "InvalidLimitOrderOwner",
      msg: "Invalid limit order owner"
    },
    {
      code: 6107,
      name: "InvalidCancelLimitOrderParameters",
      msg: "Invalid cancel limit order parameters"
    },
    {
      code: 6108,
      name: "CannotFindLimitOrderByBinId",
      msg: "Cannot find limit order by bin id"
    },
    {
      code: 6109,
      name: "CancelNonEmptyLimitOrder",
      msg: "Cannot cancel non-empty limit order"
    },
    {
      code: 6110,
      name: "InvalidCollectFeeMode",
      msg: "Invalid collect fee mode"
    }
  ],
  types: [
    {
      name: "AccountsType",
      type: {
        kind: "enum",
        variants: [
          {
            name: "TransferHookX"
          },
          {
            name: "TransferHookY"
          },
          {
            name: "TransferHookReward"
          },
          {
            name: "TransferHookMultiReward",
            fields: ["u8"]
          },
          {
            name: "TransferHookReferral"
          }
        ]
      }
    },
    {
      name: "ActivationType",
      docs: ["Type of the activation"],
      repr: {
        kind: "rust"
      },
      type: {
        kind: "enum",
        variants: [
          {
            name: "Slot"
          },
          {
            name: "Timestamp"
          }
        ]
      }
    },
    {
      name: "AddLiquidity",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "from",
            type: "pubkey"
          },
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "amounts",
            type: {
              array: ["u64", 2]
            }
          },
          {
            name: "active_bin_id",
            type: "i32"
          }
        ]
      }
    },
    {
      name: "AddLiquidityParams",
      type: {
        kind: "struct",
        fields: [
          {
            name: "min_delta_id",
            type: "i32"
          },
          {
            name: "max_delta_id",
            type: "i32"
          },
          {
            name: "x0",
            type: "u64"
          },
          {
            name: "y0",
            type: "u64"
          },
          {
            name: "delta_x",
            type: "u64"
          },
          {
            name: "delta_y",
            type: "u64"
          },
          {
            name: "bit_flag",
            type: "u8"
          },
          {
            name: "favor_x_in_active_id",
            type: "bool"
          },
          {
            name: "padding",
            type: {
              array: ["u8", 16]
            }
          }
        ]
      }
    },
    {
      name: "AddLiquiditySingleSidePreciseParameter",
      type: {
        kind: "struct",
        fields: [
          {
            name: "bins",
            type: {
              vec: {
                defined: {
                  name: "CompressedBinDepositAmount"
                }
              }
            }
          },
          {
            name: "decompress_multiplier",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "AddLiquiditySingleSidePreciseParameter2",
      type: {
        kind: "struct",
        fields: [
          {
            name: "bins",
            type: {
              vec: {
                defined: {
                  name: "CompressedBinDepositAmount"
                }
              }
            }
          },
          {
            name: "decompress_multiplier",
            type: "u64"
          },
          {
            name: "max_amount",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "BaseFeeParameter",
      type: {
        kind: "struct",
        fields: [
          {
            name: "protocol_share",
            docs: [
              "Portion of swap fees retained by the protocol by controlling protocol_share parameter. protocol_swap_fee = protocol_share * total_swap_fee"
            ],
            type: "u16"
          },
          {
            name: "base_factor",
            docs: ["Base factor for base fee rate"],
            type: "u16"
          },
          {
            name: "base_fee_power_factor",
            docs: ["Base fee power factor"],
            type: "u8"
          }
        ]
      }
    },
    {
      name: "Bin",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "amount_x",
            docs: [
              "Amount of token X in the bin for market making. This already excluded protocol fees."
            ],
            type: "u64"
          },
          {
            name: "amount_y",
            docs: [
              "Amount of token Y in the bin for market making. This already excluded protocol fees."
            ],
            type: "u64"
          },
          {
            name: "price",
            docs: ["Bin price"],
            type: "u128"
          },
          {
            name: "liquidity_supply",
            docs: ["Bin MM liquidity supply."],
            type: "u128"
          },
          {
            name: "fulfilled_order_amount_x",
            docs: ["Total fulfilled order amount x"],
            type: "u64"
          },
          {
            name: "fulfilled_order_amount_y",
            docs: ["Total fulfilled order amount y"],
            type: "u64"
          },
          {
            name: "limit_order_fee_ask_side",
            docs: ["Limit order fee collected by ask side orders"],
            type: "u64"
          },
          {
            name: "limit_order_fee_bid_side",
            docs: ["Limit order fee collected by bid side orders"],
            type: "u64"
          },
          {
            name: "fee_amount_x_per_token_stored",
            docs: ["Swap fee amount of token X per liquidity deposited."],
            type: "u128"
          },
          {
            name: "fee_amount_y_per_token_stored",
            docs: ["Swap fee amount of token Y per liquidity deposited."],
            type: "u128"
          },
          {
            name: "open_order_amount",
            docs: ["Pending open limit orders amount in the bin."],
            type: "u64"
          },
          {
            name: "total_processing_order_amount",
            docs: ["Total processing order amount"],
            type: "u64"
          },
          {
            name: "processed_order_remaining_amount",
            docs: [
              "Remaining in processing open limit orders amount in the bin."
            ],
            type: "u64"
          },
          {
            name: "order_age",
            docs: ["Age"],
            type: "u32"
          },
          {
            name: "limit_order_ask_side",
            docs: ["limit order flag"],
            type: "u8"
          },
          {
            name: "_padding_1",
            docs: ["padding"],
            type: {
              array: ["u8", 3]
            }
          }
        ]
      }
    },
    {
      name: "BinArray",
      docs: [
        "An account to contain a range of bin. For example: Bin 100 <-> 200.",
        "For example:",
        "BinArray index: 0 contains bin 0 <-> 599",
        "index: 2 contains bin 600 <-> 1199, ..."
      ],
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "index",
            type: "i64"
          },
          {
            name: "version",
            type: "u8"
          },
          {
            name: "_padding_1",
            type: {
              array: ["u8", 7]
            }
          },
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "bins",
            type: {
              array: [
                {
                  defined: {
                    name: "Bin"
                  }
                },
                70
              ]
            }
          }
        ]
      }
    },
    {
      name: "BinArrayBitmapExtension",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "positive_bin_array_bitmap",
            docs: [
              "Packed initialized bin array state for start_bin_index is positive"
            ],
            type: {
              array: [
                {
                  array: ["u64", 8]
                },
                12
              ]
            }
          },
          {
            name: "negative_bin_array_bitmap",
            docs: [
              "Packed initialized bin array state for start_bin_index is negative"
            ],
            type: {
              array: [
                {
                  array: ["u64", 8]
                },
                12
              ]
            }
          }
        ]
      }
    },
    {
      name: "BinLimitOrderAmount",
      type: {
        kind: "struct",
        fields: [
          {
            name: "id",
            type: "i32"
          },
          {
            name: "amount",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "BinLiquidityDistribution",
      type: {
        kind: "struct",
        fields: [
          {
            name: "bin_id",
            docs: ["Define the bin ID wish to deposit to."],
            type: "i32"
          },
          {
            name: "distribution_x",
            docs: [
              "DistributionX (or distributionY) is the percentages of amountX (or amountY) you want to add to each bin."
            ],
            type: "u16"
          },
          {
            name: "distribution_y",
            docs: [
              "DistributionX (or distributionY) is the percentages of amountX (or amountY) you want to add to each bin."
            ],
            type: "u16"
          }
        ]
      }
    },
    {
      name: "BinLiquidityDistributionByWeight",
      type: {
        kind: "struct",
        fields: [
          {
            name: "bin_id",
            docs: ["Define the bin ID wish to deposit to."],
            type: "i32"
          },
          {
            name: "weight",
            docs: ["weight of liquidity distributed for this bin id"],
            type: "u16"
          }
        ]
      }
    },
    {
      name: "BinLiquidityReduction",
      type: {
        kind: "struct",
        fields: [
          {
            name: "bin_id",
            type: "i32"
          },
          {
            name: "bps_to_remove",
            type: "u16"
          }
        ]
      }
    },
    {
      name: "CancelLimitOrderEvt",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "from",
            type: "pubkey"
          },
          {
            name: "limit_order",
            type: "pubkey"
          },
          {
            name: "amounts",
            type: {
              array: ["u64", 2]
            }
          },
          {
            name: "active_id",
            type: "i32"
          },
          {
            name: "bins",
            type: {
              vec: "i32"
            }
          }
        ]
      }
    },
    {
      name: "ClaimFee",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "owner",
            type: "pubkey"
          },
          {
            name: "fee_x",
            type: "u64"
          },
          {
            name: "fee_y",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "ClaimFee2",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "owner",
            type: "pubkey"
          },
          {
            name: "fee_x",
            type: "u64"
          },
          {
            name: "fee_y",
            type: "u64"
          },
          {
            name: "active_bin_id",
            type: "i32"
          }
        ]
      }
    },
    {
      name: "ClaimFeeOperator",
      docs: ["Parameter that set by the protocol"],
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "operator",
            docs: ["operator"],
            type: "pubkey"
          },
          {
            name: "_padding",
            docs: ["Reserve"],
            type: {
              array: ["u8", 128]
            }
          }
        ]
      }
    },
    {
      name: "ClaimReward",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "owner",
            type: "pubkey"
          },
          {
            name: "reward_index",
            type: "u64"
          },
          {
            name: "total_reward",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "ClaimReward2",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "owner",
            type: "pubkey"
          },
          {
            name: "reward_index",
            type: "u64"
          },
          {
            name: "total_reward",
            type: "u64"
          },
          {
            name: "active_bin_id",
            type: "i32"
          }
        ]
      }
    },
    {
      name: "CloseLimitOrderEvt",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "owner",
            type: "pubkey"
          },
          {
            name: "limit_order",
            type: "pubkey"
          }
        ]
      }
    },
    {
      name: "CompositionFee",
      type: {
        kind: "struct",
        fields: [
          {
            name: "from",
            type: "pubkey"
          },
          {
            name: "bin_id",
            type: "i16"
          },
          {
            name: "token_x_fee_amount",
            type: "u64"
          },
          {
            name: "token_y_fee_amount",
            type: "u64"
          },
          {
            name: "protocol_token_x_fee_amount",
            type: "u64"
          },
          {
            name: "protocol_token_y_fee_amount",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "CompressedBinDepositAmount",
      type: {
        kind: "struct",
        fields: [
          {
            name: "bin_id",
            type: "i32"
          },
          {
            name: "amount",
            type: "u32"
          }
        ]
      }
    },
    {
      name: "CustomizableParams",
      type: {
        kind: "struct",
        fields: [
          {
            name: "active_id",
            docs: ["Pool price"],
            type: "i32"
          },
          {
            name: "bin_step",
            docs: ["Bin step"],
            type: "u16"
          },
          {
            name: "base_factor",
            docs: ["Base factor"],
            type: "u16"
          },
          {
            name: "activation_type",
            docs: [
              "Activation type. 0 = Slot, 1 = Time. Check ActivationType enum"
            ],
            type: "u8"
          },
          {
            name: "has_alpha_vault",
            docs: ["Whether the pool has an alpha vault"],
            type: "bool"
          },
          {
            name: "activation_point",
            docs: ["Decide when does the pool start trade. None = Now"],
            type: {
              option: "u64"
            }
          },
          {
            name: "creator_pool_on_off_control",
            docs: [
              "Pool creator have permission to enable/disable pool with restricted program validation. Only applicable for customizable permissionless pool."
            ],
            type: "bool"
          },
          {
            name: "base_fee_power_factor",
            docs: ["Base fee power factor"],
            type: "u8"
          },
          {
            name: "concrete_function_type",
            docs: ["Concrete function type"],
            type: "u8"
          },
          {
            name: "collect_fee_mode",
            docs: ["Collect fee mode"],
            type: "u8"
          },
          {
            name: "padding",
            docs: ["Padding, for future use"],
            type: {
              array: ["u8", 60]
            }
          }
        ]
      }
    },
    {
      name: "DecreasePositionLength",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "owner",
            type: "pubkey"
          },
          {
            name: "length_to_remove",
            type: "u16"
          },
          {
            name: "side",
            type: "u8"
          }
        ]
      }
    },
    {
      name: "DummyIx",
      type: {
        kind: "struct",
        fields: [
          {
            name: "_pair_status",
            type: {
              defined: {
                name: "PairStatus"
              }
            }
          },
          {
            name: "_pair_type",
            type: {
              defined: {
                name: "PairType"
              }
            }
          },
          {
            name: "_activation_type",
            type: {
              defined: {
                name: "ActivationType"
              }
            }
          },
          {
            name: "_token_program_flag",
            type: {
              defined: {
                name: "TokenProgramFlags"
              }
            }
          },
          {
            name: "_resize_side",
            type: {
              defined: {
                name: "ResizeSide"
              }
            }
          },
          {
            name: "_rounding",
            type: {
              defined: {
                name: "Rounding"
              }
            }
          }
        ]
      }
    },
    {
      name: "DummyZcAccount",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "position_bin_data",
            type: {
              defined: {
                name: "PositionBinData"
              }
            }
          },
          {
            name: "limit_order_bin_data",
            type: {
              defined: {
                name: "LimitOrderBinData"
              }
            }
          }
        ]
      }
    },
    {
      name: "DynamicFeeParameter",
      type: {
        kind: "struct",
        fields: [
          {
            name: "filter_period",
            docs: [
              "Filter period determine high frequency trading time window."
            ],
            type: "u16"
          },
          {
            name: "decay_period",
            docs: [
              "Decay period determine when the volatile fee start decay / decrease."
            ],
            type: "u16"
          },
          {
            name: "reduction_factor",
            docs: [
              "Reduction factor controls the volatile fee rate decrement rate."
            ],
            type: "u16"
          },
          {
            name: "variable_fee_control",
            docs: [
              "Used to scale the variable fee component depending on the dynamic of the market"
            ],
            type: "u32"
          },
          {
            name: "max_volatility_accumulator",
            docs: [
              "Maximum number of bin crossed can be accumulated. Used to cap volatile fee rate."
            ],
            type: "u32"
          }
        ]
      }
    },
    {
      name: "DynamicFeeParameterUpdate",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "filter_period",
            docs: [
              "Filter period determine high frequency trading time window."
            ],
            type: "u16"
          },
          {
            name: "decay_period",
            docs: [
              "Decay period determine when the volatile fee start decay / decrease."
            ],
            type: "u16"
          },
          {
            name: "reduction_factor",
            docs: [
              "Reduction factor controls the volatile fee rate decrement rate."
            ],
            type: "u16"
          },
          {
            name: "variable_fee_control",
            docs: [
              "Used to scale the variable fee component depending on the dynamic of the market"
            ],
            type: "u32"
          },
          {
            name: "max_volatility_accumulator",
            docs: [
              "Maximum number of bin crossed can be accumulated. Used to cap volatile fee rate."
            ],
            type: "u32"
          }
        ]
      }
    },
    {
      name: "FeeInfo",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "fee_x_per_token_complete",
            type: "u128"
          },
          {
            name: "fee_y_per_token_complete",
            type: "u128"
          },
          {
            name: "fee_x_pending",
            type: "u64"
          },
          {
            name: "fee_y_pending",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "FeeParameterUpdate",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "protocol_share",
            type: "u16"
          },
          {
            name: "base_factor",
            type: "u16"
          },
          {
            name: "base_fee_power_factor",
            type: "u8"
          }
        ]
      }
    },
    {
      name: "FundReward",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "funder",
            type: "pubkey"
          },
          {
            name: "reward_index",
            type: "u64"
          },
          {
            name: "amount",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "GoToABin",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "from_bin_id",
            type: "i32"
          },
          {
            name: "to_bin_id",
            type: "i32"
          }
        ]
      }
    },
    {
      name: "IncreaseObservation",
      type: {
        kind: "struct",
        fields: [
          {
            name: "oracle",
            type: "pubkey"
          },
          {
            name: "new_observation_length",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "IncreasePositionLength",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "owner",
            type: "pubkey"
          },
          {
            name: "length_to_add",
            type: "u16"
          },
          {
            name: "side",
            type: "u8"
          }
        ]
      }
    },
    {
      name: "InitPermissionPairIx",
      type: {
        kind: "struct",
        fields: [
          {
            name: "active_id",
            type: "i32"
          },
          {
            name: "bin_step",
            type: "u16"
          },
          {
            name: "base_factor",
            type: "u16"
          },
          {
            name: "base_fee_power_factor",
            type: "u8"
          },
          {
            name: "activation_type",
            type: "u8"
          },
          {
            name: "padding0",
            type: "u16"
          },
          {
            name: "concrete_function_type",
            type: "u8"
          },
          {
            name: "collect_fee_mode",
            type: "u8"
          }
        ]
      }
    },
    {
      name: "InitPresetParametersIx",
      type: {
        kind: "struct",
        fields: [
          {
            name: "index",
            type: "u16"
          },
          {
            name: "bin_step",
            docs: ["Bin step. Represent the price increment / decrement."],
            type: "u16"
          },
          {
            name: "base_factor",
            docs: [
              "Used for base fee calculation. base_fee_rate = base_factor * bin_step * 10 * 10^base_fee_power_factor"
            ],
            type: "u16"
          },
          {
            name: "filter_period",
            docs: [
              "Filter period determine high frequency trading time window."
            ],
            type: "u16"
          },
          {
            name: "decay_period",
            docs: [
              "Decay period determine when the volatile fee start decay / decrease."
            ],
            type: "u16"
          },
          {
            name: "reduction_factor",
            docs: [
              "Reduction factor controls the volatile fee rate decrement rate."
            ],
            type: "u16"
          },
          {
            name: "variable_fee_control",
            docs: [
              "Used to scale the variable fee component depending on the dynamic of the market"
            ],
            type: "u32"
          },
          {
            name: "max_volatility_accumulator",
            docs: [
              "Maximum number of bin crossed can be accumulated. Used to cap volatile fee rate."
            ],
            type: "u32"
          },
          {
            name: "protocol_share",
            docs: [
              "Portion of swap fees retained by the protocol by controlling protocol_share parameter. protocol_swap_fee = protocol_share * total_swap_fee"
            ],
            type: "u16"
          },
          {
            name: "base_fee_power_factor",
            docs: ["Base fee power factor"],
            type: "u8"
          },
          {
            name: "concrete_function_type",
            docs: ["function type"],
            type: "u8"
          },
          {
            name: "collect_fee_mode",
            docs: ["collect fee mode"],
            type: "u8"
          }
        ]
      }
    },
    {
      name: "InitializeLbPair2Params",
      type: {
        kind: "struct",
        fields: [
          {
            name: "active_id",
            docs: ["Pool price"],
            type: "i32"
          },
          {
            name: "padding",
            docs: ["Padding, for future use"],
            type: {
              array: ["u8", 96]
            }
          }
        ]
      }
    },
    {
      name: "InitializeReward",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "reward_mint",
            type: "pubkey"
          },
          {
            name: "funder",
            type: "pubkey"
          },
          {
            name: "reward_index",
            type: "u64"
          },
          {
            name: "reward_duration",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "LbPair",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "parameters",
            type: {
              defined: {
                name: "StaticParameters"
              }
            }
          },
          {
            name: "v_parameters",
            type: {
              defined: {
                name: "VariableParameters"
              }
            }
          },
          {
            name: "bump_seed",
            type: {
              array: ["u8", 1]
            }
          },
          {
            name: "bin_step_seed",
            docs: ["Bin step signer seed"],
            type: {
              array: ["u8", 2]
            }
          },
          {
            name: "pair_type",
            docs: ["Type of the pair"],
            type: "u8"
          },
          {
            name: "active_id",
            docs: ["Active bin id"],
            type: "i32"
          },
          {
            name: "bin_step",
            docs: ["Bin step. Represent the price increment / decrement."],
            type: "u16"
          },
          {
            name: "status",
            docs: ["Status of the pair. Check PairStatus enum."],
            type: "u8"
          },
          {
            name: "require_base_factor_seed",
            docs: ["Require base factor seed"],
            type: "u8"
          },
          {
            name: "base_factor_seed",
            docs: ["Base factor seed"],
            type: {
              array: ["u8", 2]
            }
          },
          {
            name: "activation_type",
            docs: ["Activation type"],
            type: "u8"
          },
          {
            name: "creator_pool_on_off_control",
            docs: [
              "Allow pool creator to enable/disable pool with restricted validation. Only applicable for customizable permissionless pair type."
            ],
            type: "u8"
          },
          {
            name: "token_x_mint",
            docs: ["Token X mint"],
            type: "pubkey"
          },
          {
            name: "token_y_mint",
            docs: ["Token Y mint"],
            type: "pubkey"
          },
          {
            name: "reserve_x",
            docs: ["LB token X vault"],
            type: "pubkey"
          },
          {
            name: "reserve_y",
            docs: ["LB token Y vault"],
            type: "pubkey"
          },
          {
            name: "protocol_fee",
            docs: ["Uncollected protocol fee"],
            type: {
              defined: {
                name: "ProtocolFee"
              }
            }
          },
          {
            name: "_padding_1",
            docs: ["padding 1"],
            type: {
              array: ["u8", 32]
            }
          },
          {
            name: "reward_infos",
            docs: ["Farming reward information"],
            type: {
              array: [
                {
                  defined: {
                    name: "RewardInfo"
                  }
                },
                2
              ]
            }
          },
          {
            name: "oracle",
            docs: ["Oracle pubkey"],
            type: "pubkey"
          },
          {
            name: "bin_array_bitmap",
            docs: ["Packed initialized bin array state"],
            type: {
              array: ["u64", 16]
            }
          },
          {
            name: "last_updated_at",
            docs: ["Last time the pool fee parameter was updated"],
            type: "i64"
          },
          {
            name: "_padding_2",
            docs: ["_padding_2"],
            type: {
              array: ["u8", 32]
            }
          },
          {
            name: "pre_activation_swap_address",
            docs: [
              "Address allowed to swap when the current point is greater than or equal to the pre-activation point. The pre-activation point is calculated as `activation_point - pre_activation_duration`."
            ],
            type: "pubkey"
          },
          {
            name: "base_key",
            docs: ["Base keypair. Only required for permission pair"],
            type: "pubkey"
          },
          {
            name: "activation_point",
            docs: [
              "Time point to enable the pair. Only applicable for permission pair."
            ],
            type: "u64"
          },
          {
            name: "pre_activation_duration",
            docs: [
              "Duration before activation activation_point. Used to calculate pre-activation time point for pre_activation_swap_address"
            ],
            type: "u64"
          },
          {
            name: "_padding_3",
            docs: ["_padding 3"],
            type: {
              array: ["u8", 8]
            }
          },
          {
            name: "_padding_4",
            docs: ["_padding_4"],
            type: "u64"
          },
          {
            name: "creator",
            docs: ["Pool creator"],
            type: "pubkey"
          },
          {
            name: "token_mint_x_program_flag",
            docs: ["token_mint_x_program_flag"],
            type: "u8"
          },
          {
            name: "token_mint_y_program_flag",
            docs: ["token_mint_y_program_flag"],
            type: "u8"
          },
          {
            name: "version",
            docs: ["version to know whether we have reset tombstone fields"],
            type: "u8"
          },
          {
            name: "_reserved",
            docs: ["Reserved space for future use"],
            type: {
              array: ["u8", 21]
            }
          }
        ]
      }
    },
    {
      name: "LbPairCreate",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "bin_step",
            type: "u16"
          },
          {
            name: "token_x",
            type: "pubkey"
          },
          {
            name: "token_y",
            type: "pubkey"
          }
        ]
      }
    },
    {
      name: "LimitOrder",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            docs: ["The LB pair of this LO"],
            type: "pubkey"
          },
          {
            name: "owner",
            docs: [
              "Owner of the LO. Client rely on this to to fetch their LOs."
            ],
            type: "pubkey"
          },
          {
            name: "bin_count",
            docs: ["Bin count"],
            type: "u16"
          },
          {
            name: "_padding_0",
            docs: ["Padding"],
            type: {
              array: ["u8", 14]
            }
          },
          {
            name: "padding_1",
            docs: ["Reserved space for future use"],
            type: {
              array: ["u64", 4]
            }
          }
        ]
      }
    },
    {
      name: "LimitOrderBinData",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "amount",
            type: "u64"
          },
          {
            name: "age",
            type: "u32"
          },
          {
            name: "_padding_0",
            type: {
              array: ["u8", 4]
            }
          },
          {
            name: "bin_id",
            type: "i32"
          },
          {
            name: "is_ask",
            type: "u8"
          },
          {
            name: "_padding_1",
            type: {
              array: ["u8", 11]
            }
          }
        ]
      }
    },
    {
      name: "LiquidityOneSideParameter",
      type: {
        kind: "struct",
        fields: [
          {
            name: "amount",
            docs: ["Amount of X token or Y token to deposit"],
            type: "u64"
          },
          {
            name: "active_id",
            docs: ["Active bin that integrator observe off-chain"],
            type: "i32"
          },
          {
            name: "max_active_bin_slippage",
            docs: ["max active bin slippage allowed"],
            type: "i32"
          },
          {
            name: "bin_liquidity_dist",
            docs: ["Liquidity distribution to each bins"],
            type: {
              vec: {
                defined: {
                  name: "BinLiquidityDistributionByWeight"
                }
              }
            }
          }
        ]
      }
    },
    {
      name: "LiquidityParameter",
      type: {
        kind: "struct",
        fields: [
          {
            name: "amount_x",
            docs: ["Amount of X token to deposit"],
            type: "u64"
          },
          {
            name: "amount_y",
            docs: ["Amount of Y token to deposit"],
            type: "u64"
          },
          {
            name: "bin_liquidity_dist",
            docs: ["Liquidity distribution to each bins"],
            type: {
              vec: {
                defined: {
                  name: "BinLiquidityDistribution"
                }
              }
            }
          }
        ]
      }
    },
    {
      name: "LiquidityParameterByStrategy",
      type: {
        kind: "struct",
        fields: [
          {
            name: "amount_x",
            docs: ["Amount of X token to deposit"],
            type: "u64"
          },
          {
            name: "amount_y",
            docs: ["Amount of Y token to deposit"],
            type: "u64"
          },
          {
            name: "active_id",
            docs: ["Active bin that integrator observe off-chain"],
            type: "i32"
          },
          {
            name: "max_active_bin_slippage",
            docs: ["max active bin slippage allowed"],
            type: "i32"
          },
          {
            name: "strategy_parameters",
            docs: ["strategy parameters"],
            type: {
              defined: {
                name: "StrategyParameters"
              }
            }
          }
        ]
      }
    },
    {
      name: "LiquidityParameterByStrategyOneSide",
      type: {
        kind: "struct",
        fields: [
          {
            name: "amount",
            docs: ["Amount of X token or Y token to deposit"],
            type: "u64"
          },
          {
            name: "active_id",
            docs: ["Active bin that integrator observe off-chain"],
            type: "i32"
          },
          {
            name: "max_active_bin_slippage",
            docs: ["max active bin slippage allowed"],
            type: "i32"
          },
          {
            name: "strategy_parameters",
            docs: ["strategy parameters"],
            type: {
              defined: {
                name: "StrategyParameters"
              }
            }
          }
        ]
      }
    },
    {
      name: "LiquidityParameterByWeight",
      type: {
        kind: "struct",
        fields: [
          {
            name: "amount_x",
            docs: ["Amount of X token to deposit"],
            type: "u64"
          },
          {
            name: "amount_y",
            docs: ["Amount of Y token to deposit"],
            type: "u64"
          },
          {
            name: "active_id",
            docs: ["Active bin that integrator observe off-chain"],
            type: "i32"
          },
          {
            name: "max_active_bin_slippage",
            docs: ["max active bin slippage allowed"],
            type: "i32"
          },
          {
            name: "bin_liquidity_dist",
            docs: ["Liquidity distribution to each bins"],
            type: {
              vec: {
                defined: {
                  name: "BinLiquidityDistributionByWeight"
                }
              }
            }
          }
        ]
      }
    },
    {
      name: "Operator",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "signer",
            type: "pubkey"
          },
          {
            name: "permission",
            type: "u128"
          },
          {
            name: "padding",
            type: {
              array: ["u64", 2]
            }
          }
        ]
      }
    },
    {
      name: "Oracle",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "idx",
            docs: ["Index of latest observation"],
            type: "u64"
          },
          {
            name: "active_size",
            docs: [
              "Size of active sample. Active sample is initialized observation."
            ],
            type: "u64"
          },
          {
            name: "length",
            docs: ["Number of observations"],
            type: "u64"
          }
        ]
      }
    },
    {
      name: "PairStatus",
      docs: [
        "Pair status. 0 = Enabled, 1 = Disabled. Putting 0 as enabled for backward compatibility."
      ],
      repr: {
        kind: "rust"
      },
      type: {
        kind: "enum",
        variants: [
          {
            name: "Enabled"
          },
          {
            name: "Disabled"
          }
        ]
      }
    },
    {
      name: "PairType",
      docs: [
        "Type of the Pair. 0 = Permissionless, 1 = Permission, 2 = CustomizablePermissionless. Putting 0 as permissionless for backward compatibility."
      ],
      repr: {
        kind: "rust"
      },
      type: {
        kind: "enum",
        variants: [
          {
            name: "Permissionless"
          },
          {
            name: "Permission"
          },
          {
            name: "CustomizablePermissionless"
          },
          {
            name: "PermissionlessV2"
          }
        ]
      }
    },
    {
      name: "PlaceLimitOrderEvt",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "sender",
            type: "pubkey"
          },
          {
            name: "owner",
            type: "pubkey"
          },
          {
            name: "limit_order",
            type: "pubkey"
          },
          {
            name: "active_id",
            type: "i32"
          },
          {
            name: "params",
            type: {
              defined: {
                name: "PlaceLimitOrderParams"
              }
            }
          }
        ]
      }
    },
    {
      name: "PlaceLimitOrderParams",
      type: {
        kind: "struct",
        fields: [
          {
            name: "is_ask_side",
            type: "bool"
          },
          {
            name: "padding",
            type: {
              array: ["u8", 16]
            }
          },
          {
            name: "relative_bin",
            type: {
              option: {
                defined: {
                  name: "RelativeBin"
                }
              }
            }
          },
          {
            name: "bins",
            type: {
              vec: {
                defined: {
                  name: "BinLimitOrderAmount"
                }
              }
            }
          }
        ]
      }
    },
    {
      name: "PositionBinData",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "liquidity_share",
            type: "u128"
          },
          {
            name: "reward_info",
            type: {
              defined: {
                name: "UserRewardInfo"
              }
            }
          },
          {
            name: "fee_info",
            type: {
              defined: {
                name: "FeeInfo"
              }
            }
          }
        ]
      }
    },
    {
      name: "PositionClose",
      type: {
        kind: "struct",
        fields: [
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "owner",
            type: "pubkey"
          }
        ]
      }
    },
    {
      name: "PositionCreate",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "owner",
            type: "pubkey"
          }
        ]
      }
    },
    {
      name: "PositionV2",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            docs: ["The LB pair of this position"],
            type: "pubkey"
          },
          {
            name: "owner",
            docs: [
              "Owner of the position. Client rely on this to to fetch their positions."
            ],
            type: "pubkey"
          },
          {
            name: "liquidity_shares",
            docs: [
              "Liquidity shares of this position in bins (lower_bin_id <-> upper_bin_id). This is the same as LP concept."
            ],
            type: {
              array: ["u128", 70]
            }
          },
          {
            name: "reward_infos",
            docs: ["Farming reward information"],
            type: {
              array: [
                {
                  defined: {
                    name: "UserRewardInfo"
                  }
                },
                70
              ]
            }
          },
          {
            name: "fee_infos",
            docs: ["Swap fee to claim information"],
            type: {
              array: [
                {
                  defined: {
                    name: "FeeInfo"
                  }
                },
                70
              ]
            }
          },
          {
            name: "lower_bin_id",
            docs: ["Lower bin ID"],
            type: "i32"
          },
          {
            name: "upper_bin_id",
            docs: ["Upper bin ID"],
            type: "i32"
          },
          {
            name: "last_updated_at",
            docs: ["Last updated timestamp"],
            type: "i64"
          },
          {
            name: "total_claimed_fee_x_amount",
            docs: ["Total claimed token fee X"],
            type: "u64"
          },
          {
            name: "total_claimed_fee_y_amount",
            docs: ["Total claimed token fee Y"],
            type: "u64"
          },
          {
            name: "total_claimed_rewards",
            docs: ["Total claimed rewards"],
            type: {
              array: ["u64", 2]
            }
          },
          {
            name: "operator",
            docs: ["Operator of position"],
            type: "pubkey"
          },
          {
            name: "lock_release_point",
            docs: ["Time point which the locked liquidity can be withdraw"],
            type: "u64"
          },
          {
            name: "_padding_0",
            docs: [
              "_padding_0, previous subjected_to_bootstrap_liquidity_locking, BE CAREFUL FOR TOMBSTONE WHEN REUSE !!"
            ],
            type: "u8"
          },
          {
            name: "fee_owner",
            docs: [
              "Address is able to claim fee in this position, only valid for bootstrap_liquidity_position"
            ],
            type: "pubkey"
          },
          {
            name: "version",
            docs: ["version to know whether we have reset tombstone fields"],
            type: "u8"
          },
          {
            name: "permissionless_operation_bits",
            type: "u8"
          },
          {
            name: "_reserved",
            docs: ["Reserved space for future use"],
            type: {
              array: ["u8", 85]
            }
          }
        ]
      }
    },
    {
      name: "PresetParameter",
      type: {
        kind: "struct",
        fields: [
          {
            name: "bin_step",
            docs: ["Bin step. Represent the price increment / decrement."],
            type: "u16"
          },
          {
            name: "base_factor",
            docs: [
              "Used for base fee calculation. base_fee_rate = base_factor * bin_step * 10 * 10^base_fee_power_factor"
            ],
            type: "u16"
          },
          {
            name: "filter_period",
            docs: [
              "Filter period determine high frequency trading time window."
            ],
            type: "u16"
          },
          {
            name: "decay_period",
            docs: [
              "Decay period determine when the volatile fee start decay / decrease."
            ],
            type: "u16"
          },
          {
            name: "reduction_factor",
            docs: [
              "Reduction factor controls the volatile fee rate decrement rate."
            ],
            type: "u16"
          },
          {
            name: "variable_fee_control",
            docs: [
              "Used to scale the variable fee component depending on the dynamic of the market"
            ],
            type: "u32"
          },
          {
            name: "max_volatility_accumulator",
            docs: [
              "Maximum number of bin crossed can be accumulated. Used to cap volatile fee rate."
            ],
            type: "u32"
          },
          {
            name: "min_bin_id",
            docs: [
              "Min bin id supported by the pool based on the configured bin step."
            ],
            type: "i32"
          },
          {
            name: "max_bin_id",
            docs: [
              "Max bin id supported by the pool based on the configured bin step."
            ],
            type: "i32"
          },
          {
            name: "protocol_share",
            docs: [
              "Portion of swap fees retained by the protocol by controlling protocol_share parameter. protocol_swap_fee = protocol_share * total_swap_fee"
            ],
            type: "u16"
          }
        ]
      }
    },
    {
      name: "PresetParameter2",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "bin_step",
            docs: ["Bin step. Represent the price increment / decrement."],
            type: "u16"
          },
          {
            name: "base_factor",
            docs: [
              "Used for base fee calculation. base_fee_rate = base_factor * bin_step * 10 * 10^base_fee_power_factor"
            ],
            type: "u16"
          },
          {
            name: "filter_period",
            docs: [
              "Filter period determine high frequency trading time window."
            ],
            type: "u16"
          },
          {
            name: "decay_period",
            docs: [
              "Decay period determine when the volatile fee start decay / decrease."
            ],
            type: "u16"
          },
          {
            name: "variable_fee_control",
            docs: [
              "Used to scale the variable fee component depending on the dynamic of the market"
            ],
            type: "u32"
          },
          {
            name: "max_volatility_accumulator",
            docs: [
              "Maximum number of bin crossed can be accumulated. Used to cap volatile fee rate."
            ],
            type: "u32"
          },
          {
            name: "reduction_factor",
            docs: [
              "Reduction factor controls the volatile fee rate decrement rate."
            ],
            type: "u16"
          },
          {
            name: "protocol_share",
            docs: [
              "Portion of swap fees retained by the protocol by controlling protocol_share parameter. protocol_swap_fee = protocol_share * total_swap_fee"
            ],
            type: "u16"
          },
          {
            name: "index",
            docs: ["index"],
            type: "u16"
          },
          {
            name: "base_fee_power_factor",
            docs: ["Base fee power factor"],
            type: "u8"
          },
          {
            name: "concrete_function_type",
            docs: [
              "function type, to check whether the pool should have LM farming or other functions in the future, refer ConcreteFunctionType"
            ],
            type: "u8"
          },
          {
            name: "collect_fee_mode",
            docs: ["collect fee mode"],
            type: "u8"
          },
          {
            name: "padding_0",
            type: {
              array: ["u8", 7]
            }
          },
          {
            name: "padding_1",
            docs: ["Padding 1 for future use"],
            type: {
              array: ["u64", 19]
            }
          }
        ]
      }
    },
    {
      name: "ProtocolFee",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "amount_x",
            type: "u64"
          },
          {
            name: "amount_y",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "RebalanceLiquidityParams",
      type: {
        kind: "struct",
        fields: [
          {
            name: "active_id",
            docs: ["active id"],
            type: "i32"
          },
          {
            name: "max_active_bin_slippage",
            docs: ["max active bin slippage allowed"],
            type: "u16"
          },
          {
            name: "should_claim_fee",
            docs: ["a flag to indicate that whether fee should be harvested"],
            type: "bool"
          },
          {
            name: "should_claim_reward",
            docs: [
              "a flag to indicate that whether rewards should be harvested"
            ],
            type: "bool"
          },
          {
            name: "min_withdraw_x_amount",
            docs: ["threshold for withdraw token x"],
            type: "u64"
          },
          {
            name: "max_deposit_x_amount",
            docs: ["threshold for deposit token x"],
            type: "u64"
          },
          {
            name: "min_withdraw_y_amount",
            docs: ["threshold for withdraw token y"],
            type: "u64"
          },
          {
            name: "max_deposit_y_amount",
            docs: ["threshold for deposit token y"],
            type: "u64"
          },
          {
            name: "shrink_mode",
            docs: ["shrink mode"],
            type: "u8"
          },
          {
            name: "padding",
            docs: ["padding 32 bytes for future usage"],
            type: {
              array: ["u8", 31]
            }
          },
          {
            name: "removes",
            docs: ["removes"],
            type: {
              vec: {
                defined: {
                  name: "RemoveLiquidityParams"
                }
              }
            }
          },
          {
            name: "adds",
            docs: ["adds"],
            type: {
              vec: {
                defined: {
                  name: "AddLiquidityParams"
                }
              }
            }
          }
        ]
      }
    },
    {
      name: "Rebalancing",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "owner",
            type: "pubkey"
          },
          {
            name: "active_bin_id",
            type: "i32"
          },
          {
            name: "x_withdrawn_amount",
            type: "u64"
          },
          {
            name: "x_added_amount",
            type: "u64"
          },
          {
            name: "y_withdrawn_amount",
            type: "u64"
          },
          {
            name: "y_added_amount",
            type: "u64"
          },
          {
            name: "x_fee_amount",
            type: "u64"
          },
          {
            name: "y_fee_amount",
            type: "u64"
          },
          {
            name: "old_min_id",
            type: "i32"
          },
          {
            name: "old_max_id",
            type: "i32"
          },
          {
            name: "new_min_id",
            type: "i32"
          },
          {
            name: "new_max_id",
            type: "i32"
          },
          {
            name: "rewards",
            type: {
              array: ["u64", 2]
            }
          }
        ]
      }
    },
    {
      name: "RelativeBin",
      type: {
        kind: "struct",
        fields: [
          {
            name: "active_id",
            docs: ["Active bin that integrator observe off-chain"],
            type: "i32"
          },
          {
            name: "max_active_bin_slippage",
            docs: ["max active bin slippage allowed"],
            type: "i32"
          }
        ]
      }
    },
    {
      name: "RemainingAccountsInfo",
      type: {
        kind: "struct",
        fields: [
          {
            name: "slices",
            type: {
              vec: {
                defined: {
                  name: "RemainingAccountsSlice"
                }
              }
            }
          }
        ]
      }
    },
    {
      name: "RemainingAccountsSlice",
      type: {
        kind: "struct",
        fields: [
          {
            name: "accounts_type",
            type: {
              defined: {
                name: "AccountsType"
              }
            }
          },
          {
            name: "length",
            type: "u8"
          }
        ]
      }
    },
    {
      name: "RemoveLiquidity",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "from",
            type: "pubkey"
          },
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "amounts",
            type: {
              array: ["u64", 2]
            }
          },
          {
            name: "active_bin_id",
            type: "i32"
          }
        ]
      }
    },
    {
      name: "RemoveLiquidityParams",
      type: {
        kind: "struct",
        fields: [
          {
            name: "min_bin_id",
            type: {
              option: "i32"
            }
          },
          {
            name: "max_bin_id",
            type: {
              option: "i32"
            }
          },
          {
            name: "bps",
            type: "u16"
          },
          {
            name: "padding",
            type: {
              array: ["u8", 16]
            }
          }
        ]
      }
    },
    {
      name: "ResizeSide",
      docs: ["Side of resize, 0 for lower and 1 for upper"],
      repr: {
        kind: "rust"
      },
      type: {
        kind: "enum",
        variants: [
          {
            name: "Lower"
          },
          {
            name: "Upper"
          }
        ]
      }
    },
    {
      name: "RewardInfo",
      docs: [
        "Stores the state relevant for tracking liquidity mining rewards"
      ],
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "mint",
            docs: ["Reward token mint."],
            type: "pubkey"
          },
          {
            name: "vault",
            docs: ["Reward vault token account."],
            type: "pubkey"
          },
          {
            name: "funder",
            docs: ["Authority account that allows to fund rewards"],
            type: "pubkey"
          },
          {
            name: "reward_duration",
            docs: ["LM reward duration in seconds."],
            type: "u64"
          },
          {
            name: "reward_duration_end",
            docs: ["LM reward duration end time."],
            type: "u64"
          },
          {
            name: "reward_rate",
            docs: ["LM reward rate"],
            type: "u128"
          },
          {
            name: "last_update_time",
            docs: ["The last time reward states were updated."],
            type: "u64"
          },
          {
            name: "cumulative_seconds_with_empty_liquidity_reward",
            docs: [
              "Accumulated seconds where when farm distribute rewards, but the bin is empty. The reward will be accumulated for next reward time window."
            ],
            type: "u64"
          }
        ]
      }
    },
    {
      name: "Rounding",
      type: {
        kind: "enum",
        variants: [
          {
            name: "Up"
          },
          {
            name: "Down"
          }
        ]
      }
    },
    {
      name: "SetPositionPermissionlessOperationBitsEvt",
      type: {
        kind: "struct",
        fields: [
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "owner",
            type: "pubkey"
          },
          {
            name: "old_bits",
            type: "u8"
          },
          {
            name: "new_bits",
            type: "u8"
          }
        ]
      }
    },
    {
      name: "StaticParameters",
      docs: ["Parameter that set by the protocol"],
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "base_factor",
            docs: [
              "Used for base fee calculation. base_fee_rate = base_factor * bin_step * 10 * 10^base_fee_power_factor"
            ],
            type: "u16"
          },
          {
            name: "filter_period",
            docs: [
              "Filter period determine high frequency trading time window."
            ],
            type: "u16"
          },
          {
            name: "decay_period",
            docs: [
              "Decay period determine when the volatile fee start decay / decrease."
            ],
            type: "u16"
          },
          {
            name: "reduction_factor",
            docs: [
              "Reduction factor controls the volatile fee rate decrement rate."
            ],
            type: "u16"
          },
          {
            name: "variable_fee_control",
            docs: [
              "Used to scale the variable fee component depending on the dynamic of the market"
            ],
            type: "u32"
          },
          {
            name: "max_volatility_accumulator",
            docs: [
              "Maximum number of bin crossed can be accumulated. Used to cap volatile fee rate."
            ],
            type: "u32"
          },
          {
            name: "min_bin_id",
            docs: [
              "Min bin id supported by the pool based on the configured bin step."
            ],
            type: "i32"
          },
          {
            name: "max_bin_id",
            docs: [
              "Max bin id supported by the pool based on the configured bin step."
            ],
            type: "i32"
          },
          {
            name: "protocol_share",
            docs: [
              "Portion of swap fees retained by the protocol by controlling protocol_share parameter. protocol_swap_fee = protocol_share * total_swap_fee"
            ],
            type: "u16"
          },
          {
            name: "base_fee_power_factor",
            docs: ["Base fee power factor"],
            type: "u8"
          },
          {
            name: "function_type",
            docs: ["function type"],
            type: "u8"
          },
          {
            name: "collect_fee_mode",
            docs: ["Collect fee mode"],
            type: "u8"
          },
          {
            name: "_padding",
            docs: ["Padding for bytemuck safe alignment"],
            type: {
              array: ["u8", 3]
            }
          }
        ]
      }
    },
    {
      name: "StrategyParameters",
      type: {
        kind: "struct",
        fields: [
          {
            name: "min_bin_id",
            docs: ["min bin id"],
            type: "i32"
          },
          {
            name: "max_bin_id",
            docs: ["max bin id"],
            type: "i32"
          },
          {
            name: "strategy_type",
            docs: ["strategy type"],
            type: {
              defined: {
                name: "StrategyType"
              }
            }
          },
          {
            name: "parameteres",
            docs: ["parameters"],
            type: {
              array: ["u8", 64]
            }
          }
        ]
      }
    },
    {
      name: "StrategyType",
      type: {
        kind: "enum",
        variants: [
          {
            name: "SpotOneSide"
          },
          {
            name: "CurveOneSide"
          },
          {
            name: "BidAskOneSide"
          },
          {
            name: "SpotBalanced"
          },
          {
            name: "CurveBalanced"
          },
          {
            name: "BidAskBalanced"
          },
          {
            name: "SpotImBalanced"
          },
          {
            name: "CurveImBalanced"
          },
          {
            name: "BidAskImBalanced"
          }
        ]
      }
    },
    {
      name: "Swap",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "from",
            type: "pubkey"
          },
          {
            name: "start_bin_id",
            type: "i32"
          },
          {
            name: "end_bin_id",
            type: "i32"
          },
          {
            name: "amount_in",
            type: "u64"
          },
          {
            name: "amount_out",
            type: "u64"
          },
          {
            name: "swap_for_y",
            type: "bool"
          },
          {
            name: "fee",
            type: "u64"
          },
          {
            name: "protocol_fee",
            type: "u64"
          },
          {
            name: "fee_bps",
            type: "u128"
          },
          {
            name: "host_fee",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "Swap2Evt",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "from",
            type: "pubkey"
          },
          {
            name: "start_bin_id",
            type: "i32"
          },
          {
            name: "end_bin_id",
            type: "i32"
          },
          {
            name: "swap_for_y",
            type: "bool"
          },
          {
            name: "fee_bps",
            type: "u128"
          },
          {
            name: "amount_in",
            docs: ["Total amount, user transfer out"],
            type: "u64"
          },
          {
            name: "amount_left",
            docs: ["Leftover amount"],
            type: "u64"
          },
          {
            name: "amount_out",
            docs: ["Total amount transfer to user, including transfer fee"],
            type: "u64"
          },
          {
            name: "mm_fee",
            docs: ["Market maker fee"],
            type: "u64"
          },
          {
            name: "protocol_fee",
            docs: ["Total protocol fee"],
            type: "u64"
          },
          {
            name: "limit_order_fee",
            docs: ["Total limit order fee"],
            type: "u64"
          },
          {
            name: "host_fee",
            docs: ["Total host fee"],
            type: "u64"
          },
          {
            name: "fees_on_input",
            docs: ["check if fees on input"],
            type: "bool"
          },
          {
            name: "fees_on_token_x",
            docs: ["check if fees is on token x"],
            type: "bool"
          }
        ]
      }
    },
    {
      name: "TokenBadge",
      docs: ["Parameter that set by the protocol"],
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "token_mint",
            docs: ["token mint"],
            type: "pubkey"
          },
          {
            name: "_padding",
            docs: ["Reserve"],
            type: {
              array: ["u8", 128]
            }
          }
        ]
      }
    },
    {
      name: "TokenProgramFlags",
      repr: {
        kind: "rust"
      },
      type: {
        kind: "enum",
        variants: [
          {
            name: "TokenProgram"
          },
          {
            name: "TokenProgram2022"
          }
        ]
      }
    },
    {
      name: "UpdatePositionLockReleasePoint",
      type: {
        kind: "struct",
        fields: [
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "current_point",
            type: "u64"
          },
          {
            name: "new_lock_release_point",
            type: "u64"
          },
          {
            name: "old_lock_release_point",
            type: "u64"
          },
          {
            name: "sender",
            type: "pubkey"
          }
        ]
      }
    },
    {
      name: "UpdatePositionOperator",
      type: {
        kind: "struct",
        fields: [
          {
            name: "position",
            type: "pubkey"
          },
          {
            name: "old_operator",
            type: "pubkey"
          },
          {
            name: "new_operator",
            type: "pubkey"
          }
        ]
      }
    },
    {
      name: "UpdateRewardDuration",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "reward_index",
            type: "u64"
          },
          {
            name: "old_reward_duration",
            type: "u64"
          },
          {
            name: "new_reward_duration",
            type: "u64"
          }
        ]
      }
    },
    {
      name: "UpdateRewardFunder",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "reward_index",
            type: "u64"
          },
          {
            name: "old_funder",
            type: "pubkey"
          },
          {
            name: "new_funder",
            type: "pubkey"
          }
        ]
      }
    },
    {
      name: "UserRewardInfo",
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "reward_per_token_completes",
            type: {
              array: ["u128", 2]
            }
          },
          {
            name: "reward_pendings",
            type: {
              array: ["u64", 2]
            }
          }
        ]
      }
    },
    {
      name: "VariableParameters",
      docs: ["Parameters that changes based on dynamic of the market"],
      serialization: "bytemuck",
      repr: {
        kind: "c"
      },
      type: {
        kind: "struct",
        fields: [
          {
            name: "volatility_accumulator",
            docs: [
              "Volatility accumulator measure the number of bin crossed since reference bin ID. Normally (without filter period taken into consideration), reference bin ID is the active bin of last swap.",
              "It affects the variable fee rate"
            ],
            type: "u32"
          },
          {
            name: "volatility_reference",
            docs: [
              "Volatility reference is decayed volatility accumulator. It is always <= volatility_accumulator"
            ],
            type: "u32"
          },
          {
            name: "index_reference",
            docs: ["Active bin id of last swap."],
            type: "i32"
          },
          {
            name: "_padding",
            docs: ["Padding for bytemuck safe alignment"],
            type: {
              array: ["u8", 4]
            }
          },
          {
            name: "last_update_timestamp",
            docs: ["Last timestamp the variable parameters was updated"],
            type: "i64"
          },
          {
            name: "_padding_1",
            docs: ["Padding for bytemuck safe alignment"],
            type: {
              array: ["u8", 8]
            }
          }
        ]
      }
    },
    {
      name: "WithdrawIneligibleReward",
      type: {
        kind: "struct",
        fields: [
          {
            name: "lb_pair",
            type: "pubkey"
          },
          {
            name: "reward_mint",
            type: "pubkey"
          },
          {
            name: "amount",
            type: "u64"
          }
        ]
      }
    }
  ],
  constants: [
    {
      name: "BASIS_POINT_MAX",
      type: "u16",
      value: "10000"
    },
    {
      name: "BIN_ARRAY",
      type: "bytes",
      value: "[98, 105, 110, 95, 97, 114, 114, 97, 121]"
    },
    {
      name: "BIN_ARRAY_BITMAP_SEED",
      type: "bytes",
      value: "[98, 105, 116, 109, 97, 112]"
    },
    {
      name: "BIN_ARRAY_BITMAP_SIZE",
      type: "i32",
      value: "512"
    },
    {
      name: "CLAIM_PROTOCOL_FEE_OPERATOR",
      type: "bytes",
      value: "[99, 102, 95, 111, 112, 101, 114, 97, 116, 111, 114]"
    },
    {
      name: "DEFAULT_BIN_PER_POSITION",
      type: "u64",
      value: "70"
    },
    {
      name: "EXTENSION_BINARRAY_BITMAP_SIZE",
      type: "u64",
      value: "12"
    },
    {
      name: "FEE_DENOMINATOR",
      type: "u64",
      value: "1000000000"
    },
    {
      name: "HOST_FEE_BPS",
      docs: ["Host fee. 20%"],
      type: "u16",
      value: "2000"
    },
    {
      name: "ILM_PROTOCOL_SHARE",
      type: "u16",
      value: "2000"
    },
    {
      name: "LIMIT_ORDER_FEE_SHARE",
      type: "u16",
      value: "5000"
    },
    {
      name: "MAX_BASE_FEE",
      docs: ["Maximum base fee, base_fee / 10^9 = fee_in_percentage"],
      type: "u128",
      value: "100000000"
    },
    {
      name: "MAX_BIN_ID_PER_BIN_STEP",
      docs: [
        "Maximum bin ID per bin step. Computed based on 1 bps. Used for bin id bound estimation."
      ],
      type: "i32",
      value: "351639"
    },
    {
      name: "MAX_BIN_PER_ARRAY",
      type: "u64",
      value: "70"
    },
    {
      name: "MAX_BIN_PER_LIMIT_ORDER",
      type: "u64",
      value: "50"
    },
    {
      name: "MAX_BIN_STEP",
      docs: ["Maximum bin step"],
      type: "u16",
      value: "400"
    },
    {
      name: "MAX_FEE_RATE",
      docs: ["Maximum fee rate. 10%"],
      type: "u64",
      value: "100000000"
    },
    {
      name: "MAX_PROTOCOL_SHARE",
      docs: ["Maximum protocol share of the fee. 25%"],
      type: "u16",
      value: "2500"
    },
    {
      name: "MAX_RESIZE_LENGTH",
      type: "u64",
      value: "91"
    },
    {
      name: "MAX_REWARD_BIN_SPLIT",
      type: "u64",
      value: "15"
    },
    {
      name: "MAX_REWARD_DURATION",
      type: "u64",
      value: "31536000"
    },
    {
      name: "MINIMUM_LIQUIDITY",
      type: "u128",
      value: "1000000"
    },
    {
      name: "MIN_BASE_FEE",
      docs: ["Minimum base fee"],
      type: "u128",
      value: "100000"
    },
    {
      name: "MIN_REWARD_DURATION",
      type: "u64",
      value: "1"
    },
    {
      name: "NUM_REWARDS",
      type: "u64",
      value: "2"
    },
    {
      name: "OPERATOR_PREFIX",
      type: "bytes",
      value: "[111, 112, 101, 114, 97, 116, 111, 114]"
    },
    {
      name: "ORACLE",
      type: "bytes",
      value: "[111, 114, 97, 99, 108, 101]"
    },
    {
      name: "POSITION",
      type: "bytes",
      value: "[112, 111, 115, 105, 116, 105, 111, 110]"
    },
    {
      name: "POSITION_MAX_LENGTH",
      type: "u64",
      value: "1400"
    },
    {
      name: "PRESET_PARAMETER",
      type: "bytes",
      value: "[112, 114, 101, 115, 101, 116, 95, 112, 97, 114, 97, 109, 101, 116, 101, 114]"
    },
    {
      name: "PRESET_PARAMETER2",
      type: "bytes",
      value: "[112, 114, 101, 115, 101, 116, 95, 112, 97, 114, 97, 109, 101, 116, 101, 114, 50]"
    },
    {
      name: "PROTOCOL_SHARE",
      type: "u16",
      value: "500"
    }
  ]
};

// src/dlmm/constants/index.ts
import Decimal from "decimal.js";
var LBCLMM_PROGRAM_IDS = {
  devnet: "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo",
  localhost: "LbVRzDTvBDEcrthxfZ4RL6yiq3uZw8bS6MwtdY6UhFQ",
  "mainnet-beta": "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo"
};
var ALT_ADDRESS = {
  "mainnet-beta": "JA5F83HUK9L78Y12TRLCsJZbu3Tv8pCK1GfK8mVNp1sz",
  devnet: "BD6E8oYV52P829MxDq3sEtqWKJrHh9pDSUHeaWR1jRBs"
};
var ADMIN = {
  devnet: "6WaLrrRfReGKBYUSkmx2K6AuT21ida4j8at2SUiZdXu8",
  localhost: "bossj3JvwiNK7pvjr149DqdtJxf2gdygbcmEPTkb2F1"
};
var Network = /* @__PURE__ */ ((Network2) => {
  Network2["MAINNET"] = "mainnet-beta";
  Network2["TESTNET"] = "testnet";
  Network2["DEVNET"] = "devnet";
  Network2["LOCAL"] = "localhost";
  return Network2;
})(Network || {});
var BASIS_POINT_MAX = 1e4;
var SCALE_OFFSET = 64;
var SCALE = new BN(1).shln(SCALE_OFFSET);
var FEE_PRECISION = new BN(1e9);
var MAX_FEE_RATE = new BN(1e8);
var BIN_ARRAY_DEFAULT_VERSION = 3;
var BIN_ARRAY_FEE = 0.07143744;
var POSITION_FEE = 0.05740608;
var TOKEN_ACCOUNT_FEE = 203928e-8;
var POOL_FEE = 718272e-8;
var BIN_ARRAY_BITMAP_FEE = 0.01180416;
var BIN_ARRAY_FEE_BN = new BN(
  new Decimal(BIN_ARRAY_FEE).mul(LAMPORTS_PER_SOL).toString()
);
var POSITION_FEE_BN = new BN(
  new Decimal(POSITION_FEE).mul(LAMPORTS_PER_SOL).toString()
);
var TOKEN_ACCOUNT_FEE_BN = new BN(
  new Decimal(TOKEN_ACCOUNT_FEE).mul(LAMPORTS_PER_SOL).toString()
);
var POOL_FEE_BN = new BN(
  new Decimal(POOL_FEE).mul(LAMPORTS_PER_SOL).toString()
);
var BIN_ARRAY_BITMAP_FEE_BN = new BN(
  new Decimal(BIN_ARRAY_BITMAP_FEE).mul(LAMPORTS_PER_SOL).toString()
);
var CONSTANTS = Object.entries(idl_default.constants);
var MAX_BIN_ARRAY_SIZE = new BN(
  CONSTANTS.find(([_, v]) => v.name == "MAX_BIN_PER_ARRAY")?.[1].value ?? 0
);
var DEFAULT_BIN_PER_POSITION = new BN(
  CONSTANTS.find(([_, v]) => v.name == "DEFAULT_BIN_PER_POSITION")?.[1].value ?? 0
);
var BIN_ARRAY_BITMAP_SIZE = new BN(
  CONSTANTS.find(([_, v]) => v.name == "BIN_ARRAY_BITMAP_SIZE")?.[1].value ?? 0
);
var EXTENSION_BINARRAY_BITMAP_SIZE = new BN(
  CONSTANTS.find(([_, v]) => v.name == "EXTENSION_BINARRAY_BITMAP_SIZE")?.[1].value ?? 0
);
var POSITION_MAX_LENGTH = new BN(
  CONSTANTS.find(([_, v]) => v.name == "POSITION_MAX_LENGTH")?.[1].value ?? 0
);
var MAX_RESIZE_LENGTH = new BN(
  CONSTANTS.find(([_, v]) => v.name == "MAX_RESIZE_LENGTH")?.[1].value ?? 0
);
var MAX_BIN_ID_PER_BIN_STEP = Number(
  CONSTANTS.find(([_, v]) => v.name == "MAX_BIN_ID_PER_BIN_STEP")?.[1].value ?? 0
);
var SIMULATION_USER = new PublicKey(
  "HrY9qR5TiB2xPzzvbBu5KrBorMfYGQXh9osXydz4jy9s"
);
var PRECISION = new Decimal("18446744073709551616");
var MAX_CLAIM_ALL_ALLOWED = 2;
var MAX_BIN_LENGTH_ALLOWED_IN_ONE_TX = 26;
var MAX_ACTIVE_BIN_SLIPPAGE = 3;
var ILM_BASE = new PublicKey(
  "MFGQxwAmB91SwuYX36okv2Qmdc9aMuHTwWGUrp4AtB1"
);
var MAX_EXTRA_BIN_ARRAYS = 3;
var U64_MAX = new BN("18446744073709551615");
var MAX_BINS_PER_POSITION = new BN(
  CONSTANTS.find(([_, v]) => v.name == "POSITION_MAX_LENGTH")?.[1].value ?? 0
);
var MAX_BIN_PER_LIMIT_ORDER = new BN(
  CONSTANTS.find(([_, v]) => v.name == "MAX_BIN_PER_LIMIT_ORDER")?.[1].value ?? 0
);
var LIMIT_ORDER_FEE_SHARE = new BN(
  CONSTANTS.find(([_, v]) => v.name == "LIMIT_ORDER_FEE_SHARE")?.[1].value ?? 0
);
var FunctionType = /* @__PURE__ */ ((FunctionType2) => {
  FunctionType2[FunctionType2["Undetermined"] = 0] = "Undetermined";
  FunctionType2[FunctionType2["LiquidityMining"] = 1] = "LiquidityMining";
  FunctionType2[FunctionType2["LimitOrder"] = 2] = "LimitOrder";
  return FunctionType2;
})(FunctionType || {});
var ConcreteFunctionType = /* @__PURE__ */ ((ConcreteFunctionType2) => {
  ConcreteFunctionType2[ConcreteFunctionType2["LimitOrder"] = 0] = "LimitOrder";
  ConcreteFunctionType2[ConcreteFunctionType2["LiquidityMining"] = 1] = "LiquidityMining";
  return ConcreteFunctionType2;
})(ConcreteFunctionType || {});
var CollectFeeMode = /* @__PURE__ */ ((CollectFeeMode2) => {
  CollectFeeMode2[CollectFeeMode2["InputOnly"] = 0] = "InputOnly";
  CollectFeeMode2[CollectFeeMode2["OnlyY"] = 1] = "OnlyY";
  return CollectFeeMode2;
})(CollectFeeMode || {});

// src/dlmm/error.ts
import { AnchorError } from "@coral-xyz/anchor";
var DLMMError = class extends Error {
  errorCode;
  errorName;
  errorMessage;
  constructor(error) {
    let _errorCode = 0;
    let _errorName = "Something went wrong";
    let _errorMessage = "Something went wrong";
    if (error instanceof Error) {
      const anchorError = AnchorError.parse(
        JSON.parse(JSON.stringify(error)).logs
      );
      if (anchorError?.program.toBase58() === LBCLMM_PROGRAM_IDS["mainnet-beta"]) {
        _errorCode = anchorError.error.errorCode.number;
        _errorName = anchorError.error.errorCode.code;
        _errorMessage = anchorError.error.errorMessage;
      }
    } else {
      const idlError = idl_default.errors.find((err) => err.code === error);
      if (idlError) {
        _errorCode = idlError.code;
        _errorName = idlError.name;
        _errorMessage = idlError.msg;
      }
    }
    super(_errorMessage);
    this.errorCode = _errorCode;
    this.errorName = _errorName;
    this.errorMessage = _errorMessage;
  }
};
var DlmmSdkError = class extends Error {
  name;
  message;
  constructor(name, message) {
    super();
    this.name = name;
    this.message = message;
  }
};

// src/dlmm/helpers/index.ts
import { AnchorProvider, BN as BN20, Program as Program2 } from "@coral-xyz/anchor";
import {
  ASSOCIATED_TOKEN_PROGRAM_ID,
  NATIVE_MINT,
  TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID3,
  TokenAccountNotFoundError,
  TokenInvalidAccountOwnerError,
  createAssociatedTokenAccountIdempotentInstruction,
  createCloseAccountInstruction,
  getAccount,
  getAssociatedTokenAddressSync,
  getMint
} from "@solana/spl-token";
import {
  ComputeBudgetProgram as ComputeBudgetProgram2,
  SYSVAR_RENT_PUBKEY,
  SystemProgram,
  TransactionInstruction as TransactionInstruction3
} from "@solana/web3.js";

// src/dlmm/types/index.ts
import {
  BN as BN2
} from "@coral-xyz/anchor";
import {
  PublicKey as PublicKey2
} from "@solana/web3.js";
import Decimal2 from "decimal.js";
import { u64, i64, struct } from "@coral-xyz/borsh";
var PositionVersion = /* @__PURE__ */ ((PositionVersion3) => {
  PositionVersion3[PositionVersion3["V1"] = 0] = "V1";
  PositionVersion3[PositionVersion3["V2"] = 1] = "V2";
  return PositionVersion3;
})(PositionVersion || {});
var PairType = /* @__PURE__ */ ((PairType2) => {
  PairType2[PairType2["Permissionless"] = 0] = "Permissionless";
  PairType2[PairType2["Permissioned"] = 1] = "Permissioned";
  PairType2[PairType2["CustomizablePermissionless"] = 2] = "CustomizablePermissionless";
  PairType2[PairType2["PermissionlessV2"] = 3] = "PermissionlessV2";
  return PairType2;
})(PairType || {});
var ShrinkMode = /* @__PURE__ */ ((ShrinkMode2) => {
  ShrinkMode2[ShrinkMode2["ShrinkBoth"] = 0] = "ShrinkBoth";
  ShrinkMode2[ShrinkMode2["NoShrinkLeft"] = 1] = "NoShrinkLeft";
  ShrinkMode2[ShrinkMode2["NoShrinkRight"] = 2] = "NoShrinkRight";
  ShrinkMode2[ShrinkMode2["NoShrinkBoth"] = 3] = "NoShrinkBoth";
  return ShrinkMode2;
})(ShrinkMode || {});
var Strategy = {
  SpotBalanced: { spotBalanced: {} },
  CurveBalanced: { curveBalanced: {} },
  BidAskBalanced: { bidAskBalanced: {} },
  SpotImBalanced: { spotImBalanced: {} },
  CurveImBalanced: { curveImBalanced: {} },
  BidAskImBalanced: { bidAskImBalanced: {} }
};
var StrategyType = /* @__PURE__ */ ((StrategyType3) => {
  StrategyType3[StrategyType3["Spot"] = 0] = "Spot";
  StrategyType3[StrategyType3["Curve"] = 1] = "Curve";
  StrategyType3[StrategyType3["BidAsk"] = 2] = "BidAsk";
  return StrategyType3;
})(StrategyType || {});
var ActivationType = /* @__PURE__ */ ((ActivationType2) => {
  ActivationType2[ActivationType2["Slot"] = 0] = "Slot";
  ActivationType2[ActivationType2["Timestamp"] = 1] = "Timestamp";
  return ActivationType2;
})(ActivationType || {});
var POSITION_MIN_SIZE = 8112;
var POSITION_BIN_DATA_SIZE = 112;
var LIMIT_ORDER_MIN_SIZE = 112;
var LIMIT_ORDER_BIN_DATA_SIZE = 32;
var BinLiquidity;
((BinLiquidity2) => {
  function fromBin(bin, binId, binStep, baseTokenDecimal, quoteTokenDecimal, version, lbPair) {
    const pricePerLamport = getPriceOfBinByBinId(binId, binStep).toString();
    const supportLimitOrder = isSupportLimitOrder(lbPair);
    const xAmount = bin.amountX;
    const yAmount = bin.amountY;
    const supply = bin.liquiditySupply;
    const pricePerToken = new Decimal2(pricePerLamport).mul(new Decimal2(10 ** (baseTokenDecimal - quoteTokenDecimal))).toString();
    const feeAmountXPerTokenStored = bin.feeAmountXPerTokenStored;
    const feeAmountYPerTokenStored = bin.feeAmountYPerTokenStored;
    if (supportLimitOrder) {
      return {
        binId,
        xAmount,
        yAmount,
        supply,
        version,
        price: pricePerLamport,
        pricePerToken,
        feeAmountXPerTokenStored,
        feeAmountYPerTokenStored,
        rewardPerTokenStored: [new BN2(0), new BN2(0)],
        fulfilledOrderAmountX: bin.fulfilledOrderAmountX,
        fulfilledOrderAmountY: bin.fulfilledOrderAmountY,
        limitOrderFeeAskSide: bin.limitOrderFeeAskSide,
        limitOrderFeeBidSide: bin.limitOrderFeeBidSide,
        openOrderAmount: bin.openOrderAmount,
        totalProcessingOrderAmount: bin.totalProcessingOrderAmount,
        processedOrderRemainingAmount: bin.processedOrderRemainingAmount,
        orderAge: bin.orderAge,
        limitOrderAskSide: bin.limitOrderAskSide == 1
      };
    } else {
      return {
        binId,
        xAmount,
        yAmount,
        supply,
        version,
        price: pricePerLamport,
        pricePerToken,
        feeAmountXPerTokenStored,
        feeAmountYPerTokenStored,
        rewardPerTokenStored: decodeRewardPerTokenStored(bin),
        fulfilledOrderAmountX: new BN2(0),
        fulfilledOrderAmountY: new BN2(0),
        limitOrderFeeAskSide: new BN2(0),
        limitOrderFeeBidSide: new BN2(0),
        openOrderAmount: new BN2(0),
        totalProcessingOrderAmount: new BN2(0),
        processedOrderRemainingAmount: new BN2(0),
        orderAge: 0,
        limitOrderAskSide: false
      };
    }
  }
  BinLiquidity2.fromBin = fromBin;
  function empty(binId, binStep, baseTokenDecimal, quoteTokenDecimal, version) {
    const pricePerLamport = getPriceOfBinByBinId(binId, binStep).toString();
    return {
      binId,
      xAmount: new BN2(0),
      yAmount: new BN2(0),
      supply: new BN2(0),
      price: pricePerLamport,
      version,
      pricePerToken: new Decimal2(pricePerLamport).mul(new Decimal2(10 ** (baseTokenDecimal - quoteTokenDecimal))).toString(),
      feeAmountXPerTokenStored: new BN2(0),
      feeAmountYPerTokenStored: new BN2(0),
      rewardPerTokenStored: [new BN2(0), new BN2(0)],
      fulfilledOrderAmountX: new BN2(0),
      fulfilledOrderAmountY: new BN2(0),
      limitOrderFeeAskSide: new BN2(0),
      limitOrderFeeBidSide: new BN2(0),
      openOrderAmount: new BN2(0),
      totalProcessingOrderAmount: new BN2(0),
      processedOrderRemainingAmount: new BN2(0),
      orderAge: 0,
      limitOrderAskSide: false
    };
  }
  BinLiquidity2.empty = empty;
})(BinLiquidity || (BinLiquidity = {}));
var BitmapType = /* @__PURE__ */ ((BitmapType2) => {
  BitmapType2[BitmapType2["U1024"] = 0] = "U1024";
  BitmapType2[BitmapType2["U512"] = 1] = "U512";
  return BitmapType2;
})(BitmapType || {});
var ClockLayout = struct([
  u64("slot"),
  i64("epochStartTimestamp"),
  u64("epoch"),
  u64("leaderScheduleEpoch"),
  i64("unixTimestamp")
]);
var PairStatus = /* @__PURE__ */ ((PairStatus2) => {
  PairStatus2[PairStatus2["Enabled"] = 0] = "Enabled";
  PairStatus2[PairStatus2["Disabled"] = 1] = "Disabled";
  return PairStatus2;
})(PairStatus || {});
var ActionType = /* @__PURE__ */ ((ActionType2) => {
  ActionType2[ActionType2["Liquidity"] = 0] = "Liquidity";
  ActionType2[ActionType2["Reward"] = 1] = "Reward";
  return ActionType2;
})(ActionType || {});
var ResizeSide = /* @__PURE__ */ ((ResizeSide2) => {
  ResizeSide2[ResizeSide2["Lower"] = 0] = "Lower";
  ResizeSide2[ResizeSide2["Upper"] = 1] = "Upper";
  return ResizeSide2;
})(ResizeSide || {});
var MEMO_PROGRAM_ID = new PublicKey2(
  "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
);
var REBALANCE_POSITION_PADDING = Array(31).fill(0);
var PositionPermission = /* @__PURE__ */ ((PositionPermission3) => {
  PositionPermission3[PositionPermission3["ClaimFee"] = 0] = "ClaimFee";
  return PositionPermission3;
})(PositionPermission || {});
var LimitOrderStatus = /* @__PURE__ */ ((LimitOrderStatus2) => {
  LimitOrderStatus2[LimitOrderStatus2["NotFilled"] = 0] = "NotFilled";
  LimitOrderStatus2[LimitOrderStatus2["PartialFilled"] = 1] = "PartialFilled";
  LimitOrderStatus2[LimitOrderStatus2["Fulfilled"] = 2] = "Fulfilled";
  return LimitOrderStatus2;
})(LimitOrderStatus || {});

// src/dlmm/helpers/binArray.ts
import { BN as BN10 } from "@coral-xyz/anchor";
import { PublicKey as PublicKey5 } from "@solana/web3.js";

// src/dlmm/helpers/derive.ts
import { PublicKey as PublicKey3 } from "@solana/web3.js";
function sortTokenMints(tokenX, tokenY) {
  const [minKey, maxKey] = tokenX.toBuffer().compare(tokenY.toBuffer()) == 1 ? [tokenY, tokenX] : [tokenX, tokenY];
  return [minKey, maxKey];
}
function derivePresetParameterWithIndex(index, programId) {
  return PublicKey3.findProgramAddressSync(
    [
      Buffer.from("preset_parameter2"),
      new Uint8Array(index.toArrayLike(Buffer, "le", 2))
    ],
    programId
  );
}
function deriveLbPairWithPresetParamWithIndexKey(presetParameterKey, tokenX, tokenY, programId) {
  const [minKey, maxKey] = sortTokenMints(tokenX, tokenY);
  return PublicKey3.findProgramAddressSync(
    [presetParameterKey.toBuffer(), minKey.toBuffer(), maxKey.toBuffer()],
    programId
  );
}
function derivePresetParameter(binStep, programId) {
  return PublicKey3.findProgramAddressSync(
    [
      Buffer.from("preset_parameter"),
      new Uint8Array(binStep.toArrayLike(Buffer, "le", 2))
    ],
    programId
  );
}
function derivePresetParameter2(binStep, baseFactor, programId) {
  return PublicKey3.findProgramAddressSync(
    [
      Buffer.from("preset_parameter"),
      new Uint8Array(binStep.toArrayLike(Buffer, "le", 2)),
      new Uint8Array(baseFactor.toArrayLike(Buffer, "le", 2))
    ],
    programId
  );
}
function deriveLbPair2(tokenX, tokenY, binStep, baseFactor, programId) {
  const [minKey, maxKey] = sortTokenMints(tokenX, tokenY);
  return PublicKey3.findProgramAddressSync(
    [
      minKey.toBuffer(),
      maxKey.toBuffer(),
      new Uint8Array(binStep.toArrayLike(Buffer, "le", 2)),
      new Uint8Array(baseFactor.toArrayLike(Buffer, "le", 2))
    ],
    programId
  );
}
function deriveLbPair(tokenX, tokenY, binStep, programId) {
  const [minKey, maxKey] = sortTokenMints(tokenX, tokenY);
  return PublicKey3.findProgramAddressSync(
    [
      minKey.toBuffer(),
      maxKey.toBuffer(),
      new Uint8Array(binStep.toArrayLike(Buffer, "le", 2))
    ],
    programId
  );
}
function deriveCustomizablePermissionlessLbPair(tokenX, tokenY, programId) {
  const [minKey, maxKey] = sortTokenMints(tokenX, tokenY);
  return PublicKey3.findProgramAddressSync(
    [ILM_BASE.toBuffer(), minKey.toBuffer(), maxKey.toBuffer()],
    programId
  );
}
function derivePermissionLbPair(baseKey, tokenX, tokenY, binStep, programId) {
  const [minKey, maxKey] = sortTokenMints(tokenX, tokenY);
  return PublicKey3.findProgramAddressSync(
    [
      baseKey.toBuffer(),
      minKey.toBuffer(),
      maxKey.toBuffer(),
      new Uint8Array(binStep.toArrayLike(Buffer, "le", 2))
    ],
    programId
  );
}
function deriveOracle(lbPair, programId) {
  return PublicKey3.findProgramAddressSync(
    [Buffer.from("oracle"), lbPair.toBytes()],
    programId
  );
}
function derivePosition(lbPair, base, lowerBinId, width, programId) {
  let lowerBinIdBytes;
  if (lowerBinId.isNeg()) {
    lowerBinIdBytes = new Uint8Array(
      lowerBinId.toTwos(32).toArrayLike(Buffer, "le", 4)
    );
  } else {
    lowerBinIdBytes = new Uint8Array(lowerBinId.toArrayLike(Buffer, "le", 4));
  }
  return PublicKey3.findProgramAddressSync(
    [
      Buffer.from("position"),
      lbPair.toBuffer(),
      base.toBuffer(),
      lowerBinIdBytes,
      new Uint8Array(width.toArrayLike(Buffer, "le", 4))
    ],
    programId
  );
}
function deriveBinArray(lbPair, index, programId) {
  let binArrayBytes;
  if (index.isNeg()) {
    binArrayBytes = new Uint8Array(
      index.toTwos(64).toArrayLike(Buffer, "le", 8)
    );
  } else {
    binArrayBytes = new Uint8Array(index.toArrayLike(Buffer, "le", 8));
  }
  return PublicKey3.findProgramAddressSync(
    [Buffer.from("bin_array"), lbPair.toBytes(), binArrayBytes],
    programId
  );
}
function deriveReserve(token, lbPair, programId) {
  return PublicKey3.findProgramAddressSync(
    [lbPair.toBuffer(), token.toBuffer()],
    programId
  );
}
function deriveTokenBadge(mint, programId) {
  return PublicKey3.findProgramAddressSync(
    [Buffer.from("token_badge"), mint.toBuffer()],
    programId
  );
}
function deriveEventAuthority(programId) {
  return PublicKey3.findProgramAddressSync(
    [Buffer.from("__event_authority")],
    programId
  );
}
function deriveRewardVault(lbPair, rewardIndex, programId) {
  return PublicKey3.findProgramAddressSync(
    [lbPair.toBuffer(), rewardIndex.toArrayLike(Buffer, "le", 8)],
    programId
  );
}
function derivePlaceHolderAccountMeta(programId) {
  return {
    pubkey: programId,
    isWritable: false,
    isSigner: false
  };
}
function deriveOperator(whitelistedSigner, programId) {
  return PublicKey3.findProgramAddressSync(
    [Buffer.from("operator"), whitelistedSigner.toBuffer()],
    programId
  )[0];
}

// src/dlmm/helpers/math.ts
import { BN as BN7 } from "@coral-xyz/anchor";
import Decimal5 from "decimal.js";

// src/dlmm/helpers/u64xu64_math.ts
import BN3 from "bn.js";
var MAX_EXPONENTIAL = new BN3(524288);
var ONE = new BN3(1).shln(SCALE_OFFSET);
var MAX = new BN3(2).pow(new BN3(128)).sub(new BN3(1));
function pow(base, exp) {
  let invert = exp.isNeg();
  if (exp.isZero()) {
    return ONE;
  }
  exp = invert ? exp.abs() : exp;
  if (exp.gt(MAX_EXPONENTIAL)) {
    return new BN3(0);
  }
  let squaredBase = base;
  let result = ONE;
  if (squaredBase.gte(result)) {
    squaredBase = MAX.div(squaredBase);
    invert = !invert;
  }
  if (!exp.and(new BN3(1)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(2)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(4)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(8)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(16)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(32)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(64)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(128)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(256)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(512)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(1024)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(2048)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(4096)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(8192)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(16384)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(32768)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(65536)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(131072)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET);
  if (!exp.and(new BN3(262144)).isZero()) {
    result = result.mul(squaredBase).shrn(SCALE_OFFSET);
  }
  if (result.isZero()) {
    return new BN3(0);
  }
  if (invert) {
    result = MAX.div(result);
  }
  return result;
}

// src/dlmm/helpers/weight.ts
import { BN as BN6 } from "@coral-xyz/anchor";
import gaussian from "gaussian";
import Decimal4 from "decimal.js";

// src/dlmm/helpers/weightToAmounts.ts
import { BN as BN5 } from "@coral-xyz/anchor";
import Decimal3 from "decimal.js";

// src/dlmm/helpers/token_2022.ts
import {
  addExtraAccountMetasForExecute,
  calculateFee,
  createTransferCheckedInstruction,
  getEpochFee,
  getTransferFeeConfig,
  getTransferHook,
  MAX_FEE_BASIS_POINTS,
  TOKEN_2022_PROGRAM_ID,
  TOKEN_PROGRAM_ID,
  unpackMint
} from "@solana/spl-token";
import {
  PublicKey as PublicKey4
} from "@solana/web3.js";
import BN4 from "bn.js";
async function getMultipleMintsExtraAccountMetasForTransferHook(connection, mintAddressesWithAccountInfo) {
  const extraAccountMetas = await Promise.all(
    mintAddressesWithAccountInfo.map(
      ({ mintAddress, mintAccountInfo }) => getExtraAccountMetasForTransferHook(
        connection,
        mintAddress,
        mintAccountInfo
      )
    )
  );
  const mintsWithHookAccountMap = /* @__PURE__ */ new Map();
  for (let i = 0; i < extraAccountMetas.length; i++) {
    const { mintAddress } = mintAddressesWithAccountInfo[i];
    const transferHooks = extraAccountMetas[i];
    mintsWithHookAccountMap.set(mintAddress.toBase58(), transferHooks);
  }
  return mintsWithHookAccountMap;
}
async function getExtraAccountMetasForTransferHook(connection, mintAddress, mintAccountInfo) {
  if (![TOKEN_PROGRAM_ID.toBase58(), TOKEN_2022_PROGRAM_ID.toBase58()].includes(
    mintAccountInfo.owner.toBase58()
  )) {
    return [];
  }
  const mintState = unpackMint(
    mintAddress,
    mintAccountInfo,
    mintAccountInfo.owner
  );
  if (mintAccountInfo.owner.equals(TOKEN_PROGRAM_ID)) {
    return [];
  }
  const transferHook = getTransferHook(mintState);
  if (!transferHook || transferHook.programId.equals(PublicKey4.default)) {
    return [];
  } else {
    const instruction = createTransferCheckedInstruction(
      PublicKey4.default,
      mintAddress,
      PublicKey4.default,
      PublicKey4.default,
      BigInt(0),
      mintState.decimals,
      [],
      mintAccountInfo.owner
    );
    await addExtraAccountMetasForExecute(
      connection,
      instruction,
      transferHook.programId,
      PublicKey4.default,
      mintAddress,
      PublicKey4.default,
      PublicKey4.default,
      BigInt(0)
    );
    const transferHookAccounts = instruction.keys.slice(4);
    if (transferHookAccounts.length == 0) {
      transferHookAccounts.push({
        pubkey: transferHook.programId,
        isSigner: false,
        isWritable: false
      });
    }
    return transferHookAccounts;
  }
}
function calculatePreFeeAmount(transferFee, postFeeAmount) {
  if (postFeeAmount.isZero()) {
    return new BN4(0);
  }
  if (transferFee.transferFeeBasisPoints === 0) {
    return postFeeAmount;
  }
  const maximumFee = new BN4(transferFee.maximumFee.toString());
  if (transferFee.transferFeeBasisPoints === MAX_FEE_BASIS_POINTS) {
    return postFeeAmount.add(maximumFee);
  }
  const ONE_IN_BASIS_POINTS = new BN4(MAX_FEE_BASIS_POINTS);
  const numerator = postFeeAmount.mul(ONE_IN_BASIS_POINTS);
  const denominator = ONE_IN_BASIS_POINTS.sub(
    new BN4(transferFee.transferFeeBasisPoints)
  );
  const rawPreFeeAmount = numerator.add(denominator).sub(new BN4(1)).div(denominator);
  if (rawPreFeeAmount.sub(postFeeAmount).gte(maximumFee)) {
    return postFeeAmount.add(maximumFee);
  }
  return rawPreFeeAmount;
}
function calculateInverseFee(transferFee, postFeeAmount) {
  const preFeeAmount = calculatePreFeeAmount(transferFee, postFeeAmount);
  return new BN4(
    calculateFee(transferFee, BigInt(preFeeAmount.toString())).toString()
  );
}
function calculateTransferFeeIncludedAmount(transferFeeExcludedAmount, mint, currentEpoch) {
  if (transferFeeExcludedAmount.isZero()) {
    return {
      amount: new BN4(0),
      transferFee: new BN4(0)
    };
  }
  const transferFeeConfig = getTransferFeeConfig(mint);
  if (transferFeeConfig === null) {
    return {
      amount: transferFeeExcludedAmount,
      transferFee: new BN4(0)
    };
  }
  const epochFee = getEpochFee(transferFeeConfig, BigInt(currentEpoch));
  const transferFee = epochFee.transferFeeBasisPoints == MAX_FEE_BASIS_POINTS ? new BN4(epochFee.maximumFee.toString()) : calculateInverseFee(epochFee, transferFeeExcludedAmount);
  const transferFeeIncludedAmount = transferFeeExcludedAmount.add(transferFee);
  return {
    amount: transferFeeIncludedAmount,
    transferFee
  };
}
function calculateTransferFeeExcludedAmount(transferFeeIncludedAmount, mint, currentEpoch) {
  const transferFeeConfig = getTransferFeeConfig(mint);
  if (transferFeeConfig === null) {
    return {
      amount: transferFeeIncludedAmount,
      transferFee: new BN4(0)
    };
  }
  const transferFeeIncludedAmountN = BigInt(
    transferFeeIncludedAmount.toString()
  );
  const transferFee = calculateFee(
    getEpochFee(transferFeeConfig, BigInt(currentEpoch)),
    transferFeeIncludedAmountN
  );
  const transferFeeExcludedAmount = new BN4(
    (transferFeeIncludedAmountN - transferFee).toString()
  );
  return {
    amount: transferFeeExcludedAmount,
    transferFee: new BN4(transferFee.toString())
  };
}

// src/dlmm/helpers/weightToAmounts.ts
function toAmountBidSide(activeId, totalAmount, distributions, mintY, clock) {
  totalAmount = calculateTransferFeeExcludedAmount(
    totalAmount,
    mintY,
    clock.epoch.toNumber()
  ).amount;
  const totalWeight = distributions.reduce(function(sum, el) {
    return el.binId > activeId ? sum : sum.add(el.weight);
  }, new Decimal3(0));
  if (totalWeight.cmp(new Decimal3(0)) != 1) {
    throw Error("Invalid parameteres");
  }
  return distributions.map((bin) => {
    if (bin.binId > activeId) {
      return {
        binId: bin.binId,
        amount: new BN5(0)
      };
    } else {
      return {
        binId: bin.binId,
        amount: new BN5(
          new Decimal3(totalAmount.toString()).mul(new Decimal3(bin.weight).div(totalWeight)).floor().toString()
        )
      };
    }
  });
}
function toAmountAskSide(activeId, binStep, totalAmount, distributions, mintX, clock) {
  totalAmount = calculateTransferFeeExcludedAmount(
    totalAmount,
    mintX,
    clock.epoch.toNumber()
  ).amount;
  const totalWeight = distributions.reduce(function(sum, el) {
    if (el.binId < activeId) {
      return sum;
    } else {
      const price = getPriceOfBinByBinId(el.binId, binStep);
      const weightPerPrice = new Decimal3(el.weight).div(price);
      return sum.add(weightPerPrice);
    }
  }, new Decimal3(0));
  if (totalWeight.cmp(new Decimal3(0)) != 1) {
    throw Error("Invalid parameteres");
  }
  return distributions.map((bin) => {
    if (bin.binId < activeId) {
      return {
        binId: bin.binId,
        amount: new BN5(0)
      };
    } else {
      const price = getPriceOfBinByBinId(bin.binId, binStep);
      const weightPerPrice = new Decimal3(bin.weight).div(price);
      return {
        binId: bin.binId,
        amount: new BN5(
          new Decimal3(totalAmount.toString()).mul(weightPerPrice).div(totalWeight).floor().toString()
        )
      };
    }
  });
}
function toAmountBothSide(activeId, binStep, amountX, amountY, amountXInActiveBin, amountYInActiveBin, distributions, mintX, mintY, clock) {
  if (activeId > distributions[distributions.length - 1].binId) {
    let amounts = toAmountBidSide(
      activeId,
      amountY,
      distributions,
      mintY,
      clock
    );
    return amounts.map((bin) => {
      return {
        binId: bin.binId,
        amountX: new BN5(0),
        amountY: bin.amount
      };
    });
  }
  if (activeId < distributions[0].binId) {
    let amounts = toAmountAskSide(
      activeId,
      binStep,
      amountX,
      distributions,
      mintX,
      clock
    );
    return amounts.map((bin) => {
      return {
        binId: bin.binId,
        amountX: bin.amount,
        amountY: new BN5(0)
      };
    });
  }
  amountX = calculateTransferFeeIncludedAmount(
    amountX,
    mintX,
    clock.epoch.toNumber()
  ).amount;
  amountY = calculateTransferFeeIncludedAmount(
    amountY,
    mintY,
    clock.epoch.toNumber()
  ).amount;
  const activeBins = distributions.filter((element) => {
    return element.binId === activeId;
  });
  if (activeBins.length === 1) {
    const p0 = getPriceOfBinByBinId(activeId, binStep);
    let wx0 = new Decimal3(0);
    let wy0 = new Decimal3(0);
    const activeBin = activeBins[0];
    if (amountXInActiveBin.isZero() && amountYInActiveBin.isZero()) {
      wx0 = new Decimal3(activeBin.weight).div(p0.mul(new Decimal3(2)));
      wy0 = new Decimal3(activeBin.weight).div(new Decimal3(2));
    } else {
      let amountXInActiveBinDec = new Decimal3(amountXInActiveBin.toString());
      let amountYInActiveBinDec = new Decimal3(amountYInActiveBin.toString());
      if (!amountXInActiveBin.isZero()) {
        wx0 = new Decimal3(activeBin.weight).div(
          p0.add(amountYInActiveBinDec.div(amountXInActiveBinDec))
        );
      }
      if (!amountYInActiveBin.isZero()) {
        wy0 = new Decimal3(activeBin.weight).div(
          new Decimal3(1).add(
            p0.mul(amountXInActiveBinDec).div(amountYInActiveBinDec)
          )
        );
      }
    }
    let totalWeightX = wx0;
    let totalWeightY = wy0;
    distributions.forEach((element) => {
      if (element.binId < activeId) {
        totalWeightY = totalWeightY.add(new Decimal3(element.weight));
      }
      if (element.binId > activeId) {
        let price = getPriceOfBinByBinId(element.binId, binStep);
        let weighPerPrice = new Decimal3(element.weight).div(price);
        totalWeightX = totalWeightX.add(weighPerPrice);
      }
    });
    const kx = new Decimal3(amountX.toString()).div(totalWeightX);
    const ky = new Decimal3(amountY.toString()).div(totalWeightY);
    let k = kx.lessThan(ky) ? kx : ky;
    return distributions.map((bin) => {
      if (bin.binId < activeId) {
        const amount = k.mul(new Decimal3(bin.weight));
        return {
          binId: bin.binId,
          amountX: new BN5(0),
          amountY: new BN5(amount.floor().toString())
        };
      }
      if (bin.binId > activeId) {
        const price = getPriceOfBinByBinId(bin.binId, binStep);
        const weighPerPrice = new Decimal3(bin.weight).div(price);
        const amount = k.mul(weighPerPrice);
        return {
          binId: bin.binId,
          amountX: new BN5(amount.floor().toString()),
          amountY: new BN5(0)
        };
      }
      const amountXActiveBin = k.mul(wx0);
      const amountYActiveBin = k.mul(wy0);
      return {
        binId: bin.binId,
        amountX: new BN5(amountXActiveBin.floor().toString()),
        amountY: new BN5(amountYActiveBin.floor().toString())
      };
    });
  } else {
    let totalWeightX = new Decimal3(0);
    let totalWeightY = new Decimal3(0);
    distributions.forEach((element) => {
      if (element.binId < activeId) {
        totalWeightY = totalWeightY.add(new Decimal3(element.weight));
      } else {
        let price = getPriceOfBinByBinId(element.binId, binStep);
        let weighPerPrice = new Decimal3(element.weight).div(price);
        totalWeightX = totalWeightX.add(weighPerPrice);
      }
    });
    let kx = new Decimal3(amountX.toString()).div(totalWeightX);
    let ky = new Decimal3(amountY.toString()).div(totalWeightY);
    let k = kx.lessThan(ky) ? kx : ky;
    return distributions.map((bin) => {
      if (bin.binId < activeId) {
        const amount = k.mul(new Decimal3(bin.weight));
        return {
          binId: bin.binId,
          amountX: new BN5(0),
          amountY: new BN5(amount.floor().toString())
        };
      } else {
        let price = getPriceOfBinByBinId(bin.binId, binStep);
        let weighPerPrice = new Decimal3(bin.weight).div(price);
        const amount = k.mul(weighPerPrice);
        return {
          binId: bin.binId,
          amountX: new BN5(amount.floor().toString()),
          amountY: new BN5(0)
        };
      }
    });
  }
}
function autoFillYByWeight(activeId, binStep, amountX, amountXInActiveBin, amountYInActiveBin, distributions) {
  const activeBins = distributions.filter((element) => {
    return element.binId === activeId;
  });
  if (activeBins.length === 1) {
    const p0 = getPriceOfBinByBinId(activeId, binStep);
    let wx0 = new Decimal3(0);
    let wy0 = new Decimal3(0);
    const activeBin = activeBins[0];
    if (amountXInActiveBin.isZero() && amountYInActiveBin.isZero()) {
      wx0 = new Decimal3(activeBin.weight).div(p0.mul(new Decimal3(2)));
      wy0 = new Decimal3(activeBin.weight).div(new Decimal3(2));
    } else {
      let amountXInActiveBinDec = new Decimal3(amountXInActiveBin.toString());
      let amountYInActiveBinDec = new Decimal3(amountYInActiveBin.toString());
      if (!amountXInActiveBin.isZero()) {
        wx0 = new Decimal3(activeBin.weight).div(
          p0.add(amountYInActiveBinDec.div(amountXInActiveBinDec))
        );
      }
      if (!amountYInActiveBin.isZero()) {
        wy0 = new Decimal3(activeBin.weight).div(
          new Decimal3(1).add(
            p0.mul(amountXInActiveBinDec).div(amountYInActiveBinDec)
          )
        );
      }
    }
    let totalWeightX = wx0;
    let totalWeightY = wy0;
    distributions.forEach((element) => {
      if (element.binId < activeId) {
        totalWeightY = totalWeightY.add(new Decimal3(element.weight));
      }
      if (element.binId > activeId) {
        const price = getPriceOfBinByBinId(element.binId, binStep);
        const weighPerPrice = new Decimal3(element.weight).div(price);
        totalWeightX = totalWeightX.add(weighPerPrice);
      }
    });
    const kx = totalWeightX.isZero() ? new Decimal3(1) : new Decimal3(amountX.toString()).div(totalWeightX);
    const amountY = kx.mul(totalWeightY);
    return new BN5(amountY.floor().toString());
  } else {
    let totalWeightX = new Decimal3(0);
    let totalWeightY = new Decimal3(0);
    distributions.forEach((element) => {
      if (element.binId < activeId) {
        totalWeightY = totalWeightY.add(new Decimal3(element.weight));
      } else {
        const price = getPriceOfBinByBinId(element.binId, binStep);
        const weighPerPrice = new Decimal3(element.weight).div(price);
        totalWeightX = totalWeightX.add(weighPerPrice);
      }
    });
    const kx = totalWeightX.isZero() ? new Decimal3(1) : new Decimal3(amountX.toString()).div(totalWeightX);
    const amountY = kx.mul(totalWeightY);
    return new BN5(amountY.floor().toString());
  }
}
function autoFillXByWeight(activeId, binStep, amountY, amountXInActiveBin, amountYInActiveBin, distributions) {
  const activeBins = distributions.filter((element) => {
    return element.binId === activeId;
  });
  if (activeBins.length === 1) {
    const p0 = getPriceOfBinByBinId(activeId, binStep);
    let wx0 = new Decimal3(0);
    let wy0 = new Decimal3(0);
    const activeBin = activeBins[0];
    if (amountXInActiveBin.isZero() && amountYInActiveBin.isZero()) {
      wx0 = new Decimal3(activeBin.weight).div(p0.mul(new Decimal3(2)));
      wy0 = new Decimal3(activeBin.weight).div(new Decimal3(2));
    } else {
      let amountXInActiveBinDec = new Decimal3(amountXInActiveBin.toString());
      let amountYInActiveBinDec = new Decimal3(amountYInActiveBin.toString());
      if (!amountXInActiveBin.isZero()) {
        wx0 = new Decimal3(activeBin.weight).div(
          p0.add(amountYInActiveBinDec.div(amountXInActiveBinDec))
        );
      }
      if (!amountYInActiveBin.isZero()) {
        wy0 = new Decimal3(activeBin.weight).div(
          new Decimal3(1).add(
            p0.mul(amountXInActiveBinDec).div(amountYInActiveBinDec)
          )
        );
      }
    }
    let totalWeightX = wx0;
    let totalWeightY = wy0;
    distributions.forEach((element) => {
      if (element.binId < activeId) {
        totalWeightY = totalWeightY.add(new Decimal3(element.weight));
      }
      if (element.binId > activeId) {
        const price = getPriceOfBinByBinId(element.binId, binStep);
        const weighPerPrice = new Decimal3(element.weight).div(price);
        totalWeightX = totalWeightX.add(weighPerPrice);
      }
    });
    const ky = totalWeightY.isZero() ? new Decimal3(1) : new Decimal3(amountY.toString()).div(totalWeightY);
    const amountX = ky.mul(totalWeightX);
    return new BN5(amountX.floor().toString());
  } else {
    let totalWeightX = new Decimal3(0);
    let totalWeightY = new Decimal3(0);
    distributions.forEach((element) => {
      if (element.binId < activeId) {
        totalWeightY = totalWeightY.add(new Decimal3(element.weight));
      } else {
        const price = getPriceOfBinByBinId(element.binId, binStep);
        const weighPerPrice = new Decimal3(element.weight).div(price);
        totalWeightX = totalWeightX.add(weighPerPrice);
      }
    });
    const ky = totalWeightY.isZero() ? new Decimal3(1) : new Decimal3(amountY.toString()).div(totalWeightY);
    const amountX = ky.mul(totalWeightX);
    return new BN5(amountX.floor().toString());
  }
}

// src/dlmm/helpers/weight.ts
function getPriceOfBinByBinId(binId, binStep) {
  const binStepNum = new Decimal4(binStep).div(new Decimal4(BASIS_POINT_MAX));
  return new Decimal4(1).add(new Decimal4(binStepNum)).pow(new Decimal4(binId));
}
function buildGaussianFromBins(activeBin, binIds) {
  const smallestBin = Math.min(...binIds);
  const largestBin = Math.max(...binIds);
  let mean = 0;
  const isAroundActiveBin = binIds.find((bid) => bid == activeBin);
  if (isAroundActiveBin) {
    mean = activeBin;
  } else if (activeBin < smallestBin) {
    mean = smallestBin;
  } else {
    mean = largestBin;
  }
  const TWO_STANDARD_DEVIATION = 4;
  const stdDev = (largestBin - smallestBin) / TWO_STANDARD_DEVIATION;
  const variance = Math.max(stdDev ** 2, 1);
  return gaussian(mean, variance);
}
function generateBinLiquidityAllocation(gaussian2, binIds, invert) {
  const allocations = binIds.map(
    (bid) => invert ? 1 / gaussian2.pdf(bid) : gaussian2.pdf(bid)
  );
  const totalAllocations = allocations.reduce((acc, v) => acc + v, 0);
  return allocations.map((a) => a / totalAllocations);
}
function computeAllocationBps(allocations) {
  let totalAllocation = new BN6(0);
  const bpsAllocations = [];
  for (const allocation of allocations) {
    const allocBps = new BN6(allocation * 1e4);
    bpsAllocations.push(allocBps);
    totalAllocation = totalAllocation.add(allocBps);
  }
  const pLoss = new BN6(1e4).sub(totalAllocation);
  return {
    bpsAllocations,
    pLoss
  };
}
function toWeightDistribution(amountX, amountY, distributions, binStep) {
  let totalQuote = new BN6(0);
  const precision = 1e12;
  const quoteDistributions = distributions.map((bin) => {
    const price = new BN6(
      getPriceOfBinByBinId(bin.binId, binStep).mul(precision).floor().toString()
    );
    const quoteValue = amountX.mul(new BN6(bin.xAmountBpsOfTotal)).mul(new BN6(price)).div(new BN6(BASIS_POINT_MAX)).div(new BN6(precision));
    const quoteAmount = quoteValue.add(
      amountY.mul(new BN6(bin.yAmountBpsOfTotal)).div(new BN6(BASIS_POINT_MAX))
    );
    totalQuote = totalQuote.add(quoteAmount);
    return {
      binId: bin.binId,
      quoteAmount
    };
  });
  if (totalQuote.eq(new BN6(0))) {
    return [];
  }
  const distributionWeights = quoteDistributions.map((bin) => {
    const weight = Math.floor(
      bin.quoteAmount.mul(new BN6(65535)).div(totalQuote).toNumber()
    );
    return {
      binId: bin.binId,
      weight
    };
  }).filter((item) => item.weight > 0);
  return distributionWeights;
}
function calculateSpotDistribution(activeBin, binIds) {
  if (!binIds.includes(activeBin)) {
    const { div: dist, mod: rem } = new BN6(1e4).divmod(
      new BN6(binIds.length)
    );
    const loss = rem.isZero() ? new BN6(0) : new BN6(1);
    const distributions = binIds[0] < activeBin ? binIds.map((binId) => ({
      binId,
      xAmountBpsOfTotal: new BN6(0),
      yAmountBpsOfTotal: dist
    })) : binIds.map((binId) => ({
      binId,
      xAmountBpsOfTotal: dist,
      yAmountBpsOfTotal: new BN6(0)
    }));
    if (binIds[0] < activeBin) {
      distributions[0].yAmountBpsOfTotal.add(loss);
    } else {
      distributions[binIds.length - 1].xAmountBpsOfTotal.add(loss);
    }
    return distributions;
  }
  const binYCount = binIds.filter((binId) => binId < activeBin).length;
  const binXCount = binIds.filter((binId) => binId > activeBin).length;
  const totalYBinCapacity = binYCount + 0.5;
  const totalXBinCapacity = binXCount + 0.5;
  const yBinBps = new BN6(1e4 / totalYBinCapacity);
  const yActiveBinBps = new BN6(1e4).sub(yBinBps.mul(new BN6(binYCount)));
  const xBinBps = new BN6(1e4 / totalXBinCapacity);
  const xActiveBinBps = new BN6(1e4).sub(xBinBps.mul(new BN6(binXCount)));
  return binIds.map((binId) => {
    const isYBin = binId < activeBin;
    const isXBin = binId > activeBin;
    const isActiveBin = binId === activeBin;
    if (isYBin) {
      return {
        binId,
        xAmountBpsOfTotal: new BN6(0),
        yAmountBpsOfTotal: yBinBps
      };
    }
    if (isXBin) {
      return {
        binId,
        xAmountBpsOfTotal: xBinBps,
        yAmountBpsOfTotal: new BN6(0)
      };
    }
    if (isActiveBin) {
      return {
        binId,
        xAmountBpsOfTotal: xActiveBinBps,
        yAmountBpsOfTotal: yActiveBinBps
      };
    }
  });
}
function calculateBidAskDistribution(activeBin, binIds) {
  const smallestBin = Math.min(...binIds);
  const largestBin = Math.max(...binIds);
  const rightOnly = activeBin < smallestBin;
  const leftOnly = activeBin > largestBin;
  const gaussian2 = buildGaussianFromBins(activeBin, binIds);
  const allocations = generateBinLiquidityAllocation(gaussian2, binIds, true);
  if (rightOnly) {
    const { bpsAllocations, pLoss } = computeAllocationBps(allocations);
    const binDistributions = binIds.map((bid, idx2) => ({
      binId: bid,
      xAmountBpsOfTotal: bpsAllocations[idx2],
      yAmountBpsOfTotal: new BN6(0)
    }));
    const idx = binDistributions.length - 1;
    binDistributions[idx].xAmountBpsOfTotal = binDistributions[idx].xAmountBpsOfTotal.add(pLoss);
    return binDistributions;
  }
  if (leftOnly) {
    const { bpsAllocations, pLoss } = computeAllocationBps(allocations);
    const binDistributions = binIds.map((bid, idx) => ({
      binId: bid,
      xAmountBpsOfTotal: new BN6(0),
      yAmountBpsOfTotal: bpsAllocations[idx]
    }));
    binDistributions[0].yAmountBpsOfTotal = binDistributions[0].yAmountBpsOfTotal.add(pLoss);
    return binDistributions;
  }
  const [totalXAllocation, totalYAllocation] = allocations.reduce(
    ([xAcc, yAcc], allocation, idx) => {
      const binId = binIds[idx];
      if (binId > activeBin) {
        return [xAcc + allocation, yAcc];
      } else if (binId < activeBin) {
        return [xAcc, yAcc + allocation];
      } else {
        const half = allocation / 2;
        return [xAcc + half, yAcc + half];
      }
    },
    [0, 0]
  );
  const [normXAllocations, normYAllocations] = allocations.reduce(
    ([xAllocations, yAllocations], allocation, idx) => {
      const binId = binIds[idx];
      if (binId > activeBin) {
        const distX = new BN6(allocation * 1e4 / totalXAllocation);
        xAllocations.push(distX);
      }
      if (binId < activeBin) {
        const distY = new BN6(allocation * 1e4 / totalYAllocation);
        yAllocations.push(distY);
      }
      if (binId == activeBin) {
        const half = allocation / 2;
        const distX = new BN6(half * 1e4 / totalXAllocation);
        const distY = new BN6(half * 1e4 / totalYAllocation);
        xAllocations.push(distX);
        yAllocations.push(distY);
      }
      return [xAllocations, yAllocations];
    },
    [[], []]
  );
  const totalXNormAllocations = normXAllocations.reduce(
    (acc, v) => acc.add(v),
    new BN6(0)
  );
  const totalYNormAllocations = normYAllocations.reduce(
    (acc, v) => acc.add(v),
    new BN6(0)
  );
  const xPLoss = new BN6(1e4).sub(totalXNormAllocations);
  const yPLoss = new BN6(1e4).sub(totalYNormAllocations);
  const distributions = binIds.map((binId) => {
    if (binId === activeBin) {
      return {
        binId,
        xAmountBpsOfTotal: normXAllocations.shift(),
        yAmountBpsOfTotal: normYAllocations.shift()
      };
    }
    if (binId > activeBin) {
      return {
        binId,
        xAmountBpsOfTotal: normXAllocations.shift(),
        yAmountBpsOfTotal: new BN6(0)
      };
    }
    if (binId < activeBin) {
      return {
        binId,
        xAmountBpsOfTotal: new BN6(0),
        yAmountBpsOfTotal: normYAllocations.shift()
      };
    }
  });
  if (!yPLoss.isZero()) {
    distributions[0].yAmountBpsOfTotal = distributions[0].yAmountBpsOfTotal.add(yPLoss);
  }
  if (!xPLoss.isZero()) {
    const last = distributions.length - 1;
    distributions[last].xAmountBpsOfTotal = distributions[last].xAmountBpsOfTotal.add(xPLoss);
  }
  return distributions;
}
function calculateNormalDistribution(activeBin, binIds) {
  const smallestBin = Math.min(...binIds);
  const largestBin = Math.max(...binIds);
  const rightOnly = activeBin < smallestBin;
  const leftOnly = activeBin > largestBin;
  const gaussian2 = buildGaussianFromBins(activeBin, binIds);
  const allocations = generateBinLiquidityAllocation(gaussian2, binIds, false);
  if (rightOnly) {
    const { bpsAllocations, pLoss } = computeAllocationBps(allocations);
    const binDistributions = binIds.map((bid, idx) => ({
      binId: bid,
      xAmountBpsOfTotal: bpsAllocations[idx],
      yAmountBpsOfTotal: new BN6(0)
    }));
    binDistributions[0].xAmountBpsOfTotal = binDistributions[0].xAmountBpsOfTotal.add(pLoss);
    return binDistributions;
  }
  if (leftOnly) {
    const { bpsAllocations, pLoss } = computeAllocationBps(allocations);
    const binDistributions = binIds.map((bid, idx2) => ({
      binId: bid,
      xAmountBpsOfTotal: new BN6(0),
      yAmountBpsOfTotal: bpsAllocations[idx2]
    }));
    const idx = binDistributions.length - 1;
    binDistributions[idx].yAmountBpsOfTotal = binDistributions[idx].yAmountBpsOfTotal.add(pLoss);
    return binDistributions;
  }
  const [totalXAllocation, totalYAllocation] = allocations.reduce(
    ([xAcc, yAcc], allocation, idx) => {
      const binId = binIds[idx];
      if (binId > activeBin) {
        return [xAcc + allocation, yAcc];
      } else if (binId < activeBin) {
        return [xAcc, yAcc + allocation];
      } else {
        const half = allocation / 2;
        return [xAcc + half, yAcc + half];
      }
    },
    [0, 0]
  );
  const [normXAllocations, normYAllocations] = allocations.reduce(
    ([xAllocations, yAllocations], allocation, idx) => {
      const binId = binIds[idx];
      if (binId > activeBin) {
        const distX = new BN6(allocation * 1e4 / totalXAllocation);
        xAllocations.push(distX);
      }
      if (binId < activeBin) {
        const distY = new BN6(allocation * 1e4 / totalYAllocation);
        yAllocations.push(distY);
      }
      return [xAllocations, yAllocations];
    },
    [[], []]
  );
  const normXActiveBinAllocation = normXAllocations.reduce(
    (maxBps, bps) => maxBps.sub(bps),
    new BN6(1e4)
  );
  const normYActiveBinAllocation = normYAllocations.reduce(
    (maxBps, bps) => maxBps.sub(bps),
    new BN6(1e4)
  );
  return binIds.map((binId) => {
    if (binId === activeBin) {
      return {
        binId,
        xAmountBpsOfTotal: normXActiveBinAllocation,
        yAmountBpsOfTotal: normYActiveBinAllocation
      };
    }
    if (binId > activeBin) {
      return {
        binId,
        xAmountBpsOfTotal: normXAllocations.shift(),
        yAmountBpsOfTotal: new BN6(0)
      };
    }
    if (binId < activeBin) {
      return {
        binId,
        xAmountBpsOfTotal: new BN6(0),
        yAmountBpsOfTotal: normYAllocations.shift()
      };
    }
  });
}
function fromWeightDistributionToAmountOneSide(amount, distributions, binStep, activeId, depositForY, mint, clock) {
  if (depositForY) {
    return toAmountBidSide(activeId, amount, distributions, mint, clock);
  } else {
    return toAmountAskSide(
      activeId,
      binStep,
      amount,
      distributions,
      mint,
      clock
    );
  }
}
function fromWeightDistributionToAmount(amountX, amountY, distributions, binStep, activeId, amountXInActiveBin, amountYInActiveBin, mintX, mintY, clock) {
  var distributions = distributions.sort((n1, n2) => {
    return n1.binId - n2.binId;
  });
  if (distributions.length == 0) {
    return [];
  }
  if (activeId > distributions[distributions.length - 1].binId) {
    let amounts = toAmountBidSide(
      activeId,
      amountY,
      distributions,
      mintY,
      clock
    );
    return amounts.map((bin) => {
      return {
        binId: bin.binId,
        amountX: new BN6(0),
        amountY: new BN6(bin.amount.toString())
      };
    });
  }
  if (activeId < distributions[0].binId) {
    let amounts = toAmountAskSide(
      activeId,
      binStep,
      amountX,
      distributions,
      mintX,
      clock
    );
    return amounts.map((bin) => {
      return {
        binId: bin.binId,
        amountX: new BN6(bin.amount.toString()),
        amountY: new BN6(0)
      };
    });
  }
  return toAmountBothSide(
    activeId,
    binStep,
    amountX,
    amountY,
    amountXInActiveBin,
    amountYInActiveBin,
    distributions,
    mintX,
    mintY,
    clock
  );
}

// src/dlmm/helpers/math.ts
var Rounding = /* @__PURE__ */ ((Rounding2) => {
  Rounding2[Rounding2["Up"] = 0] = "Up";
  Rounding2[Rounding2["Down"] = 1] = "Down";
  return Rounding2;
})(Rounding || {});
function mulShr(x, y, offset, rounding) {
  const denominator = new BN7(1).shln(offset);
  return mulDiv(x, y, denominator, rounding);
}
function shlDiv(x, y, offset, rounding) {
  const scale = new BN7(1).shln(offset);
  return mulDiv(x, scale, y, rounding);
}
function mulDiv(x, y, denominator, rounding) {
  const { div, mod } = x.mul(y).divmod(denominator);
  if (rounding == 0 /* Up */ && !mod.isZero()) {
    return div.add(new BN7(1));
  }
  return div;
}
function computeBaseFactorFromFeeBps(binStep, feeBps) {
  const U16_MAX = 65535;
  const computedBaseFactor = feeBps.toNumber() * BASIS_POINT_MAX / binStep.toNumber();
  if (computedBaseFactor > U16_MAX) {
    let truncatedBaseFactor = computedBaseFactor;
    let base_power_factor = 0;
    while (truncatedBaseFactor > U16_MAX) {
      const remainder = truncatedBaseFactor % 10;
      if (remainder == 0) {
        base_power_factor += 1;
        truncatedBaseFactor /= 10;
      } else {
        throw "have decimals";
      }
    }
    return [new BN7(truncatedBaseFactor), new BN7(base_power_factor)];
  } else {
    const computedBaseFactorFloor = Math.floor(computedBaseFactor);
    if (computedBaseFactor != computedBaseFactorFloor) {
      if (computedBaseFactorFloor >= U16_MAX) {
        throw "base factor for the give fee bps overflow u16";
      }
      if (computedBaseFactorFloor == 0) {
        throw "base factor for the give fee bps underflow";
      }
      if (computedBaseFactor % 1 != 0) {
        throw "couldn't compute base factor for the exact fee bps";
      }
    }
    return [new BN7(computedBaseFactor), new BN7(0)];
  }
}
function getQPriceFromId(binId, binStep) {
  return pow(getQPriceBaseFactor(binStep), binId);
}
function getQPriceBaseFactor(binStep) {
  const bps = binStep.shln(SCALE_OFFSET).div(new BN7(BASIS_POINT_MAX));
  const base = ONE.add(bps);
  return base;
}
function getC(amount, binStep, binId, baseTokenDecimal, quoteTokenDecimal, minPrice, maxPrice, k) {
  const currentPricePerLamport = new Decimal5(1 + binStep / 1e4).pow(
    binId.toNumber()
  );
  const currentPricePerToken = currentPricePerLamport.mul(
    new Decimal5(10 ** (baseTokenDecimal - quoteTokenDecimal))
  );
  const priceRange = maxPrice.sub(minPrice);
  const currentPriceDeltaFromMin = currentPricePerToken.sub(
    new Decimal5(minPrice)
  );
  const c = new Decimal5(amount.toString()).mul(
    currentPriceDeltaFromMin.div(priceRange).pow(k)
  );
  return c.floor();
}
function distributeAmountToCompressedBinsByRatio(compressedBinAmount, uncompressedAmount, multiplier, binCapAmount) {
  const newCompressedBinAmount = /* @__PURE__ */ new Map();
  let totalCompressedAmount = new BN7(0);
  for (const compressedAmount of compressedBinAmount.values()) {
    totalCompressedAmount = totalCompressedAmount.add(compressedAmount);
  }
  let totalDepositedAmount = new BN7(0);
  for (const [binId, compressedAmount] of compressedBinAmount.entries()) {
    const depositAmount = compressedAmount.mul(uncompressedAmount).div(totalCompressedAmount);
    let compressedDepositAmount = depositAmount.div(multiplier);
    let newCompressedAmount = compressedAmount.add(compressedDepositAmount);
    if (newCompressedAmount.gt(binCapAmount)) {
      compressedDepositAmount = compressedDepositAmount.sub(
        newCompressedAmount.sub(binCapAmount)
      );
      newCompressedAmount = binCapAmount;
    }
    newCompressedBinAmount.set(binId, newCompressedAmount);
    totalDepositedAmount = totalDepositedAmount.add(
      compressedDepositAmount.mul(multiplier)
    );
  }
  const loss = uncompressedAmount.sub(totalDepositedAmount);
  return {
    newCompressedBinAmount,
    loss
  };
}
function getPositionCount(minBinId, maxBinId) {
  const binDelta = maxBinId.sub(minBinId);
  const positionCount = binDelta.div(DEFAULT_BIN_PER_POSITION);
  return positionCount.add(new BN7(1));
}
function findOptimumDecompressMultiplier(binAmount, tokenDecimal) {
  let multiplier = new BN7(10).pow(tokenDecimal);
  while (!multiplier.isZero()) {
    let found = true;
    for (const [_binId, amount] of binAmount) {
      const compressedAmount = amount.div(multiplier);
      if (compressedAmount.isZero()) {
        multiplier = multiplier.div(new BN7(10));
        found = false;
        break;
      }
    }
    if (found) {
      return multiplier;
    }
  }
  throw "Couldn't find optimum multiplier";
}
function compressBinAmount(binAmount, multiplier) {
  const compressedBinAmount = /* @__PURE__ */ new Map();
  let totalAmount = new BN7(0);
  let compressionLoss = new BN7(0);
  for (const [binId, amount] of binAmount) {
    totalAmount = totalAmount.add(amount);
    const compressedAmount = amount.div(multiplier);
    compressedBinAmount.set(binId, compressedAmount);
    let loss = amount.sub(compressedAmount.mul(multiplier));
    compressionLoss = compressionLoss.add(loss);
  }
  return {
    compressedBinAmount,
    compressionLoss
  };
}
function generateAmountForBinRange(amount, binStep, tokenXDecimal, tokenYDecimal, minBinId, maxBinId, k) {
  const toTokenMultiplier = new Decimal5(10 ** (tokenXDecimal - tokenYDecimal));
  const minPrice = getPriceOfBinByBinId(minBinId.toNumber(), binStep).mul(
    toTokenMultiplier
  );
  const maxPrice = getPriceOfBinByBinId(maxBinId.toNumber(), binStep).mul(
    toTokenMultiplier
  );
  const binAmounts = /* @__PURE__ */ new Map();
  for (let i = minBinId.toNumber(); i < maxBinId.toNumber(); i++) {
    const binAmount = generateBinAmount(
      amount,
      binStep,
      new BN7(i),
      tokenXDecimal,
      tokenYDecimal,
      minPrice,
      maxPrice,
      k
    );
    if (binAmount.isZero()) {
      throw "bin amount is zero";
    }
    binAmounts.set(i, binAmount);
  }
  return binAmounts;
}
function generateBinAmount(amount, binStep, binId, tokenXDecimal, tokenYDecimal, minPrice, maxPrice, k) {
  const c1 = getC(
    amount,
    binStep,
    binId.add(new BN7(1)),
    tokenXDecimal,
    tokenYDecimal,
    minPrice,
    maxPrice,
    k
  );
  const c0 = getC(
    amount,
    binStep,
    binId,
    tokenXDecimal,
    tokenYDecimal,
    minPrice,
    maxPrice,
    k
  );
  return new BN7(c1.sub(c0).floor().toString());
}

// src/dlmm/helpers/positions/index.ts
import BN9 from "bn.js";

// src/dlmm/helpers/positions/wrapper.ts
import BN8 from "bn.js";
function combineBaseAndExtendedPositionBinData(base, extended) {
  const combinedLiquidityShares = base.liquidityShares;
  const combinedRewardInfos = base.rewardInfos;
  const combinedFeeInfos = base.feeInfos;
  for (const binData of extended) {
    combinedLiquidityShares.push(binData.liquidityShare);
    combinedRewardInfos.push(binData.rewardInfo);
    combinedFeeInfos.push(binData.feeInfo);
  }
  return {
    liquidityShares: combinedLiquidityShares,
    rewardInfos: combinedRewardInfos,
    feeInfos: combinedFeeInfos
  };
}
function wrapPosition(program, key, account) {
  const disc = account.data.subarray(0, 8);
  if (disc.equals(Buffer.from(getAccountDiscriminator("positionV2")))) {
    const state = decodeAccount(
      program,
      "positionV2",
      account.data
    );
    const extended = decodeExtendedPosition(
      state,
      program,
      account.data.subarray(8 + POSITION_MIN_SIZE)
    );
    const combinedPositionBinData = combineBaseAndExtendedPositionBinData(
      state,
      extended
    );
    return new PositionV2Wrapper(key, state, extended, combinedPositionBinData);
  } else {
    throw new Error("Unknown position account");
  }
}
var PositionV2Wrapper = class {
  constructor(positionAddress, inner, extended, combinedPositionBinData) {
    this.positionAddress = positionAddress;
    this.inner = inner;
    this.extended = extended;
    this.combinedPositionBinData = combinedPositionBinData;
  }
  address() {
    return this.positionAddress;
  }
  totalClaimedRewards() {
    return this.inner.totalClaimedRewards;
  }
  feeOwner() {
    return this.inner.feeOwner;
  }
  lockReleasePoint() {
    return this.inner.lockReleasePoint;
  }
  operator() {
    return this.inner.operator;
  }
  totalClaimedFeeYAmount() {
    return this.inner.totalClaimedFeeYAmount;
  }
  totalClaimedFeeXAmount() {
    return this.inner.totalClaimedFeeXAmount;
  }
  lbPair() {
    return this.inner.lbPair;
  }
  lowerBinId() {
    return new BN8(this.inner.lowerBinId);
  }
  upperBinId() {
    return new BN8(this.inner.upperBinId);
  }
  liquidityShares() {
    return this.combinedPositionBinData.liquidityShares;
  }
  rewardInfos() {
    return this.combinedPositionBinData.rewardInfos;
  }
  feeInfos() {
    return this.combinedPositionBinData.feeInfos;
  }
  lastUpdatedAt() {
    return this.inner.lastUpdatedAt;
  }
  getBinArrayIndexesCoverage() {
    const isExtended = this.extended.length > 0;
    if (isExtended) {
      return getBinArrayIndexesCoverage(this.lowerBinId(), this.upperBinId());
    } else {
      const lowerBinArrayIndex = binIdToBinArrayIndex(this.lowerBinId());
      const upperBinArrayIndex = lowerBinArrayIndex.add(new BN8(1));
      return [lowerBinArrayIndex, upperBinArrayIndex];
    }
  }
  getBinArrayKeysCoverage(programId) {
    return this.getBinArrayIndexesCoverage().map(
      (index) => deriveBinArray(this.lbPair(), index, programId)[0]
    );
  }
  version() {
    return 1 /* V2 */;
  }
  owner() {
    return this.inner.owner;
  }
  width() {
    return this.upperBinId().sub(this.lowerBinId()).add(new BN8(1));
  }
};

// src/dlmm/helpers/positions/index.ts
function getBinArrayIndexesCoverage(lowerBinId, upperBinId) {
  const lowerBinArrayIndex = binIdToBinArrayIndex(lowerBinId);
  const upperBinArrayIndex = binIdToBinArrayIndex(upperBinId);
  const binArrayIndexes = [];
  for (let i = lowerBinArrayIndex.toNumber(); i <= upperBinArrayIndex.toNumber(); i++) {
    binArrayIndexes.push(new BN9(i));
  }
  return binArrayIndexes;
}
function getBinArrayKeysCoverage(lowerBinId, upperBinId, lbPair, programId) {
  const binArrayIndexes = getBinArrayIndexesCoverage(lowerBinId, upperBinId);
  return binArrayIndexes.map((index) => {
    return deriveBinArray(lbPair, index, programId)[0];
  });
}
function getBinArrayAccountMetasCoverage(lowerBinId, upperBinId, lbPair, programId) {
  return getBinArrayKeysCoverage(lowerBinId, upperBinId, lbPair, programId).map(
    (key) => {
      return {
        pubkey: key,
        isSigner: false,
        isWritable: true
      };
    }
  );
}
function getPositionLowerUpperBinIdWithLiquidity(position) {
  const binWithLiquidity = position.positionBinData.filter(
    (b) => !new BN9(b.binLiquidity).isZero() || !new BN9(b.positionFeeXAmount.toString()).isZero() || !new BN9(b.positionFeeYAmount.toString()).isZero() || !new BN9(b.positionRewardAmount[0].toString()).isZero() || !new BN9(b.positionRewardAmount[1].toString()).isZero()
  );
  return binWithLiquidity.length > 0 ? {
    lowerBinId: new BN9(binWithLiquidity[0].binId),
    upperBinId: new BN9(binWithLiquidity[binWithLiquidity.length - 1].binId)
  } : null;
}
function isPositionNoFee(position) {
  return position.feeX.isZero() && position.feeY.isZero();
}
function isPositionNoReward(position) {
  return position.rewardOne.isZero() && position.rewardTwo.isZero();
}
function chunkBinRangeIntoExtendedPositions(minBinId, maxBinId) {
  const chunkedBinRange = [];
  for (let currentMinBinId = minBinId; currentMinBinId <= maxBinId; currentMinBinId += POSITION_MAX_LENGTH.toNumber()) {
    const currentMaxBinId = Math.min(
      currentMinBinId + POSITION_MAX_LENGTH.toNumber() - 1,
      maxBinId
    );
    chunkedBinRange.push({
      lowerBinId: currentMinBinId,
      upperBinId: currentMaxBinId
    });
  }
  return chunkedBinRange;
}
function chunkBinRange(minBinId, maxBinId, binPerChunk) {
  const chunkedBinRange = [];
  let startBinId = minBinId;
  binPerChunk = binPerChunk ?? DEFAULT_BIN_PER_POSITION.toNumber();
  while (startBinId <= maxBinId) {
    const endBinId = Math.min(startBinId + binPerChunk - 1, maxBinId);
    chunkedBinRange.push({
      lowerBinId: startBinId,
      upperBinId: endBinId
    });
    startBinId += binPerChunk;
  }
  return chunkedBinRange;
}
function chunkPositionBinRange(position, minBinId, maxBinId) {
  const chunkedFeesAndRewards = [];
  let totalAmountX = new BN9(0);
  let totalAmountY = new BN9(0);
  let totalFeeXAmount = new BN9(0);
  let totalFeeYAmount = new BN9(0);
  let totalRewardAmounts = [new BN9(0), new BN9(0)];
  let count = 0;
  for (let i = 0; i < position.positionData.positionBinData.length; i++) {
    const positionBinData = position.positionData.positionBinData[i];
    if (positionBinData.binId >= minBinId && positionBinData.binId <= maxBinId) {
      totalFeeXAmount = totalFeeXAmount.add(
        new BN9(positionBinData.positionFeeXAmount)
      );
      totalFeeYAmount = totalFeeYAmount.add(
        new BN9(positionBinData.positionFeeYAmount)
      );
      totalAmountX = totalAmountX.add(new BN9(positionBinData.positionXAmount));
      totalAmountY = totalAmountY.add(new BN9(positionBinData.positionYAmount));
      for (const [
        index,
        reward
      ] of positionBinData.positionRewardAmount.entries()) {
        totalRewardAmounts[index] = totalRewardAmounts[index].add(
          new BN9(reward)
        );
      }
      count++;
    }
    if (count === DEFAULT_BIN_PER_POSITION.toNumber() || positionBinData.binId == maxBinId) {
      chunkedFeesAndRewards.push({
        minBinId: positionBinData.binId - count + 1,
        maxBinId: positionBinData.binId,
        feeXAmount: totalFeeXAmount,
        feeYAmount: totalFeeYAmount,
        rewardAmounts: totalRewardAmounts,
        amountX: totalAmountX,
        amountY: totalAmountY
      });
      totalFeeXAmount = new BN9(0);
      totalFeeYAmount = new BN9(0);
      totalAmountX = new BN9(0);
      totalAmountY = new BN9(0);
      totalRewardAmounts = [new BN9(0), new BN9(0)];
      count = 0;
    }
  }
  return chunkedFeesAndRewards;
}
function calculatePositionSize(binCount) {
  const extraBinCount = binCount.gt(DEFAULT_BIN_PER_POSITION) ? binCount.sub(DEFAULT_BIN_PER_POSITION) : new BN9(0);
  return new BN9(POSITION_MIN_SIZE).add(
    extraBinCount.mul(new BN9(POSITION_BIN_DATA_SIZE))
  );
}
function getPositionRentExemption(connection, binCount) {
  const size = calculatePositionSize(binCount);
  return connection.getMinimumBalanceForRentExemption(size.toNumber());
}
async function getPositionExpandRentExemption(currentMinBinId, currentMaxBinId, connection, binCountToExpand) {
  const currentPositionWidth = currentMaxBinId.sub(currentMinBinId).addn(1);
  const positionWidthAfterExpand = currentPositionWidth.add(binCountToExpand);
  if (positionWidthAfterExpand.lte(DEFAULT_BIN_PER_POSITION)) {
    return 0;
  } else {
    const binCountInExpandedBytes = positionWidthAfterExpand.sub(
      DEFAULT_BIN_PER_POSITION
    );
    const expandSize = binCountInExpandedBytes.toNumber() * POSITION_BIN_DATA_SIZE;
    const [minimumLamports, rentExemptionLamports] = await Promise.all([
      connection.getMinimumBalanceForRentExemption(0),
      connection.getMinimumBalanceForRentExemption(expandSize)
    ]);
    return rentExemptionLamports - minimumLamports;
  }
}
function getExtendedPositionBinCount(minBinId, maxBinId) {
  const width = maxBinId.sub(minBinId).addn(1);
  const extended = width.sub(DEFAULT_BIN_PER_POSITION);
  return extended.lte(new BN9(0)) ? new BN9(0) : extended;
}
function decodeExtendedPosition(base, program, bytes) {
  const width = base.upperBinId - base.lowerBinId + 1;
  const extendedWidth = width - DEFAULT_BIN_PER_POSITION.toNumber();
  const extendedPosition = [];
  for (let i = 0; i < extendedWidth; i++) {
    const offset = i * POSITION_BIN_DATA_SIZE;
    const data = bytes.subarray(offset, offset + POSITION_BIN_DATA_SIZE);
    const decodedPositionBinData = program.coder.types.decode(
      // TODO: Find a type safe way
      "positionBinData",
      data
    );
    extendedPosition.push(decodedPositionBinData);
  }
  return extendedPosition;
}

// src/dlmm/helpers/binArray.ts
function internalBitmapRange() {
  const lowerBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.neg();
  const upperBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.sub(new BN10(1));
  return [lowerBinArrayIndex, upperBinArrayIndex];
}
function buildBitmapFromU64Arrays(u64Arrays, type) {
  const buffer = Buffer.concat(
    u64Arrays.map((b) => {
      return b.toArrayLike(Buffer, "le", 8);
    })
  );
  return new BN10(buffer, "le");
}
function bitmapTypeDetail(type) {
  if (type == 0 /* U1024 */) {
    return {
      bits: 1024,
      bytes: 1024 / 8
    };
  } else {
    return {
      bits: 512,
      bytes: 512 / 8
    };
  }
}
function mostSignificantBit(number, bitLength) {
  const highestIndex = bitLength - 1;
  if (number.isZero()) {
    return null;
  }
  for (let i = highestIndex; i >= 0; i--) {
    if (number.testn(i)) {
      return highestIndex - i;
    }
  }
  return null;
}
function leastSignificantBit(number, bitLength) {
  if (number.isZero()) {
    return null;
  }
  for (let i = 0; i < bitLength; i++) {
    if (number.testn(i)) {
      return i;
    }
  }
  return null;
}
function extensionBitmapRange() {
  return [
    BIN_ARRAY_BITMAP_SIZE.neg().mul(
      EXTENSION_BINARRAY_BITMAP_SIZE.add(new BN10(1))
    ),
    BIN_ARRAY_BITMAP_SIZE.mul(
      EXTENSION_BINARRAY_BITMAP_SIZE.add(new BN10(1))
    ).sub(new BN10(1))
  ];
}
function findSetBit(startIndex, endIndex, binArrayBitmapExtension) {
  const getBinArrayOffset = (binArrayIndex) => {
    return binArrayIndex.gt(new BN10(0)) ? binArrayIndex.mod(BIN_ARRAY_BITMAP_SIZE) : binArrayIndex.add(new BN10(1)).neg().mod(BIN_ARRAY_BITMAP_SIZE);
  };
  const getBitmapOffset = (binArrayIndex) => {
    return binArrayIndex.gt(new BN10(0)) ? binArrayIndex.div(BIN_ARRAY_BITMAP_SIZE).sub(new BN10(1)) : binArrayIndex.add(new BN10(1)).neg().div(BIN_ARRAY_BITMAP_SIZE).sub(new BN10(1));
  };
  if (startIndex <= endIndex) {
    for (let i = startIndex; i <= endIndex; i++) {
      const binArrayOffset = getBinArrayOffset(new BN10(i)).toNumber();
      const bitmapOffset = getBitmapOffset(new BN10(i)).toNumber();
      const bitmapChunks = i > 0 ? binArrayBitmapExtension.positiveBinArrayBitmap[bitmapOffset] : binArrayBitmapExtension.negativeBinArrayBitmap[bitmapOffset];
      const bitmap = buildBitmapFromU64Arrays(bitmapChunks, 1 /* U512 */);
      if (bitmap.testn(binArrayOffset)) {
        return i;
      }
    }
  } else {
    for (let i = startIndex; i >= endIndex; i--) {
      const binArrayOffset = getBinArrayOffset(new BN10(i)).toNumber();
      const bitmapOffset = getBitmapOffset(new BN10(i)).toNumber();
      const bitmapChunks = i > 0 ? binArrayBitmapExtension.positiveBinArrayBitmap[bitmapOffset] : binArrayBitmapExtension.negativeBinArrayBitmap[bitmapOffset];
      const bitmap = buildBitmapFromU64Arrays(bitmapChunks, 1 /* U512 */);
      if (bitmap.testn(binArrayOffset)) {
        return i;
      }
    }
  }
  return null;
}
function isOverflowDefaultBinArrayBitmap(binArrayIndex) {
  const [minBinArrayIndex, maxBinArrayIndex] = internalBitmapRange();
  return binArrayIndex.gt(maxBinArrayIndex) || binArrayIndex.lt(minBinArrayIndex);
}
function deriveBinArrayBitmapExtension(lbPair, programId) {
  return PublicKey5.findProgramAddressSync(
    [Buffer.from("bitmap"), lbPair.toBytes()],
    programId
  );
}
function binIdToBinArrayIndex(binId) {
  const { div: idx, mod } = binId.divmod(MAX_BIN_ARRAY_SIZE);
  return binId.isNeg() && !mod.isZero() ? idx.sub(new BN10(1)) : idx;
}
function getBinArrayLowerUpperBinId(binArrayIndex) {
  const lowerBinId = binArrayIndex.mul(MAX_BIN_ARRAY_SIZE);
  const upperBinId = lowerBinId.add(MAX_BIN_ARRAY_SIZE).sub(new BN10(1));
  return [lowerBinId, upperBinId];
}
function isBinIdWithinBinArray(activeId, binArrayIndex) {
  const [lowerBinId, upperBinId] = getBinArrayLowerUpperBinId(binArrayIndex);
  return activeId.gte(lowerBinId) && activeId.lte(upperBinId);
}
function getBinFromBinArray(binId, binArray) {
  const [lowerBinId, upperBinId] = getBinArrayLowerUpperBinId(binArray.index);
  let index = 0;
  if (binId > 0) {
    index = binId - lowerBinId.toNumber();
  } else {
    const delta = upperBinId.toNumber() - binId;
    index = MAX_BIN_ARRAY_SIZE.toNumber() - delta - 1;
  }
  return binArray.bins[index];
}
function findNextBinArrayIndexWithLiquidity(swapForY, activeId, lbPairState, binArrayBitmapExtension) {
  const [lowerBinArrayIndex, upperBinArrayIndex] = internalBitmapRange();
  let startBinArrayIndex = binIdToBinArrayIndex(activeId);
  while (true) {
    if (isOverflowDefaultBinArrayBitmap(startBinArrayIndex)) {
      if (binArrayBitmapExtension === null) {
        return null;
      }
      const [minBinArrayIndex, maxBinArrayIndex] = extensionBitmapRange();
      if (startBinArrayIndex.isNeg()) {
        if (swapForY) {
          const binArrayIndex = findSetBit(
            startBinArrayIndex.toNumber(),
            minBinArrayIndex.toNumber(),
            binArrayBitmapExtension
          );
          if (binArrayIndex !== null) {
            return new BN10(binArrayIndex);
          } else {
            return null;
          }
        } else {
          const binArrayIndex = findSetBit(
            startBinArrayIndex.toNumber(),
            BIN_ARRAY_BITMAP_SIZE.neg().sub(new BN10(1)).toNumber(),
            binArrayBitmapExtension
          );
          if (binArrayIndex !== null) {
            return new BN10(binArrayIndex);
          } else {
            startBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.neg();
          }
        }
      } else {
        if (swapForY) {
          const binArrayIndex = findSetBit(
            startBinArrayIndex.toNumber(),
            BIN_ARRAY_BITMAP_SIZE.toNumber(),
            binArrayBitmapExtension
          );
          if (binArrayIndex !== null) {
            return new BN10(binArrayIndex);
          } else {
            startBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.sub(new BN10(1));
          }
        } else {
          const binArrayIndex = findSetBit(
            startBinArrayIndex.toNumber(),
            maxBinArrayIndex.toNumber(),
            binArrayBitmapExtension
          );
          if (binArrayIndex !== null) {
            return new BN10(binArrayIndex);
          } else {
            return null;
          }
        }
      }
    } else {
      const bitmapType = 0 /* U1024 */;
      const bitmapDetail = bitmapTypeDetail(bitmapType);
      const offset = startBinArrayIndex.add(BIN_ARRAY_BITMAP_SIZE);
      const bitmap = buildBitmapFromU64Arrays(
        lbPairState.binArrayBitmap,
        bitmapType
      );
      if (swapForY) {
        const upperBitRange = new BN10(bitmapDetail.bits - 1).sub(offset);
        const croppedBitmap = bitmap.shln(upperBitRange.toNumber());
        const msb = mostSignificantBit(croppedBitmap, bitmapDetail.bits);
        if (msb !== null) {
          return startBinArrayIndex.sub(new BN10(msb));
        } else {
          startBinArrayIndex = lowerBinArrayIndex.sub(new BN10(1));
        }
      } else {
        const lowerBitRange = offset;
        const croppedBitmap = bitmap.shrn(lowerBitRange.toNumber());
        const lsb = leastSignificantBit(croppedBitmap, bitmapDetail.bits);
        if (lsb !== null) {
          return startBinArrayIndex.add(new BN10(lsb));
        } else {
          startBinArrayIndex = upperBinArrayIndex.add(new BN10(1));
        }
      }
    }
  }
}
function findNextBinArrayWithLiquidity(swapForY, activeBinId, lbPairState, binArrayBitmapExtension, binArrays) {
  const nearestBinArrayIndexWithLiquidity = findNextBinArrayIndexWithLiquidity(
    swapForY,
    activeBinId,
    lbPairState,
    binArrayBitmapExtension
  );
  if (nearestBinArrayIndexWithLiquidity == null) {
    return null;
  }
  const binArrayAccount = binArrays.find(
    (ba) => ba.account.index.eq(nearestBinArrayIndexWithLiquidity)
  );
  if (!binArrayAccount) {
    return null;
  }
  return binArrayAccount;
}
function getBinArraysRequiredByPositionRange(pair, fromBinId, toBinId, programId) {
  const [minBinId, maxBinId] = fromBinId.lt(toBinId) ? [fromBinId, toBinId] : [toBinId, fromBinId];
  const positionCount = getPositionCount(minBinId, maxBinId);
  const binArrays = /* @__PURE__ */ new Map();
  for (let i = 0; i < positionCount.toNumber(); i++) {
    const lowerBinId = minBinId.add(DEFAULT_BIN_PER_POSITION.mul(new BN10(i)));
    const lowerBinArrayIndex = binIdToBinArrayIndex(lowerBinId);
    const upperBinArrayIndex = lowerBinArrayIndex.add(new BN10(1));
    const [lowerBinArray] = deriveBinArray(pair, lowerBinArrayIndex, programId);
    const [upperBinArray] = deriveBinArray(pair, upperBinArrayIndex, programId);
    binArrays.set(lowerBinArray.toBase58(), lowerBinArrayIndex);
    binArrays.set(upperBinArray.toBase58(), upperBinArrayIndex);
  }
  return Array.from(binArrays, ([key, index]) => ({
    key: new PublicKey5(key),
    index
  }));
}
function getBinArraysRequiredByPositionRange2(pair, fromBinId, toBinId, programId) {
  const [minBinId, maxBinId] = fromBinId.lt(toBinId) ? [fromBinId, toBinId] : [toBinId, fromBinId];
  const binArrayIndexes = getBinArrayIndexesCoverage(minBinId, maxBinId);
  return Array.from(binArrayIndexes, (index) => {
    const [binArrayPubkey] = deriveBinArray(pair, index, programId);
    return {
      key: binArrayPubkey,
      index
    };
  });
}
function* enumerateBins(binsById, lowerBinId, upperBinId, binStep, baseTokenDecimal, quoteTokenDecimal, version, lbPair) {
  for (let currentBinId = lowerBinId; currentBinId <= upperBinId; currentBinId++) {
    const bin = binsById.get(currentBinId);
    if (bin != null) {
      yield BinLiquidity.fromBin(
        bin,
        currentBinId,
        binStep,
        baseTokenDecimal,
        quoteTokenDecimal,
        version,
        lbPair
      );
    } else {
      yield BinLiquidity.empty(
        currentBinId,
        binStep,
        baseTokenDecimal,
        quoteTokenDecimal,
        version
      );
    }
  }
}
function getBinIdIndexInBinArray(binId, lowerBinId, upperBinId) {
  if (binId.lt(lowerBinId) || binId.gt(upperBinId)) {
    return null;
  }
  return binId.sub(lowerBinId);
}
function binDeltaToMinMaxBinId(binDelta, activeBinId) {
  const minBinId = activeBinId - binDelta;
  const maxBinId = minBinId + binDelta * 2;
  return {
    minBinId,
    maxBinId
  };
}
function decodeRewardPerTokenStored(bin) {
  const rewardPerTokenStored0Buf0 = bin.fulfilledOrderAmountX.toArrayLike(
    Buffer,
    "le",
    8
  );
  const rewardPerTokenStored0Buf1 = bin.fulfilledOrderAmountY.toArrayLike(
    Buffer,
    "le",
    8
  );
  const rewardPerTokenStored0 = new BN10(
    Buffer.concat([rewardPerTokenStored0Buf0, rewardPerTokenStored0Buf1]),
    "le"
  );
  const rewardPerTokenStored1Buf0 = bin.limitOrderFeeAskSide.toArrayLike(
    Buffer,
    "le",
    8
  );
  const rewardPerTokenStored1Buf1 = bin.limitOrderFeeBidSide.toArrayLike(
    Buffer,
    "le",
    8
  );
  const rewardPerTokenStored1 = new BN10(
    Buffer.concat([rewardPerTokenStored1Buf0, rewardPerTokenStored1Buf1]),
    "le"
  );
  return [rewardPerTokenStored0, rewardPerTokenStored1];
}
function getBinArrayInfoForNonContiguousBinIds(binIds, programId, lbPair) {
  let binArrayBitmapExtension = programId;
  const binArrayIndexes = /* @__PURE__ */ new Set();
  for (const binId of binIds) {
    const binArrayIndex = binIdToBinArrayIndex(new BN10(binId));
    if (isOverflowDefaultBinArrayBitmap(binArrayIndex) && binArrayBitmapExtension.equals(programId)) {
      binArrayBitmapExtension = deriveBinArrayBitmapExtension(
        lbPair,
        programId
      )[0];
    }
    binArrayIndexes.add(binArrayIndex.toNumber());
  }
  const binArrayPubkeys = [...binArrayIndexes].map(
    (idx) => deriveBinArray(lbPair, new BN10(idx), programId)[0]
  );
  const binArrayAccountMetas = binArrayPubkeys.map((pubkey) => {
    return {
      pubkey,
      isSigner: false,
      isWritable: true
    };
  });
  return {
    binArrayAccountMetas,
    binArrayBitmapExtension,
    binArrayIndexes: [...binArrayIndexes].map((idx) => new BN10(idx))
  };
}

// src/dlmm/helpers/computeUnit.ts
import {
  ComputeBudgetProgram,
  PublicKey as PublicKey6,
  TransactionMessage,
  VersionedTransaction
} from "@solana/web3.js";
var DEFAULT_ADD_LIQUIDITY_CU = 1e6;
var DEFAULT_EXTEND_POSITION_HIGH_CU = 1e6;
var DEFAULT_EXTEND_POSITION_LOW_CU = 3e4;
var DEFAULT_INIT_POSITION_CU = 3e4;
var DEFAULT_INIT_BIN_ARRAY_CU = 35e4;
var MIN_CU_BUFFER = 5e4;
var MAX_CU_BUFFER = 2e5;
var MAX_CU = 14e5;
var getDefaultExtendPositionCU = (side) => {
  switch (side) {
    case 0 /* Lower */:
      return DEFAULT_EXTEND_POSITION_HIGH_CU;
    case 1 /* Upper */:
      return DEFAULT_EXTEND_POSITION_LOW_CU;
  }
};
var getSimulationComputeUnits = async (connection, instructions, payer, lookupTables, commitment = "confirmed") => {
  const testInstructions = [
    // Set an arbitrarily high number in simulation
    // so we can be sure the transaction will succeed
    // and get the real compute units used
    ComputeBudgetProgram.setComputeUnitLimit({ units: 14e5 }),
    ...instructions
  ];
  const testTransaction = new VersionedTransaction(
    new TransactionMessage({
      instructions: testInstructions,
      payerKey: payer,
      // RecentBlockhash can by any public key during simulation
      // since 'replaceRecentBlockhash' is set to 'true' below
      recentBlockhash: PublicKey6.default.toString()
    }).compileToV0Message(lookupTables)
  );
  const rpcResponse = await connection.simulateTransaction(testTransaction, {
    replaceRecentBlockhash: true,
    sigVerify: false,
    commitment
  });
  if (rpcResponse?.value?.err) {
    const logs = rpcResponse.value.logs?.join("\n  \u2022 ") || "No logs available";
    throw new Error(
      `Transaction simulation failed:
  \u2022${logs}` + JSON.stringify(rpcResponse?.value?.err)
    );
  }
  return rpcResponse.value.unitsConsumed || null;
};

// src/dlmm/helpers/rebalance/rebalancePosition.ts
import { SYSVAR_CLOCK_PUBKEY } from "@solana/web3.js";
import BN12 from "bn.js";
import Decimal6 from "decimal.js";

// src/dlmm/helpers/fee.ts
import { BN as BN11 } from "@coral-xyz/anchor";
function getBaseFee(binStep, sParameter) {
  return new BN11(sParameter.baseFactor).mul(new BN11(binStep)).mul(new BN11(10)).mul(new BN11(10).pow(new BN11(sParameter.baseFeePowerFactor)));
}
function getVariableFee(binStep, sParameter, vParameter) {
  if (sParameter.variableFeeControl > 0) {
    const square_vfa_bin = new BN11(vParameter.volatilityAccumulator).mul(new BN11(binStep)).pow(new BN11(2));
    const v_fee = new BN11(sParameter.variableFeeControl).mul(square_vfa_bin);
    return v_fee.add(new BN11(99999999999)).div(new BN11(1e11));
  }
  return new BN11(0);
}
function getTotalFee(binStep, sParameter, vParameter) {
  const totalFee = getBaseFee(binStep, sParameter).add(
    getVariableFee(binStep, sParameter, vParameter)
  );
  return totalFee.gt(MAX_FEE_RATE) ? MAX_FEE_RATE : totalFee;
}
function computeFee(binStep, sParameter, vParameter, inAmount) {
  const totalFee = getTotalFee(binStep, sParameter, vParameter);
  const denominator = FEE_PRECISION.sub(totalFee);
  return inAmount.mul(totalFee).add(denominator).sub(new BN11(1)).div(denominator);
}
function computeFeeFromAmount(binStep, sParameter, vParameter, inAmountWithFees) {
  const totalFee = getTotalFee(binStep, sParameter, vParameter);
  return inAmountWithFees.mul(totalFee).add(FEE_PRECISION.sub(new BN11(1))).div(FEE_PRECISION);
}
function computeProtocolFee(feeAmount, sParameter) {
  return feeAmount.mul(new BN11(sParameter.protocolShare)).div(new BN11(BASIS_POINT_MAX));
}
function getExcludedFeeAmount(includedFeeAmount, tradeFeeNumerator) {
  const tradingFee = includedFeeAmount.mul(tradeFeeNumerator).add(FEE_PRECISION.sub(new BN11(1))).div(FEE_PRECISION);
  const excludedFeeAmount = includedFeeAmount.sub(tradingFee);
  return {
    excludedFeeAmount,
    fee: tradingFee
  };
}
function getIncludedFeeAmount(excludedFeeAmount, tradeFeeNumerator) {
  const denominator = FEE_PRECISION.sub(tradeFeeNumerator);
  const includedFeeAmount = excludedFeeAmount.mul(FEE_PRECISION).add(denominator.sub(new BN11(1))).div(denominator);
  const fee = includedFeeAmount.sub(excludedFeeAmount);
  return {
    includedFeeAmount,
    fee
  };
}
function splitFee(tradingFee, protocolShare, mmAmountIn, totalAmountIn) {
  if (totalAmountIn.isZero()) {
    return {
      fee: new BN11(0),
      protocolFee: new BN11(0)
    };
  }
  const mmFee = tradingFee.mul(mmAmountIn).add(totalAmountIn.sub(new BN11(1))).div(totalAmountIn);
  const totalLoFee = tradingFee.sub(mmFee);
  const loFee = totalLoFee.mul(LIMIT_ORDER_FEE_SHARE).div(new BN11(BASIS_POINT_MAX));
  const loProtocolFee = totalLoFee.sub(loFee);
  const mmProtocolFee = mmFee.mul(protocolShare).div(new BN11(BASIS_POINT_MAX));
  const totalProtocolFee = loProtocolFee.add(mmProtocolFee);
  const totalUserFee = tradingFee.sub(totalProtocolFee);
  return {
    fee: totalUserFee,
    protocolFee: totalProtocolFee
  };
}

// src/dlmm/helpers/rebalance/rebalancePosition.ts
function buildBitFlagAndNegateStrategyParameters(x0, y0, deltaX, deltaY) {
  let bitFlag = 0;
  if (x0.isNeg()) {
    bitFlag |= 1;
    x0 = x0.neg();
  }
  if (y0.isNeg()) {
    bitFlag |= 2;
    y0 = y0.neg();
  }
  if (deltaX.isNeg()) {
    bitFlag |= 4;
    deltaX = deltaX.neg();
  }
  if (deltaY.isNeg()) {
    bitFlag |= 8;
    deltaY = deltaY.neg();
  }
  return {
    bitFlag,
    x0,
    y0,
    deltaX,
    deltaY
  };
}
function toRebalancePositionBinData(positionData) {
  return positionData.positionBinData.map(
    ({
      binId,
      price,
      pricePerToken,
      positionXAmount,
      positionYAmount,
      positionFeeXAmount,
      positionFeeYAmount,
      positionRewardAmount
    }) => {
      return {
        binId,
        price,
        pricePerToken,
        amountX: new BN12(positionXAmount),
        amountY: new BN12(positionYAmount),
        claimableRewardAmount: positionRewardAmount.map(
          (amount) => new BN12(amount)
        ),
        claimableFeeXAmount: new BN12(positionFeeXAmount),
        claimableFeeYAmount: new BN12(positionFeeYAmount)
      };
    }
  );
}
function getDepositBinIds(activeId, deposits) {
  const uniqueBinId = /* @__PURE__ */ new Set();
  for (const { minDeltaId, maxDeltaId } of deposits) {
    const minBinId = activeId.add(minDeltaId);
    const maxBinId = activeId.add(maxDeltaId);
    for (let binId = minBinId.toNumber(); binId <= maxBinId.toNumber(); binId++) {
      uniqueBinId.add(binId);
    }
  }
  const binIds = Array.from(uniqueBinId);
  binIds.sort((a, b) => a - b);
  return binIds;
}
function findMinMaxBinIdWithLiquidity(rebalancePositionBinData) {
  let minBinId = null;
  let maxBinId = null;
  for (const binData of rebalancePositionBinData) {
    if (binData.amountX.isZero() && binData.amountY.isZero() && binData.claimableFeeXAmount.isZero() && binData.claimableFeeYAmount.isZero() && binData.claimableRewardAmount.every((amount) => amount.isZero())) {
      continue;
    }
    if (minBinId == null || binData.binId < minBinId) {
      minBinId = binData.binId;
    }
    if (maxBinId == null || binData.binId > maxBinId) {
      maxBinId = binData.binId;
    }
  }
  return [minBinId, maxBinId];
}
function onlyDepositToBidSide(maxDeltaId, favorXInActiveBin) {
  if (favorXInActiveBin) {
    return maxDeltaId.lt(new BN12(0));
  }
  return maxDeltaId.lte(new BN12(0));
}
function onlyDepositToAskSide(minDeltaId, favorXInActiveBin) {
  if (favorXInActiveBin) {
    return minDeltaId.gte(new BN12(0));
  }
  return minDeltaId.gt(new BN12(0));
}
function getAmountInBinsBidSide(activeId, minDeltaId, maxDeltaId, deltaY, y0) {
  const amountInBins = [];
  const minBinId = activeId.add(minDeltaId);
  const maxBinId = activeId.add(maxDeltaId);
  for (let binId = minBinId.toNumber(); binId <= maxBinId.toNumber(); binId++) {
    const deltaBin = activeId.toNumber() - binId;
    const totalDeltaY = deltaY.mul(new BN12(deltaBin));
    const amountY = y0.add(totalDeltaY);
    amountInBins.push({
      binId: new BN12(binId),
      amountX: new BN12(0),
      amountY
    });
  }
  return amountInBins;
}
function getAmountInBinsAskSide(activeId, binStep, minDeltaId, maxDeltaId, deltaX, x0) {
  const binCount = maxDeltaId.sub(minDeltaId).add(new BN12(1));
  const minBinId = activeId.add(minDeltaId);
  const maxBinId = activeId.add(maxDeltaId);
  const amountInBins = new Array(binCount.toNumber());
  const base = getQPriceBaseFactor(binStep);
  let inverseBasePrice = pow(base, maxBinId.neg());
  for (let binId = maxBinId.toNumber(); binId >= minBinId.toNumber(); binId--) {
    const delta = binId - activeId.toNumber();
    const totalDeltaX = deltaX.mul(new BN12(delta));
    const amountX = x0.add(totalDeltaX).mul(inverseBasePrice).shrn(SCALE_OFFSET);
    const idx = binId - minBinId.toNumber();
    amountInBins[idx] = {
      binId: new BN12(binId),
      amountX,
      amountY: new BN12(0)
    };
    inverseBasePrice = inverseBasePrice.mul(base).shrn(SCALE_OFFSET);
  }
  return amountInBins;
}
function toAmountIntoBins(activeId, minDeltaId, maxDeltaId, deltaX, deltaY, x0, y0, binStep, favorXInActiveBin) {
  if (onlyDepositToBidSide(maxDeltaId, favorXInActiveBin)) {
    return getAmountInBinsBidSide(activeId, minDeltaId, maxDeltaId, deltaY, y0);
  }
  if (onlyDepositToAskSide(minDeltaId, favorXInActiveBin)) {
    return getAmountInBinsAskSide(
      activeId,
      binStep,
      minDeltaId,
      maxDeltaId,
      deltaX,
      x0
    );
  }
  const [bidSideEndDeltaId, askSideStartDeltaId] = favorXInActiveBin ? [-1, 0] : [0, 1];
  const amountInBinsBidSide = getAmountInBinsBidSide(
    activeId,
    minDeltaId,
    new BN12(bidSideEndDeltaId),
    deltaY,
    y0
  );
  const amountInBinsAskSide = getAmountInBinsAskSide(
    activeId,
    binStep,
    new BN12(askSideStartDeltaId),
    maxDeltaId,
    deltaX,
    x0
  );
  return amountInBinsBidSide.concat(amountInBinsAskSide);
}
function getLiquidity(x, y, price) {
  const px = price.mul(x);
  const shly = y.shln(SCALE_OFFSET);
  return px.add(shly);
}
function computeCompositionFee(binStep, sParameters3, vParameters3, outAmountX, inAmountX, outAmountY, inAmountY) {
  if (outAmountX.gt(inAmountX)) {
    const delta = inAmountY.sub(outAmountY);
    const totalFeeRate = getTotalFee(
      binStep.toNumber(),
      sParameters3,
      vParameters3
    );
    const feeAmount = delta.mul(totalFeeRate);
    return feeAmount.mul(FEE_PRECISION.add(totalFeeRate)).div(FEE_PRECISION.pow(new BN12(2)));
  }
  return new BN12(0);
}
function simulateDepositBin(binId, binStep, amountX, amountY, bin) {
  if (!bin) {
    return {
      amountXIntoBin: amountX,
      amountYIntoBin: amountY
    };
  }
  const price = getQPriceFromId(binId, binStep);
  const inLiquidity = getLiquidity(amountX, amountY, price);
  const binLiquidity = getLiquidity(bin.amountX, bin.amountY, price);
  if (bin.liquiditySupply.isZero()) {
    return {
      amountXIntoBin: amountX,
      amountYIntoBin: amountY
    };
  }
  const liquidityShare = inLiquidity.mul(bin.liquiditySupply).div(binLiquidity);
  const updatedBinXAmount = bin.amountX.add(amountX);
  const updatedBinYAmount = bin.amountY.add(amountY);
  const updatedBinSupply = bin.liquiditySupply.add(liquidityShare);
  let amountXIntoBin = liquidityShare.mul(
    updatedBinXAmount.div(updatedBinSupply)
  );
  let amountYIntoBin = liquidityShare.mul(
    updatedBinYAmount.div(updatedBinSupply)
  );
  if (amountXIntoBin.gt(amountX)) {
  }
  return {
    amountXIntoBin,
    amountYIntoBin
  };
}
var RebalancePosition = class {
  address;
  lowerBinId;
  upperBinId;
  lbPair;
  owner;
  shouldClaimFee;
  shouldClaimReward;
  rebalancePositionBinData;
  activeBin;
  currentTimestamp;
  constructor(positionAddress, positionData, lbPair, activeBin, shouldClaimFee, shouldClaimReward, currentTimestamp) {
    this.address = positionAddress;
    this.rebalancePositionBinData = toRebalancePositionBinData(positionData);
    this.lowerBinId = new BN12(positionData.lowerBinId);
    this.upperBinId = new BN12(positionData.upperBinId);
    this.lbPair = lbPair;
    this.shouldClaimFee = shouldClaimFee;
    this.shouldClaimReward = shouldClaimReward;
    this.owner = positionData.owner;
    this.activeBin = activeBin;
    this.currentTimestamp = currentTimestamp;
  }
  static async create(params) {
    const {
      program,
      positionAddress,
      pairAddress,
      positionData,
      shouldClaimFee,
      shouldClaimReward
    } = params;
    const [lbPairAccount, clockAccount] = await program.provider.connection.getMultipleAccountsInfo([
      pairAddress,
      SYSVAR_CLOCK_PUBKEY
    ]);
    const lbPair = decodeAccount(program, "lbPair", lbPairAccount.data);
    const clock = ClockLayout.decode(clockAccount.data);
    const activeBinArrayIdx = binIdToBinArrayIndex(new BN12(lbPair.activeId));
    const [activeBinArrayPubkey] = deriveBinArray(
      pairAddress,
      activeBinArrayIdx,
      program.programId
    );
    const [lowerBinId, upperBinId] = getBinArrayLowerUpperBinId(activeBinArrayIdx);
    const idx = getBinIdIndexInBinArray(
      new BN12(lbPair.activeId),
      lowerBinId,
      upperBinId
    );
    let activeBin = null;
    try {
      const activeBinArrayState = await program.account.binArray.fetch(activeBinArrayPubkey);
      activeBin = activeBinArrayState[idx.toNumber()];
    } catch (error) {
    }
    return new RebalancePosition(
      positionAddress,
      positionData,
      lbPair,
      activeBin,
      shouldClaimFee,
      shouldClaimReward,
      clock.unixTimestamp
    );
  }
  _simulateDeposit(binStep, tokenXDecimal, tokenYDecimal, deposits, simulatedWithdrawResult) {
    const { liquidityAndFeeXWithdrawn, liquidityAndFeeYWithdrawn } = simulatedWithdrawResult;
    const activeId = new BN12(this.lbPair.activeId);
    const depositBinIds = getDepositBinIds(activeId, deposits);
    if (depositBinIds.length > 0) {
      const depositMinBinId = depositBinIds[0];
      const depositMaxBinId = depositBinIds[depositBinIds.length - 1];
      this._simulateResize(
        new BN12(depositMinBinId),
        new BN12(depositMaxBinId),
        binStep,
        tokenXDecimal,
        tokenYDecimal
      );
    }
    let totalAmountXDeposited = new BN12(0);
    let totalAmountYDeposited = new BN12(0);
    const addLiquidityParam = [];
    for (const {
      x0,
      y0,
      favorXInActiveBin,
      deltaX,
      deltaY,
      minDeltaId,
      maxDeltaId
    } of deposits) {
      const params = buildBitFlagAndNegateStrategyParameters(
        x0,
        y0,
        deltaX,
        deltaY
      );
      addLiquidityParam.push({
        minDeltaId: minDeltaId.toNumber(),
        maxDeltaId: maxDeltaId.toNumber(),
        x0: params.x0,
        y0: params.y0,
        deltaX: params.deltaX,
        deltaY: params.deltaY,
        bitFlag: params.bitFlag,
        padding: Array(16).fill(0),
        favorXInActiveId: favorXInActiveBin
      });
      const amountIntoBins = toAmountIntoBins(
        activeId,
        minDeltaId,
        maxDeltaId,
        deltaX,
        deltaY,
        x0,
        y0,
        binStep,
        favorXInActiveBin
      );
      for (const { binId, amountX, amountY } of amountIntoBins) {
        totalAmountXDeposited = totalAmountXDeposited.add(amountX);
        totalAmountYDeposited = totalAmountYDeposited.add(amountY);
        const idx = this.rebalancePositionBinData.findIndex(
          (data) => data.binId == binId.toNumber()
        );
        if (binId.eq(activeId)) {
          const vParameters3 = Object.assign({}, this.lbPair.vParameters);
          const sParameters3 = Object.assign({}, this.lbPair.parameters);
          DLMM.updateReference(
            activeId.toNumber(),
            vParameters3,
            sParameters3,
            this.currentTimestamp.toNumber()
          );
          DLMM.updateVolatilityAccumulator(
            vParameters3,
            sParameters3,
            activeId.toNumber()
          );
          const { amountXIntoBin, amountYIntoBin } = simulateDepositBin(
            binId,
            binStep,
            amountX,
            amountY,
            this.activeBin
          );
          const feeY = computeCompositionFee(
            binStep,
            sParameters3,
            vParameters3,
            amountXIntoBin,
            amountX,
            amountYIntoBin,
            amountY
          );
          const feeX = computeCompositionFee(
            binStep,
            sParameters3,
            vParameters3,
            amountYIntoBin,
            amountY,
            amountXIntoBin,
            amountX
          );
          const amountXIntoBinExcludeFee = amountXIntoBin.sub(feeX);
          const amountYIntoBinExcludeFee = amountYIntoBin.sub(feeY);
          this.rebalancePositionBinData[idx].amountX = this.rebalancePositionBinData[idx].amountX.add(
            amountXIntoBinExcludeFee
          );
          this.rebalancePositionBinData[idx].amountY = this.rebalancePositionBinData[idx].amountY.add(
            amountYIntoBinExcludeFee
          );
        } else {
          this.rebalancePositionBinData[idx].amountX = this.rebalancePositionBinData[idx].amountX.add(amountX);
          this.rebalancePositionBinData[idx].amountY = this.rebalancePositionBinData[idx].amountY.add(amountY);
        }
      }
    }
    let actualTotalAmountXDeposited = totalAmountXDeposited;
    let actualTotalAmountYDeposited = totalAmountYDeposited;
    let actualLiquidityAndFeeXWithdrawn = liquidityAndFeeXWithdrawn;
    let actualLiquidityAndFeeYWithdrawn = liquidityAndFeeYWithdrawn;
    if (actualTotalAmountXDeposited.gt(actualLiquidityAndFeeXWithdrawn)) {
      actualTotalAmountXDeposited = actualTotalAmountXDeposited.sub(
        actualLiquidityAndFeeXWithdrawn
      );
      actualLiquidityAndFeeXWithdrawn = new BN12(0);
    } else {
      actualLiquidityAndFeeXWithdrawn = actualLiquidityAndFeeXWithdrawn.sub(
        actualTotalAmountXDeposited
      );
      actualTotalAmountXDeposited = new BN12(0);
    }
    if (actualTotalAmountYDeposited.gt(actualLiquidityAndFeeYWithdrawn)) {
      actualTotalAmountYDeposited = actualTotalAmountYDeposited.sub(
        actualLiquidityAndFeeYWithdrawn
      );
      actualLiquidityAndFeeYWithdrawn = new BN12(0);
    } else {
      actualLiquidityAndFeeYWithdrawn = actualLiquidityAndFeeYWithdrawn.sub(
        actualTotalAmountYDeposited
      );
      actualTotalAmountYDeposited = new BN12(0);
    }
    return {
      result: {
        totalAmountXDeposited,
        totalAmountYDeposited,
        actualLiquidityAndFeeXWithdrawn,
        actualLiquidityAndFeeYWithdrawn,
        actualTotalAmountXDeposited,
        actualTotalAmountYDeposited
      },
      depositParams: addLiquidityParam
    };
  }
  _simulateResize(depositMinBinId, depositMaxBinId, binStep, tokenXDecimal, tokenYDecimal) {
    const tokenXMultiplier = new Decimal6(10 ** tokenXDecimal.toNumber());
    const tokenYMultiplier = new Decimal6(10 ** tokenYDecimal.toNumber());
    const [minBinId, maxBinId] = findMinMaxBinIdWithLiquidity(
      this.rebalancePositionBinData
    );
    const newMinBinId = new BN12(
      Math.min(depositMinBinId.toNumber(), minBinId ?? Number.MAX_SAFE_INTEGER)
    );
    const newMaxBinId = new BN12(
      Math.max(depositMaxBinId.toNumber(), maxBinId ?? Number.MIN_SAFE_INTEGER)
    );
    if (newMinBinId.lt(this.lowerBinId)) {
      const binCountToExpand = this.lowerBinId.sub(depositMinBinId);
      for (let i = 1; i <= binCountToExpand.toNumber(); i++) {
        const binId = this.lowerBinId.subn(i);
        const price = getPriceOfBinByBinId(
          binId.toNumber(),
          binStep.toNumber()
        );
        const adjustedPrice = price.mul(tokenXMultiplier).div(tokenYMultiplier);
        this.rebalancePositionBinData.unshift({
          binId: binId.toNumber(),
          price: adjustedPrice.toString(),
          pricePerToken: adjustedPrice.toString(),
          amountX: new BN12(0),
          amountY: new BN12(0),
          claimableRewardAmount: [new BN12(0), new BN12(0)],
          claimableFeeXAmount: new BN12(0),
          claimableFeeYAmount: new BN12(0)
        });
      }
    } else {
      const binCountToShrink = newMinBinId.sub(this.lowerBinId);
      for (let i = 1; i <= binCountToShrink.toNumber(); i++) {
        this.rebalancePositionBinData.shift();
      }
    }
    if (newMaxBinId.gt(this.upperBinId)) {
      const binCountToExpand = newMaxBinId.sub(this.upperBinId);
      for (let i = 1; i <= binCountToExpand.toNumber(); i++) {
        const binId = this.upperBinId.addn(i);
        const price = getPriceOfBinByBinId(
          binId.toNumber(),
          binStep.toNumber()
        );
        const adjustedPrice = price.mul(tokenXMultiplier).div(tokenYMultiplier);
        this.rebalancePositionBinData.push({
          binId: binId.toNumber(),
          price: adjustedPrice.toString(),
          pricePerToken: adjustedPrice.toString(),
          amountX: new BN12(0),
          amountY: new BN12(0),
          claimableRewardAmount: [new BN12(0), new BN12(0)],
          claimableFeeXAmount: new BN12(0),
          claimableFeeYAmount: new BN12(0)
        });
      }
    } else {
      const binCountToShrink = this.upperBinId.sub(newMaxBinId);
      for (let i = 1; i <= binCountToShrink.toNumber(); i++) {
        this.rebalancePositionBinData.pop();
      }
    }
    this.lowerBinId = newMinBinId;
    this.upperBinId = newMaxBinId;
  }
  _simulateWithdraw(withdraws) {
    let liquidityAndFeeXWithdrawn = new BN12(0);
    let liquidityAndFeeYWithdrawn = new BN12(0);
    let rewardsAmountClaimed = [new BN12(0), new BN12(0)];
    const activeId = new BN12(this.lbPair.activeId);
    for (const { minBinId, maxBinId, bps } of withdraws) {
      const fromBinId = minBinId ?? activeId;
      const toBinId = maxBinId ?? activeId;
      const binIds = binRangeToBinIdArray(fromBinId, toBinId).filter(
        (binId) => binId.gte(this.lowerBinId) && binId.lte(this.upperBinId)
      );
      for (const binId of binIds) {
        const idx = this.rebalancePositionBinData.findIndex(
          (b) => b.binId === binId.toNumber()
        );
        const binData = this.rebalancePositionBinData[idx];
        const amountXWithdrawn = binData.amountX.mul(bps).divn(BASIS_POINT_MAX);
        const amountYWithdrawn = binData.amountY.mul(bps).divn(BASIS_POINT_MAX);
        liquidityAndFeeXWithdrawn = liquidityAndFeeXWithdrawn.add(amountXWithdrawn);
        liquidityAndFeeYWithdrawn = liquidityAndFeeYWithdrawn.add(amountYWithdrawn);
        binData.amountX = binData.amountX.sub(amountXWithdrawn);
        binData.amountY = binData.amountY.sub(amountYWithdrawn);
        if (this.shouldClaimFee) {
          liquidityAndFeeXWithdrawn = liquidityAndFeeXWithdrawn.add(
            binData.claimableFeeXAmount
          );
          liquidityAndFeeYWithdrawn = liquidityAndFeeYWithdrawn.add(
            binData.claimableFeeYAmount
          );
          binData.claimableFeeXAmount = new BN12(0);
          binData.claimableFeeYAmount = new BN12(0);
        }
        if (this.shouldClaimReward) {
          for (const [idx2, amount] of binData.claimableRewardAmount.entries()) {
            rewardsAmountClaimed[idx2] = rewardsAmountClaimed[idx2].add(amount);
            binData.claimableRewardAmount[idx2] = new BN12(0);
          }
        }
        this.rebalancePositionBinData[idx] = binData;
      }
    }
    const withdrawParams = withdraws.map(
      ({ minBinId, maxBinId, bps }) => {
        return {
          minBinId: minBinId ? minBinId.toNumber() : null,
          maxBinId: maxBinId ? maxBinId.toNumber() : null,
          bps: bps.toNumber(),
          padding: Array(16).fill(0)
        };
      }
    );
    return {
      result: {
        liquidityAndFeeXWithdrawn,
        liquidityAndFeeYWithdrawn,
        rewardsAmountClaimed
      },
      withdrawParams
    };
  }
  async simulateRebalance(connection, binStep, tokenXDecimal, tokenYDecimal, withdraws, deposits) {
    if (withdraws.length == 0 && deposits.length == 0) {
      throw "No rebalance action";
    }
    const activeId = new BN12(this.lbPair.activeId);
    withdraws = validateAndSortRebalanceWithdraw(withdraws, activeId);
    deposits = validateAndSortRebalanceDeposit(deposits);
    const beforeWidth = getPositionWidthWithMinWidth(
      this.lowerBinId.toNumber(),
      this.upperBinId.toNumber()
    );
    const { withdrawParams, result: withdrawResult } = this._simulateWithdraw(withdraws);
    const { depositParams, result: depositResult } = this._simulateDeposit(
      binStep,
      tokenXDecimal,
      tokenYDecimal,
      deposits,
      withdrawResult
    );
    const afterWidth = getPositionWidthWithMinWidth(
      this.lowerBinId.toNumber(),
      this.upperBinId.toNumber()
    );
    const widthDelta = afterWidth - beforeWidth;
    let rentalCostLamports = new BN12(0);
    if (widthDelta != 0) {
      const sizeChanges = Math.abs(widthDelta) * POSITION_BIN_DATA_SIZE;
      const [minimumLamports, rentExemptionLamports] = await Promise.all([
        connection.getMinimumBalanceForRentExemption(0),
        connection.getMinimumBalanceForRentExemption(sizeChanges)
      ]);
      const lamportChanges = new BN12(rentExemptionLamports).sub(
        new BN12(minimumLamports)
      );
      if (widthDelta > 0) {
        rentalCostLamports = rentalCostLamports.add(lamportChanges);
      } else {
        rentalCostLamports = rentalCostLamports.sub(lamportChanges);
      }
    }
    return {
      amountXDeposited: depositResult.totalAmountXDeposited,
      amountYDeposited: depositResult.totalAmountYDeposited,
      actualAmountXDeposited: depositResult.actualTotalAmountXDeposited,
      actualAmountYDeposited: depositResult.actualTotalAmountYDeposited,
      actualAmountXWithdrawn: depositResult.actualLiquidityAndFeeXWithdrawn,
      actualAmountYWithdrawn: depositResult.actualLiquidityAndFeeYWithdrawn,
      rewardAmountsClaimed: withdrawResult.rewardsAmountClaimed,
      withdrawParams,
      depositParams,
      rentalCostLamports
    };
  }
  totalAmounts() {
    let totalAmountX = new BN12(0);
    let totalAmountY = new BN12(0);
    for (const binData of this.rebalancePositionBinData) {
      totalAmountX = totalAmountX.add(binData.amountX);
      totalAmountY = totalAmountY.add(binData.amountY);
    }
    return [totalAmountX, totalAmountY];
  }
  totalFeeAmounts() {
    let totalFeeXAmount = new BN12(0);
    let totalFeeYAmount = new BN12(0);
    for (const binData of this.rebalancePositionBinData) {
      totalFeeXAmount = totalFeeXAmount.add(binData.claimableFeeXAmount);
      totalFeeYAmount = totalFeeYAmount.add(binData.claimableFeeYAmount);
    }
    return [totalFeeXAmount, totalFeeYAmount];
  }
  totalRewardAmounts() {
    let totalRewardAmounts = [new BN12(0), new BN12(0)];
    for (const binData of this.rebalancePositionBinData) {
      totalRewardAmounts[0] = totalRewardAmounts[0].add(
        binData.claimableRewardAmount[0]
      );
      totalRewardAmounts[1] = totalRewardAmounts[1].add(
        binData.claimableRewardAmount[1]
      );
    }
    return totalRewardAmounts;
  }
};
function getPositionWidthWithMinWidth(lowerBinId, upperBinId) {
  const width = upperBinId - lowerBinId + 1;
  return Math.max(width, DEFAULT_BIN_PER_POSITION.toNumber());
}
function validateAndSortRebalanceDeposit(deposits) {
  const sortedDeposits = deposits.sort(
    (a, b) => a.minDeltaId.sub(b.minDeltaId).toNumber()
  );
  for (const deposit of deposits) {
    if (deposit.minDeltaId.gt(deposit.maxDeltaId)) {
      throw "Invalid minDeltaId or maxDeltaId";
    }
  }
  for (let i = 1; i < sortedDeposits.length; i++) {
    const prevDeposit = sortedDeposits[i - 1];
    const currDeposit = sortedDeposits[i];
    if (prevDeposit.maxDeltaId.gte(currDeposit.minDeltaId)) {
      throw "Overlap deposit bin range";
    }
  }
  return sortedDeposits;
}
function validateAndSortRebalanceWithdraw(withdraws, activeId) {
  const filledWithdraws = [];
  for (const { minBinId, maxBinId, bps } of withdraws) {
    if (bps.toNumber() < 0 || bps.toNumber() > BASIS_POINT_MAX) {
      throw "Invalid bps";
    }
    const filledMinBinId = minBinId ?? activeId;
    const filledMaxBinId = maxBinId ?? activeId;
    if (filledMinBinId.gt(filledMaxBinId)) {
      throw "Invalid minBinId or maxBinId";
    }
    filledWithdraws.push({
      minBinId: filledMinBinId,
      maxBinId: filledMaxBinId,
      bps
    });
  }
  filledWithdraws.sort((a, b) => {
    return a.minBinId.sub(b.minBinId).toNumber();
  });
  for (let i = 1; i < filledWithdraws.length; i++) {
    const prev = filledWithdraws[i - 1];
    const curr = filledWithdraws[i];
    if (curr.minBinId.lte(prev.maxBinId)) {
      throw "Overlap withdraw bin range";
    }
  }
  return filledWithdraws;
}
function binRangeToBinIdArray(minBinId, maxBinId) {
  const binIdArray = [];
  const fromBinId = minBinId.toNumber();
  const toBinId = maxBinId.toNumber();
  for (let binId = fromBinId; binId <= toBinId; binId++) {
    binIdArray.push(new BN12(binId));
  }
  return binIdArray;
}
function getRebalanceBinArrayIndexesAndBitmapCoverage(adds, removes, activeId, pairAddress, programId) {
  let indexMap = /* @__PURE__ */ new Map();
  removes.forEach((value) => {
    let minBinId = value.minBinId;
    if (minBinId == null) {
      minBinId = activeId;
    }
    let maxBinId = value.maxBinId;
    if (maxBinId == null) {
      maxBinId = activeId;
    }
    let binArrayIndex = binIdToBinArrayIndex(new BN12(minBinId));
    const upperBinId = new BN12(maxBinId);
    while (true) {
      indexMap.set(binArrayIndex.toNumber(), true);
      const [binArrayLowerBinId, binArrayUpperBinId] = getBinArrayLowerUpperBinId(binArrayIndex);
      if (upperBinId.gte(binArrayLowerBinId) && upperBinId.lte(binArrayUpperBinId)) {
        break;
      } else {
        binArrayIndex = binArrayIndex.add(new BN12(1));
      }
    }
  });
  adds.forEach((value) => {
    const minBinId = activeId + value.minDeltaId;
    const maxBinId = activeId + value.maxDeltaId;
    let binArrayIndex = binIdToBinArrayIndex(new BN12(minBinId));
    const upperBinId = new BN12(maxBinId);
    while (true) {
      indexMap.set(binArrayIndex.toNumber(), true);
      const [binArrayLowerBinId, binArrayUpperBinId] = getBinArrayLowerUpperBinId(binArrayIndex);
      if (upperBinId.gte(binArrayLowerBinId) && upperBinId.lte(binArrayUpperBinId)) {
        break;
      } else {
        binArrayIndex = binArrayIndex.add(new BN12(1));
      }
    }
  });
  const binArrayIndexes = Array.from(indexMap.keys()).map((idx) => new BN12(idx));
  const requireBitmapExtension = binArrayIndexes.some(
    (index) => isOverflowDefaultBinArrayBitmap(new BN12(index))
  );
  return {
    binArrayIndexes,
    binArrayBitmap: requireBitmapExtension ? deriveBinArrayBitmapExtension(pairAddress, programId)[0] : programId
  };
}

// src/dlmm/helpers/rebalance/liquidity_strategy/index.ts
import BN16 from "bn.js";

// src/dlmm/helpers/rebalance/liquidity_strategy/bidAsk.ts
import BN13 from "bn.js";
function findBaseDeltaY(amountY, minDeltaId, maxDeltaId) {
  if (minDeltaId.gt(maxDeltaId) || amountY.lte(new BN13(0))) {
    return new BN13(0);
  }
  if (minDeltaId.eq(maxDeltaId)) {
    return amountY;
  }
  const m1 = minDeltaId.neg();
  const m2 = maxDeltaId.neg();
  const b = m2.neg().addn(1).mul(m1.sub(m2).addn(1));
  const c = m1.mul(m1.addn(1)).divn(2);
  const d = m2.mul(m2.subn(1)).divn(2);
  const a = b.add(c.sub(d));
  return amountY.div(a);
}
function findY0AndDeltaY(amountY, minDeltaId, maxDeltaId, activeId) {
  if (minDeltaId.gt(maxDeltaId) || amountY.isZero()) {
    return {
      base: new BN13(0),
      delta: new BN13(0)
    };
  }
  let baseDeltaY = findBaseDeltaY(amountY, minDeltaId, maxDeltaId);
  const y0 = baseDeltaY.neg().mul(maxDeltaId.neg().subn(1));
  while (true) {
    const amountInBins = getAmountInBinsBidSide(
      activeId,
      minDeltaId,
      maxDeltaId,
      baseDeltaY,
      y0
    );
    const totalAmountY = amountInBins.reduce((acc, { amountY: amountY2 }) => {
      return acc.add(amountY2);
    }, new BN13(0));
    if (totalAmountY.gt(amountY)) {
      baseDeltaY = baseDeltaY.sub(new BN13(1));
    } else {
      return {
        base: y0,
        delta: baseDeltaY
      };
    }
  }
}
function findBaseDeltaX(amountX, minDeltaId, maxDeltaId, binStep, activeId) {
  if (minDeltaId.gt(maxDeltaId) || amountX.lte(new BN13(0))) {
    return new BN13(0);
  }
  const m1 = minDeltaId;
  const m2 = maxDeltaId;
  let b = new BN13(0);
  let c = new BN13(0);
  let s = new BN13(0);
  const base = getQPriceBaseFactor(binStep);
  const maxBinId = activeId.add(maxDeltaId);
  let inverseBasePrice = pow(base, maxBinId.neg());
  for (let m = m2.toNumber(); m >= m1.toNumber(); m--) {
    const pm = inverseBasePrice;
    b = b.add(m1.mul(pm));
    c = c.add(new BN13(m).mul(pm));
    s = s.add(pm);
    inverseBasePrice = inverseBasePrice.mul(base).shrn(SCALE_OFFSET);
  }
  return amountX.shln(SCALE_OFFSET).div(c.sub(b).add(s));
}
function findX0AndDeltaX(amountX, minDeltaId, maxDeltaId, binStep, activeId) {
  if (minDeltaId.gt(maxDeltaId) || amountX.lte(new BN13(0)) || amountX.isZero()) {
    return {
      base: new BN13(0),
      delta: new BN13(0)
    };
  }
  let baseDeltaX = findBaseDeltaX(
    amountX,
    minDeltaId,
    maxDeltaId,
    binStep,
    activeId
  );
  let maxProbe = 100;
  while (true) {
    if (maxProbe < 0) {
      throw new Error(
        "Something wrong: Unable to find suitable x0 and delta_x within probe limit"
      );
    }
    const x0 = minDeltaId.neg().addn(1).mul(baseDeltaX);
    const amountInBins = getAmountInBinsAskSide(
      activeId,
      binStep,
      minDeltaId,
      maxDeltaId,
      baseDeltaX,
      x0
    );
    const totalAmountX = amountInBins.reduce((acc, { amountX: amountX2 }) => {
      return acc.add(amountX2);
    }, new BN13(0));
    if (totalAmountX.gt(amountX)) {
      baseDeltaX = baseDeltaX.subn(1);
      maxProbe--;
    } else {
      return {
        base: x0,
        delta: baseDeltaX
      };
    }
  }
}
var BidAskStrategyParameterBuilder = class {
  findXParameters(amountX, minDeltaId, maxDeltaId, binStep, activeId) {
    return findX0AndDeltaX(amountX, minDeltaId, maxDeltaId, binStep, activeId);
  }
  findYParameters(amountY, minDeltaId, maxDeltaId, activeId) {
    return findY0AndDeltaY(amountY, minDeltaId, maxDeltaId, activeId);
  }
  suggestBalancedXParametersFromY(activeId, binStep, favorXInActiveBin, minDeltaId, maxDeltaId, amountY) {
    const deltaX = amountY.div(
      maxDeltaId.addn(1).mul(maxDeltaId.addn(2)).divn(2)
    );
    const x0 = minDeltaId.neg().mul(deltaX).add(deltaX);
    const totalAmountX = toAmountIntoBins(
      activeId,
      minDeltaId,
      maxDeltaId,
      deltaX,
      new BN13(0),
      x0,
      new BN13(0),
      binStep,
      favorXInActiveBin
    ).reduce((acc, bin) => {
      return acc.add(bin.amountX);
    }, new BN13(0));
    return {
      base: x0,
      delta: deltaX,
      amountX: totalAmountX
    };
  }
  suggestBalancedYParametersFromX(activeId, binStep, favorXInActiveBin, minDeltaId, maxDeltaId, amountXInQuoteValue) {
    const m1 = minDeltaId.neg().subn(1);
    const m2 = maxDeltaId.neg();
    const a1 = m2.neg().mul(m1.sub(m2).addn(1));
    const a2 = m1.mul(m1.addn(1)).divn(2);
    const a3 = m2.mul(m2.subn(1)).divn(2);
    const a = a1.add(a2.sub(a3));
    const deltaY = amountXInQuoteValue.div(a);
    const y0 = deltaY.neg().mul(m2).add(deltaY);
    const amountY = toAmountIntoBins(
      activeId,
      minDeltaId,
      maxDeltaId,
      new BN13(0),
      deltaY,
      new BN13(0),
      y0,
      binStep,
      favorXInActiveBin
    ).reduce((acc, bin) => {
      return acc.add(bin.amountY);
    }, new BN13(0));
    return {
      base: y0,
      delta: deltaY,
      amountY
    };
  }
};

// src/dlmm/helpers/rebalance/liquidity_strategy/curve.ts
import BN14 from "bn.js";
function findBaseY0(amountY, minDeltaId, maxDeltaId) {
  if (minDeltaId.gt(maxDeltaId) || amountY.lte(new BN14(0))) {
    return new BN14(0);
  }
  if (minDeltaId.eq(maxDeltaId)) {
    return amountY;
  }
  const m1 = minDeltaId.neg();
  const m2 = maxDeltaId.neg();
  const b = m1.sub(m2).addn(1);
  const c = m1.mul(m1.addn(1)).divn(2);
  const d = m2.mul(m2.subn(1)).divn(2);
  const a = b.sub(c.sub(d).div(m1.addn(1)));
  return amountY.div(a);
}
function findY0AndDeltaY2(amountY, minDeltaId, maxDeltaId, activeId) {
  if (minDeltaId.gt(maxDeltaId) || amountY.isZero()) {
    return {
      base: new BN14(0),
      delta: new BN14(0)
    };
  }
  let baseY0 = findBaseY0(amountY, minDeltaId, maxDeltaId);
  while (true) {
    const deltaY = baseY0.neg().div(minDeltaId.neg().addn(1));
    const amountInBins = getAmountInBinsBidSide(
      activeId,
      minDeltaId,
      maxDeltaId,
      deltaY,
      baseY0
    );
    const totalAmountY = amountInBins.reduce((acc, { amountY: amountY2 }) => {
      return acc.add(amountY2);
    }, new BN14(0));
    if (totalAmountY.gt(amountY)) {
      baseY0 = baseY0.sub(new BN14(1));
    } else {
      return {
        base: baseY0,
        delta: deltaY
      };
    }
  }
}
function findBaseX0(amountX, minDeltaId, maxDeltaId, binStep, activeId) {
  if (minDeltaId.gt(maxDeltaId) || amountX.lte(new BN14(0))) {
    return new BN14(0);
  }
  let b = new BN14(0);
  let c = new BN14(0);
  let m1 = minDeltaId;
  let m2 = maxDeltaId;
  for (let m = m1.toNumber(); m <= m2.toNumber(); m++) {
    const binId = activeId.addn(m);
    const pm = getQPriceFromId(binId.neg(), binStep);
    b = b.add(pm);
    const cDelta = new BN14(m).mul(pm).div(m2);
    c = c.add(cDelta);
  }
  return amountX.shln(SCALE_OFFSET).div(b.sub(c));
}
function findX0AndDeltaX2(amountX, minDeltaId, maxDeltaId, binStep, activeId) {
  if (minDeltaId.gt(maxDeltaId) || amountX.lte(new BN14(0)) || amountX.isZero()) {
    return {
      base: new BN14(0),
      delta: new BN14(0)
    };
  }
  let baseX0 = findBaseX0(amountX, minDeltaId, maxDeltaId, binStep, activeId);
  const deltaX = baseX0.neg().div(maxDeltaId);
  while (true) {
    const amountInBins = getAmountInBinsAskSide(
      activeId,
      binStep,
      minDeltaId,
      maxDeltaId,
      deltaX,
      baseX0
    );
    const totalAmountX = amountInBins.reduce((acc, { amountX: amountX2 }) => {
      return acc.add(amountX2);
    }, new BN14(0));
    if (totalAmountX.gt(amountX)) {
      baseX0 = baseX0.sub(new BN14(1));
    } else {
      return {
        base: baseX0,
        delta: deltaX
      };
    }
  }
}
var CurveStrategyParameterBuilder = class {
  findXParameters(amountX, minDeltaId, maxDeltaId, binStep, activeId) {
    return findX0AndDeltaX2(amountX, minDeltaId, maxDeltaId, binStep, activeId);
  }
  findYParameters(amountY, minDeltaId, maxDeltaId, activeId) {
    return findY0AndDeltaY2(amountY, minDeltaId, maxDeltaId, activeId);
  }
  suggestBalancedXParametersFromY(activeId, binStep, favorXInActiveBin, minDeltaId, maxDeltaId, amountY) {
    const x0 = amountY.muln(2).div(maxDeltaId.addn(1));
    const deltaX = x0.neg().div(maxDeltaId);
    const totalAmountX = toAmountIntoBins(
      activeId,
      minDeltaId,
      maxDeltaId,
      deltaX,
      new BN14(0),
      x0,
      new BN14(0),
      binStep,
      favorXInActiveBin
    ).reduce((acc, bin) => {
      return acc.add(bin.amountX);
    }, new BN14(0));
    return {
      base: x0,
      delta: deltaX,
      amountX: totalAmountX
    };
  }
  suggestBalancedYParametersFromX(activeId, binStep, favorXInActiveBin, minDeltaId, maxDeltaId, amountXInQuoteValue) {
    const m1 = minDeltaId.neg();
    const m2 = maxDeltaId.neg();
    const a1 = m1.sub(m2).addn(1);
    const a2 = m1.mul(m1.addn(1)).divn(2);
    const a3 = m2.mul(m2.subn(1)).divn(2);
    const a = m1.sub(a3.sub(a2)).div(m1);
    const y0 = amountXInQuoteValue.div(a);
    const deltaY = y0.neg().div(m1);
    const amountY = toAmountIntoBins(
      activeId,
      minDeltaId,
      maxDeltaId,
      new BN14(0),
      deltaY,
      new BN14(0),
      y0,
      binStep,
      favorXInActiveBin
    ).reduce((acc, bin) => {
      return acc.add(bin.amountY);
    }, new BN14(0));
    return {
      base: y0,
      delta: deltaY,
      amountY
    };
  }
};

// src/dlmm/helpers/rebalance/liquidity_strategy/spot.ts
import BN15 from "bn.js";
function findY0(amountY, minDeltaId, maxDeltaId) {
  if (minDeltaId.gt(maxDeltaId) || amountY.lte(new BN15(0)) || amountY.isZero()) {
    return new BN15(0);
  }
  const m1 = minDeltaId.neg();
  const m2 = maxDeltaId.neg();
  const delta = m1.sub(m2).addn(1);
  return amountY.div(delta);
}
function findBaseX02(amountX, minDeltaId, maxDeltaId, binStep, activeId) {
  let totalWeight = new BN15(0);
  const minBinId = activeId.add(minDeltaId);
  const maxBinId = activeId.add(maxDeltaId);
  let baseFactor = getQPriceBaseFactor(binStep);
  let basePrice = getQPriceFromId(maxBinId.neg(), binStep);
  for (let binId = minBinId.toNumber(); binId <= maxBinId.toNumber(); binId++) {
    totalWeight = totalWeight.add(basePrice);
    basePrice = basePrice.mul(baseFactor).shrn(SCALE_OFFSET);
  }
  return amountX.shln(SCALE_OFFSET).div(totalWeight);
}
function findX0(amountX, minDeltaId, maxDeltaId, binStep, activeId) {
  if (minDeltaId.gt(maxDeltaId) || amountX.lte(new BN15(0)) || amountX.isZero()) {
    return new BN15(0);
  }
  let x0 = findBaseX02(amountX, minDeltaId, maxDeltaId, binStep, activeId);
  while (true) {
    const amountInBins = getAmountInBinsAskSide(
      activeId,
      binStep,
      minDeltaId,
      maxDeltaId,
      new BN15(0),
      x0
    );
    const totalAmountX = amountInBins.reduce((acc, bin) => {
      return acc.add(bin.amountX);
    }, new BN15(0));
    if (totalAmountX.lt(amountX)) {
      x0 = x0.add(new BN15(1));
    } else {
      x0 = x0.sub(new BN15(1));
      return x0;
    }
  }
}
var SpotStrategyParameterBuilder = class {
  findXParameters(amountX, minDeltaId, maxDeltaId, binStep, activeId) {
    return {
      base: findX0(amountX, minDeltaId, maxDeltaId, binStep, activeId),
      delta: new BN15(0)
    };
  }
  findYParameters(amountY, minDeltaId, maxDeltaId, _activeId) {
    return {
      base: findY0(amountY, minDeltaId, maxDeltaId),
      delta: new BN15(0)
    };
  }
  suggestBalancedXParametersFromY(activeId, binStep, favorXInActiveBin, minDeltaId, maxDeltaId, amountY) {
    const x0 = amountY.div(maxDeltaId.addn(1));
    const totalAmountX = toAmountIntoBins(
      activeId,
      minDeltaId,
      maxDeltaId,
      new BN15(0),
      new BN15(0),
      x0,
      new BN15(0),
      binStep,
      favorXInActiveBin
    ).reduce((acc, bin) => {
      return acc.add(bin.amountX);
    }, new BN15(0));
    return {
      base: new BN15(x0.toString()),
      delta: new BN15(0),
      amountX: totalAmountX
    };
  }
  suggestBalancedYParametersFromX(activeId, binStep, favorXInActiveBin, minDeltaId, maxDeltaId, amountXInQuoteValue) {
    const y0 = amountXInQuoteValue.div(maxDeltaId.sub(minDeltaId).addn(1));
    const amountY = toAmountIntoBins(
      activeId,
      minDeltaId,
      maxDeltaId,
      new BN15(0),
      new BN15(0),
      new BN15(0),
      y0,
      binStep,
      favorXInActiveBin
    ).reduce((acc, bin) => {
      return acc.add(bin.amountY);
    }, new BN15(0));
    return {
      base: y0,
      delta: new BN15(0),
      amountY
    };
  }
};

// src/dlmm/helpers/rebalance/liquidity_strategy/index.ts
import Decimal7 from "decimal.js";
function getLiquidityStrategyParameterBuilder(strategyType) {
  switch (strategyType) {
    case 0 /* Spot */:
      return new SpotStrategyParameterBuilder();
    case 1 /* Curve */:
      return new CurveStrategyParameterBuilder();
    case 2 /* BidAsk */:
      return new BidAskStrategyParameterBuilder();
    default:
      throw new Error("Strategy not supported");
  }
}
function suggestBalancedXParametersFromY(y0, deltaY, minDeltaId, maxDeltaId, activeId, binStep, favorXInActiveBin, builder) {
  const endDeltaIdBidSide = favorXInActiveBin ? new BN16(-1) : new BN16(0);
  if (maxDeltaId.lte(endDeltaIdBidSide)) {
    return {
      base: new BN16(0),
      delta: new BN16(0),
      amountX: new BN16(0)
    };
  }
  const minYDeltaId = minDeltaId;
  const maxYDeltaId = endDeltaIdBidSide;
  const totalAmountY = toAmountIntoBins(
    activeId,
    minYDeltaId,
    maxYDeltaId,
    new BN16(0),
    deltaY,
    new BN16(0),
    y0,
    binStep,
    favorXInActiveBin
  ).reduce((acc, bin) => {
    return acc.add(bin.amountY);
  }, new BN16(0));
  const minXDeltaId = maxYDeltaId.addn(1);
  const maxXDeltaId = maxDeltaId;
  return builder.suggestBalancedXParametersFromY(
    activeId,
    binStep,
    favorXInActiveBin,
    minXDeltaId,
    maxXDeltaId,
    totalAmountY
  );
}
function getAutoFillAmountByRebalancedPosition(rebalancePosition, strategyType) {
  let liquidityInBidSide = new BN16(0);
  let liquidityInAskSide = new BN16(0);
  const builder = getLiquidityStrategyParameterBuilder(strategyType);
  const { lbPair } = rebalancePosition;
  let favorXInActiveBin = false;
  let activeIdIndex = -1;
  for (const [
    idx,
    binData
  ] of rebalancePosition.rebalancePositionBinData.entries()) {
    const liquidityBid = binData.amountY;
    const liquidityAsk = new Decimal7(binData.price).mul(new Decimal7(binData.amountX.toString())).floor().toString();
    liquidityInBidSide = liquidityInBidSide.add(liquidityBid);
    liquidityInAskSide = liquidityInAskSide.add(new BN16(liquidityAsk));
    if (binData.binId == lbPair.activeId) {
      favorXInActiveBin = binData.amountX.gt(binData.amountY);
      activeIdIndex = idx;
    }
  }
  if (liquidityInAskSide.gt(liquidityInBidSide)) {
    const minBinId = rebalancePosition.rebalancePositionBinData[0].binId;
    let maxBinId;
    if (activeIdIndex == -1) {
      maxBinId = rebalancePosition.rebalancePositionBinData[rebalancePosition.rebalancePositionBinData.length - 1].binId;
    } else {
      maxBinId = rebalancePosition.rebalancePositionBinData[favorXInActiveBin ? activeIdIndex - 1 : activeIdIndex].binId;
    }
    const minDeltaId = minBinId - lbPair.activeId;
    const maxDeltaId = maxBinId - lbPair.activeId;
    const { amountY } = builder.suggestBalancedYParametersFromX(
      new BN16(lbPair.activeId),
      new BN16(lbPair.binStep),
      favorXInActiveBin,
      new BN16(minDeltaId),
      new BN16(maxDeltaId),
      liquidityInAskSide
    );
    const [_, positionAmountY] = rebalancePosition.totalAmounts();
    return {
      amount: BN16.max(amountY.sub(positionAmountY), new BN16(0)),
      isBidSide: true
    };
  } else if (liquidityInAskSide.lt(liquidityInBidSide)) {
    const maxBinId = rebalancePosition.rebalancePositionBinData[rebalancePosition.rebalancePositionBinData.length - 1].binId;
    let minBinId;
    if (activeIdIndex == -1) {
      minBinId = rebalancePosition.rebalancePositionBinData[0].binId;
    } else {
      minBinId = rebalancePosition.rebalancePositionBinData[favorXInActiveBin ? activeIdIndex - 1 : activeIdIndex].binId;
    }
    const minDeltaId = minBinId - lbPair.activeId;
    const maxDeltaId = maxBinId - lbPair.activeId;
    const { amountX } = builder.suggestBalancedXParametersFromY(
      new BN16(lbPair.activeId),
      new BN16(lbPair.binStep),
      favorXInActiveBin,
      new BN16(minDeltaId),
      new BN16(maxDeltaId),
      liquidityInBidSide
    );
    const [positionAmountX] = rebalancePosition.totalAmounts();
    return {
      amount: BN16.max(amountX.sub(positionAmountX), new BN16(0)),
      isBidSide: false
    };
  } else {
    return {
      amount: new BN16(0),
      isBidSide: false
    };
  }
}
function suggestBalancedYParametersFromX(x0, deltaX, minDeltaId, maxDeltaId, activeId, binStep, favorXInActiveBin, builder) {
  const startDeltaIdAskSide = favorXInActiveBin ? new BN16(0) : new BN16(1);
  if (minDeltaId.gte(startDeltaIdAskSide)) {
    return {
      base: new BN16(0),
      delta: new BN16(0),
      amountY: new BN16(0)
    };
  }
  const minXDeltaId = startDeltaIdAskSide;
  const maxXDeltaId = maxDeltaId;
  const amountXInBins = toAmountIntoBins(
    activeId,
    minXDeltaId,
    maxXDeltaId,
    deltaX,
    new BN16(0),
    x0,
    new BN16(0),
    binStep,
    favorXInActiveBin
  );
  const totalAmountXInQuote = amountXInBins.reduce((acc, bin) => {
    const price = getPriceOfBinByBinId(
      bin.binId.toNumber(),
      binStep.toNumber()
    );
    return acc.add(price.mul(new Decimal7(bin.amountX.toString())));
  }, new Decimal7(0));
  const totalAmountXInQuoteBN = new BN16(totalAmountXInQuote.floor().toString());
  const minYDeltaId = minDeltaId;
  const maxYDeltaId = startDeltaIdAskSide.subn(1);
  return builder.suggestBalancedYParametersFromX(
    activeId,
    binStep,
    favorXInActiveBin,
    minYDeltaId,
    maxYDeltaId,
    totalAmountXInQuoteBN
  );
}
function buildLiquidityStrategyParameters(amountX, amountY, minDeltaId, maxDeltaId, binStep, favorXInActiveId, activeId, strategyParameterBuilder) {
  if (minDeltaId.gt(maxDeltaId)) {
    return {
      x0: new BN16(0),
      y0: new BN16(0),
      deltaX: new BN16(0),
      deltaY: new BN16(0)
    };
  }
  const depositOnlyY = maxDeltaId.lt(new BN16(0)) || maxDeltaId.isZero() && !favorXInActiveId;
  const depositOnlyX = minDeltaId.gt(new BN16(0)) || minDeltaId.isZero() && favorXInActiveId;
  if (depositOnlyY) {
    const { base, delta } = strategyParameterBuilder.findYParameters(
      amountY,
      minDeltaId,
      maxDeltaId,
      activeId
    );
    return {
      x0: new BN16(0),
      deltaX: new BN16(0),
      y0: base,
      deltaY: delta
    };
  }
  if (depositOnlyX) {
    const { base, delta } = strategyParameterBuilder.findXParameters(
      amountX,
      minDeltaId,
      maxDeltaId,
      binStep,
      activeId
    );
    return {
      x0: base,
      deltaX: delta,
      y0: new BN16(0),
      deltaY: new BN16(0)
    };
  }
  const maxDeltaIdBidSide = favorXInActiveId ? new BN16(-1) : new BN16(0);
  const minDeltaIdAskSide = favorXInActiveId ? new BN16(0) : new BN16(1);
  const { base: y0, delta: deltaY } = strategyParameterBuilder.findYParameters(
    amountY,
    minDeltaId,
    maxDeltaIdBidSide,
    activeId
  );
  const { base: x0, delta: deltaX } = strategyParameterBuilder.findXParameters(
    amountX,
    minDeltaIdAskSide,
    maxDeltaId,
    binStep,
    activeId
  );
  return {
    x0,
    deltaX,
    y0,
    deltaY
  };
}

// src/dlmm/helpers/index.ts
import Decimal9 from "decimal.js";

// src/dlmm/helpers/lbPair.ts
import { PublicKey as PublicKey8 } from "@solana/web3.js";
import { TOKEN_2022_PROGRAM_ID as TOKEN_2022_PROGRAM_ID2, TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID2 } from "@solana/spl-token";
async function getTokensMintFromPoolAddress(connection, poolAddress, opt) {
  const program = createProgram(connection, opt);
  const poolAccount = await program.account.lbPair.fetchNullable(
    new PublicKey8(poolAddress)
  );
  if (!poolAccount)
    throw new Error("Pool account not found");
  return {
    tokenXMint: poolAccount.tokenXMint,
    tokenYMint: poolAccount.tokenYMint
  };
}
function getTokenProgramId(lbPairState) {
  const getTokenProgramIdByFlag = (flag) => {
    return flag == 0 ? TOKEN_PROGRAM_ID2 : TOKEN_2022_PROGRAM_ID2;
  };
  return {
    tokenXProgram: getTokenProgramIdByFlag(lbPairState.tokenMintXProgramFlag),
    tokenYProgram: getTokenProgramIdByFlag(lbPairState.tokenMintYProgramFlag)
  };
}
function isSupportLimitOrder(lbPairState) {
  const functionType = lbPairState.parameters.functionType;
  switch (functionType) {
    case 2 /* LimitOrder */:
      return true;
    case 1 /* LiquidityMining */:
      return false;
    case 0 /* Undetermined */:
      return lbPairState.rewardInfos.every(
        (rewardInfo) => rewardInfo.mint.equals(PublicKey8.default)
      );
    default:
      throw new Error("Invalid function type");
  }
}
function getFeeMode(lbPairState, swapForY) {
  const collectFeeMode = lbPairState.parameters.collectFeeMode;
  let feeOnInput;
  let feeOnTokenX;
  switch (collectFeeMode) {
    case 0 /* InputOnly */:
      feeOnInput = true;
      feeOnTokenX = swapForY;
      break;
    case 1 /* OnlyY */:
      feeOnInput = !swapForY;
      feeOnTokenX = false;
      break;
    default:
      throw new Error("Invalid collect fee mode");
  }
  return {
    feeOnInput,
    feeOnTokenX
  };
}

// src/dlmm/helpers/strategy.ts
import { BN as BN17 } from "@coral-xyz/anchor";
var DEFAULT_MAX_WEIGHT = 2e3;
var DEFAULT_MIN_WEIGHT = 200;
function toWeightSpotBalanced(minBinId, maxBinId) {
  let distributions = [];
  for (let i = minBinId; i <= maxBinId; i++) {
    distributions.push({
      binId: i,
      weight: 1
    });
  }
  return distributions;
}
function toWeightDescendingOrder(minBinId, maxBinId) {
  let distributions = [];
  for (let i = minBinId; i <= maxBinId; i++) {
    distributions.push({
      binId: i,
      weight: maxBinId - i + 1
    });
  }
  return distributions;
}
function toWeightAscendingOrder(minBinId, maxBinId) {
  let distributions = [];
  for (let i = minBinId; i <= maxBinId; i++) {
    distributions.push({
      binId: i,
      weight: i - minBinId + 1
    });
  }
  return distributions;
}
function toWeightCurve(minBinId, maxBinId, activeId) {
  if (activeId < minBinId || activeId > maxBinId) {
    throw "Invalid strategy params";
  }
  let maxWeight = DEFAULT_MAX_WEIGHT;
  let minWeight = DEFAULT_MIN_WEIGHT;
  let diffWeight = maxWeight - minWeight;
  let diffMinWeight = activeId > minBinId ? Math.floor(diffWeight / (activeId - minBinId)) : 0;
  let diffMaxWeight = maxBinId > activeId ? Math.floor(diffWeight / (maxBinId - activeId)) : 0;
  let distributions = [];
  for (let i = minBinId; i <= maxBinId; i++) {
    if (i < activeId) {
      distributions.push({
        binId: i,
        weight: maxWeight - (activeId - i) * diffMinWeight
      });
    } else if (i > activeId) {
      distributions.push({
        binId: i,
        weight: maxWeight - (i - activeId) * diffMaxWeight
      });
    } else {
      distributions.push({
        binId: i,
        weight: maxWeight
      });
    }
  }
  return distributions;
}
function toWeightBidAsk(minBinId, maxBinId, activeId) {
  if (activeId < minBinId || activeId > maxBinId) {
    throw "Invalid strategy params";
  }
  let maxWeight = DEFAULT_MAX_WEIGHT;
  let minWeight = DEFAULT_MIN_WEIGHT;
  let diffWeight = maxWeight - minWeight;
  let diffMinWeight = activeId > minBinId ? Math.floor(diffWeight / (activeId - minBinId)) : 0;
  let diffMaxWeight = maxBinId > activeId ? Math.floor(diffWeight / (maxBinId - activeId)) : 0;
  let distributions = [];
  for (let i = minBinId; i <= maxBinId; i++) {
    if (i < activeId) {
      distributions.push({
        binId: i,
        weight: minWeight + (activeId - i) * diffMinWeight
      });
    } else if (i > activeId) {
      distributions.push({
        binId: i,
        weight: minWeight + (i - activeId) * diffMaxWeight
      });
    } else {
      distributions.push({
        binId: i,
        weight: minWeight
      });
    }
  }
  return distributions;
}
function toAmountsBothSideByStrategy(activeId, binStep, minBinId, maxBinId, amountX, amountY, amountXInActiveBin, amountYInActiveBin, strategyType, mintX, mintY, clock) {
  const isSingleSideX = amountY.isZero();
  switch (strategyType) {
    case 0 /* Spot */: {
      if (activeId < minBinId || activeId > maxBinId) {
        const weights = toWeightSpotBalanced(minBinId, maxBinId);
        return toAmountBothSide(
          activeId,
          binStep,
          amountX,
          amountY,
          amountXInActiveBin,
          amountYInActiveBin,
          weights,
          mintX,
          mintY,
          clock
        );
      }
      const amountsInBin = [];
      if (!isSingleSideX) {
        if (minBinId <= activeId) {
          const weights = toWeightSpotBalanced(minBinId, activeId);
          const amounts = toAmountBidSide(
            activeId,
            amountY,
            weights,
            mintY,
            clock
          );
          for (let bin of amounts) {
            amountsInBin.push({
              binId: bin.binId,
              amountX: new BN17(0),
              amountY: bin.amount
            });
          }
        }
        if (activeId < maxBinId) {
          const weights = toWeightSpotBalanced(activeId + 1, maxBinId);
          const amounts = toAmountAskSide(
            activeId,
            binStep,
            amountX,
            weights,
            mintX,
            clock
          );
          for (let bin of amounts) {
            amountsInBin.push({
              binId: bin.binId,
              amountX: bin.amount,
              amountY: new BN17(0)
            });
          }
        }
      } else {
        if (minBinId < activeId) {
          const weights = toWeightSpotBalanced(minBinId, activeId - 1);
          const amountsIntoBidSide = toAmountBidSide(
            activeId,
            amountY,
            weights,
            mintY,
            clock
          );
          for (let bin of amountsIntoBidSide) {
            amountsInBin.push({
              binId: bin.binId,
              amountX: new BN17(0),
              amountY: bin.amount
            });
          }
        }
        if (activeId <= maxBinId) {
          const weights = toWeightSpotBalanced(activeId, maxBinId);
          const amountsIntoAskSide = toAmountAskSide(
            activeId,
            binStep,
            amountX,
            weights,
            mintX,
            clock
          );
          for (let bin of amountsIntoAskSide) {
            amountsInBin.push({
              binId: bin.binId,
              amountX: bin.amount,
              amountY: new BN17(0)
            });
          }
        }
      }
      return amountsInBin;
    }
    case 1 /* Curve */: {
      if (activeId < minBinId) {
        let weights = toWeightDescendingOrder(minBinId, maxBinId);
        return toAmountBothSide(
          activeId,
          binStep,
          amountX,
          amountY,
          amountXInActiveBin,
          amountYInActiveBin,
          weights,
          mintX,
          mintY,
          clock
        );
      }
      if (activeId > maxBinId) {
        const weights = toWeightAscendingOrder(minBinId, maxBinId);
        return toAmountBothSide(
          activeId,
          binStep,
          amountX,
          amountY,
          amountXInActiveBin,
          amountYInActiveBin,
          weights,
          mintX,
          mintY,
          clock
        );
      }
      const amountsInBin = [];
      if (!isSingleSideX) {
        if (minBinId <= activeId) {
          const weights = toWeightAscendingOrder(minBinId, activeId);
          const amounts = toAmountBidSide(
            activeId,
            amountY,
            weights,
            mintY,
            clock
          );
          for (let bin of amounts) {
            amountsInBin.push({
              binId: bin.binId,
              amountX: new BN17(0),
              amountY: bin.amount
            });
          }
        }
        if (activeId < maxBinId) {
          const weights = toWeightDescendingOrder(activeId + 1, maxBinId);
          const amounts = toAmountAskSide(
            activeId,
            binStep,
            amountX,
            weights,
            mintX,
            clock
          );
          for (let bin of amounts) {
            amountsInBin.push({
              binId: bin.binId,
              amountX: bin.amount,
              amountY: new BN17(0)
            });
          }
        }
      } else {
        if (minBinId < activeId) {
          const weights = toWeightAscendingOrder(minBinId, activeId - 1);
          const amountsIntoBidSide = toAmountBidSide(
            activeId,
            amountY,
            weights,
            mintY,
            clock
          );
          for (let bin of amountsIntoBidSide) {
            amountsInBin.push({
              binId: bin.binId,
              amountX: new BN17(0),
              amountY: bin.amount
            });
          }
        }
        if (activeId <= maxBinId) {
          const weights = toWeightDescendingOrder(activeId, maxBinId);
          const amountsIntoAskSide = toAmountAskSide(
            activeId,
            binStep,
            amountX,
            weights,
            mintX,
            clock
          );
          for (let bin of amountsIntoAskSide) {
            amountsInBin.push({
              binId: bin.binId,
              amountX: bin.amount,
              amountY: new BN17(0)
            });
          }
        }
      }
      return amountsInBin;
    }
    case 2 /* BidAsk */: {
      if (activeId < minBinId) {
        const weights = toWeightAscendingOrder(minBinId, maxBinId);
        return toAmountBothSide(
          activeId,
          binStep,
          amountX,
          amountY,
          amountXInActiveBin,
          amountYInActiveBin,
          weights,
          mintX,
          mintY,
          clock
        );
      }
      if (activeId > maxBinId) {
        const weights = toWeightDescendingOrder(minBinId, maxBinId);
        return toAmountBothSide(
          activeId,
          binStep,
          amountX,
          amountY,
          amountXInActiveBin,
          amountYInActiveBin,
          weights,
          mintX,
          mintY,
          clock
        );
      }
      const amountsInBin = [];
      if (!isSingleSideX) {
        if (minBinId <= activeId) {
          const weights = toWeightDescendingOrder(minBinId, activeId);
          const amounts = toAmountBidSide(
            activeId,
            amountY,
            weights,
            mintY,
            clock
          );
          for (let bin of amounts) {
            amountsInBin.push({
              binId: bin.binId,
              amountX: new BN17(0),
              amountY: bin.amount
            });
          }
        }
        if (activeId < maxBinId) {
          const weights = toWeightAscendingOrder(activeId + 1, maxBinId);
          const amounts = toAmountAskSide(
            activeId,
            binStep,
            amountX,
            weights,
            mintX,
            clock
          );
          for (let bin of amounts) {
            amountsInBin.push({
              binId: bin.binId,
              amountX: bin.amount,
              amountY: new BN17(0)
            });
          }
        }
      } else {
        if (minBinId < activeId) {
          const weights = toWeightDescendingOrder(minBinId, activeId - 1);
          const amountsIntoBidSide = toAmountBidSide(
            activeId,
            amountY,
            weights,
            mintY,
            clock
          );
          for (let bin of amountsIntoBidSide) {
            amountsInBin.push({
              binId: bin.binId,
              amountX: new BN17(0),
              amountY: bin.amount
            });
          }
        }
        if (activeId <= maxBinId) {
          const weights = toWeightAscendingOrder(activeId, maxBinId);
          const amountsIntoAskSide = toAmountAskSide(
            activeId,
            binStep,
            amountX,
            weights,
            mintX,
            clock
          );
          for (let bin of amountsIntoAskSide) {
            amountsInBin.push({
              binId: bin.binId,
              amountX: bin.amount,
              amountY: new BN17(0)
            });
          }
        }
      }
      return amountsInBin;
    }
  }
}
function autoFillYByStrategy(activeId, binStep, amountX, amountXInActiveBin, amountYInActiveBin, minBinId, maxBinId, strategyType) {
  switch (strategyType) {
    case 0 /* Spot */: {
      let weights = toWeightSpotBalanced(minBinId, maxBinId);
      return autoFillYByWeight(
        activeId,
        binStep,
        amountX,
        amountXInActiveBin,
        amountYInActiveBin,
        weights
      );
    }
    case 1 /* Curve */: {
      let weights = toWeightCurve(minBinId, maxBinId, activeId);
      return autoFillYByWeight(
        activeId,
        binStep,
        amountX,
        amountXInActiveBin,
        amountYInActiveBin,
        weights
      );
    }
    case 2 /* BidAsk */: {
      let weights = toWeightBidAsk(minBinId, maxBinId, activeId);
      return autoFillYByWeight(
        activeId,
        binStep,
        amountX,
        amountXInActiveBin,
        amountYInActiveBin,
        weights
      );
    }
  }
}
function autoFillXByStrategy(activeId, binStep, amountY, amountXInActiveBin, amountYInActiveBin, minBinId, maxBinId, strategyType) {
  switch (strategyType) {
    case 0 /* Spot */: {
      let weights = toWeightSpotBalanced(minBinId, maxBinId);
      return autoFillXByWeight(
        activeId,
        binStep,
        amountY,
        amountXInActiveBin,
        amountYInActiveBin,
        weights
      );
    }
    case 1 /* Curve */: {
      let weights = toWeightCurve(minBinId, maxBinId, activeId);
      return autoFillXByWeight(
        activeId,
        binStep,
        amountY,
        amountXInActiveBin,
        amountYInActiveBin,
        weights
      );
    }
    case 2 /* BidAsk */: {
      let weights = toWeightBidAsk(minBinId, maxBinId, activeId);
      return autoFillXByWeight(
        activeId,
        binStep,
        amountY,
        amountXInActiveBin,
        amountYInActiveBin,
        weights
      );
    }
  }
}
function toStrategyParameters({
  maxBinId,
  minBinId,
  strategyType,
  singleSidedX
}) {
  const parameteres = new Array(64).fill(0);
  const favorSide = singleSidedX ? 1 : 0;
  parameteres[0] = favorSide;
  switch (strategyType) {
    case 0 /* Spot */: {
      return {
        minBinId,
        maxBinId,
        strategyType: { spotImBalanced: {} },
        parameteres
      };
    }
    case 1 /* Curve */: {
      return {
        minBinId,
        maxBinId,
        strategyType: { curveImBalanced: {} },
        parameteres
      };
    }
    case 2 /* BidAsk */: {
      return {
        minBinId,
        maxBinId,
        strategyType: { bidAskImBalanced: {} },
        parameteres
      };
    }
  }
}

// src/dlmm/helpers/bin.ts
import BN18 from "bn.js";
function getAmountIn(amountOut, price, swapForY, rounding) {
  if (swapForY) {
    return shlDiv(amountOut, price, SCALE_OFFSET, rounding);
  } else {
    return mulShr(amountOut, price, SCALE_OFFSET, rounding);
  }
}
function getAmountOut(bin, inAmount, swapForY) {
  return swapForY ? mulShr(inAmount, bin.price, SCALE_OFFSET, 1 /* Down */) : shlDiv(inAmount, bin.price, SCALE_OFFSET, 1 /* Down */);
}
function getExcludedFeeAmountIn(bin, includedFeeOutAmount, swapForY) {
  const mmAmount = swapForY ? bin.amountY : bin.amountX;
  const { openOrderAmount, processedOrderRemainingAmount } = getLimitOrderAmountsBySwapDirection(bin, swapForY);
  let remainingOutAmount = includedFeeOutAmount;
  let totalAmountIn = new BN18(0);
  let exactOutAmount = BN18.min(remainingOutAmount, mmAmount);
  let amountIn = getAmountIn(exactOutAmount, bin.price, swapForY, 0 /* Up */);
  remainingOutAmount = remainingOutAmount.sub(exactOutAmount);
  totalAmountIn = totalAmountIn.add(amountIn);
  if (remainingOutAmount.gt(new BN18(0))) {
    exactOutAmount = BN18.min(remainingOutAmount, processedOrderRemainingAmount);
    amountIn = getAmountIn(exactOutAmount, bin.price, swapForY, 0 /* Up */);
    remainingOutAmount = remainingOutAmount.sub(exactOutAmount);
    totalAmountIn = totalAmountIn.add(amountIn);
    if (remainingOutAmount.gt(new BN18(0))) {
      exactOutAmount = BN18.min(remainingOutAmount, openOrderAmount);
      amountIn = getAmountIn(exactOutAmount, bin.price, swapForY, 0 /* Up */);
      totalAmountIn = totalAmountIn.add(amountIn);
    }
  }
  return totalAmountIn;
}
function swapExactOutQuoteAtBin(bin, binStep, sParameter, vParameter, outAmount, swapForY, supportLimitOrder, feeOnInput) {
  const tradeFeeNumerator = getTotalFee(binStep, sParameter, vParameter);
  let includedFeeAmountOut = outAmount;
  if (!feeOnInput) {
    const { includedFeeAmount } = getIncludedFeeAmount(
      outAmount,
      tradeFeeNumerator
    );
    includedFeeAmountOut = includedFeeAmount;
  }
  const maxAmountOut = getBinMaxAmountOut(bin, swapForY, supportLimitOrder);
  if (includedFeeAmountOut.gte(maxAmountOut)) {
    return swapExactInQuoteAtBin(
      bin,
      binStep,
      sParameter,
      vParameter,
      U64_MAX,
      swapForY,
      supportLimitOrder,
      feeOnInput
    );
  } else {
    const excludedFeeAmountIn = getExcludedFeeAmountIn(
      bin,
      includedFeeAmountOut,
      swapForY
    );
    let includedFeeAmountIn = excludedFeeAmountIn;
    if (feeOnInput) {
      const { includedFeeAmount } = getIncludedFeeAmount(
        excludedFeeAmountIn,
        tradeFeeNumerator
      );
      includedFeeAmountIn = includedFeeAmount;
    }
    let {
      amountIn,
      amountOut: quotedAmountOut,
      fee,
      protocolFee
    } = swapExactInQuoteAtBin(
      bin,
      binStep,
      sParameter,
      vParameter,
      includedFeeAmountIn,
      swapForY,
      supportLimitOrder,
      feeOnInput
    );
    const delta = quotedAmountOut.sub(outAmount);
    if (delta.gt(new BN18(1))) {
      protocolFee = protocolFee.add(delta);
    }
    return {
      amountIn,
      amountOut: outAmount,
      fee,
      protocolFee
    };
  }
}
function calculateExactInFillAmount(bin, amount, maxAmountOut, swapForY) {
  const maxAmountIn = getAmountIn(
    maxAmountOut,
    bin.price,
    swapForY,
    0 /* Up */
  );
  if (amount.gte(maxAmountIn)) {
    return {
      amountIn: maxAmountIn,
      amountLeft: amount.sub(maxAmountIn),
      outAmount: maxAmountOut
    };
  } else {
    const outAmount = getAmountOut(bin, amount, swapForY);
    return {
      amountIn: amount,
      amountLeft: new BN18(0),
      outAmount
    };
  }
}
function getLimitOrderAmountsBySwapDirection(bin, swapForY) {
  const isAskSide = Boolean(bin.limitOrderAskSide);
  if (swapForY && !isAskSide || !swapForY && isAskSide) {
    return {
      openOrderAmount: bin.openOrderAmount,
      processedOrderRemainingAmount: bin.processedOrderRemainingAmount
    };
  }
  return {
    openOrderAmount: new BN18(0),
    processedOrderRemainingAmount: new BN18(0)
  };
}
function getExactInFillAmountResult(bin, amountIn, swapForY, supportLimitOrder) {
  const mmAmount = swapForY ? bin.amountY : bin.amountX;
  const mmFillInResult = calculateExactInFillAmount(
    bin,
    amountIn,
    mmAmount,
    swapForY
  );
  if (!supportLimitOrder) {
    return {
      amountIn: mmFillInResult.amountIn,
      amountLeft: mmFillInResult.amountLeft,
      outAmount: mmFillInResult.outAmount,
      mmAmountIn: mmFillInResult.amountIn,
      mmAmountOut: mmFillInResult.outAmount
    };
  }
  const amountLeftAfterMM = mmFillInResult.amountLeft;
  let processedOrderAmountIn = new BN18(0);
  let processedOrderAmountOut = new BN18(0);
  let openOrderAmountIn = new BN18(0);
  let openOrderAmountOut = new BN18(0);
  if (!amountLeftAfterMM.isZero()) {
    const { openOrderAmount, processedOrderRemainingAmount } = getLimitOrderAmountsBySwapDirection(bin, swapForY);
    const remainingOrderFillInResult = calculateExactInFillAmount(
      bin,
      amountLeftAfterMM,
      processedOrderRemainingAmount,
      swapForY
    );
    processedOrderAmountIn = remainingOrderFillInResult.amountIn;
    processedOrderAmountOut = remainingOrderFillInResult.outAmount;
    if (!remainingOrderFillInResult.amountLeft.isZero()) {
      const openOrderFillInResult = calculateExactInFillAmount(
        bin,
        remainingOrderFillInResult.amountLeft,
        openOrderAmount,
        swapForY
      );
      openOrderAmountIn = openOrderFillInResult.amountIn;
      openOrderAmountOut = openOrderFillInResult.outAmount;
    }
  }
  const totalAmountIn = mmFillInResult.amountIn.add(processedOrderAmountIn).add(openOrderAmountIn);
  const totalAmountOut = mmFillInResult.outAmount.add(processedOrderAmountOut).add(openOrderAmountOut);
  return {
    amountIn: totalAmountIn,
    amountLeft: amountIn.sub(totalAmountIn),
    outAmount: totalAmountOut,
    mmAmountIn: mmFillInResult.amountIn,
    mmAmountOut: mmFillInResult.outAmount
  };
}
function swapExactInQuoteAtBin(bin, binStep, sParameter, vParameter, inAmount, swapForY, supportLimitOrder, feeOnInput) {
  let tradingFee = new BN18(0);
  let excludedFeeAmountIn = inAmount;
  const tradeFeeNumerator = getTotalFee(binStep, sParameter, vParameter);
  if (feeOnInput) {
    const { excludedFeeAmount: amount, fee: fee2 } = getExcludedFeeAmount(
      inAmount,
      tradeFeeNumerator
    );
    tradingFee = fee2;
    excludedFeeAmountIn = amount;
  }
  const fillAmountResult = getExactInFillAmountResult(
    bin,
    excludedFeeAmountIn,
    swapForY,
    supportLimitOrder
  );
  const amountLeft = fillAmountResult.amountLeft;
  const outAmount = fillAmountResult.outAmount;
  let includedFeeAmountIn = inAmount;
  if (!amountLeft.isZero()) {
    excludedFeeAmountIn = excludedFeeAmountIn.sub(amountLeft);
    if (feeOnInput) {
      const { includedFeeAmount: amount, fee: fee2 } = getIncludedFeeAmount(
        excludedFeeAmountIn,
        tradeFeeNumerator
      );
      tradingFee = fee2;
      includedFeeAmountIn = amount;
    } else {
      includedFeeAmountIn = excludedFeeAmountIn;
    }
  }
  let excludedFeeAmountOut = outAmount;
  if (!feeOnInput) {
    const { excludedFeeAmount: amount, fee: fee2 } = getExcludedFeeAmount(
      outAmount,
      tradeFeeNumerator
    );
    tradingFee = fee2;
    excludedFeeAmountOut = amount;
  }
  const { fee, protocolFee } = splitFee(
    tradingFee,
    new BN18(sParameter.protocolShare),
    fillAmountResult.mmAmountIn,
    fillAmountResult.amountIn
  );
  return {
    amountIn: includedFeeAmountIn,
    amountOut: excludedFeeAmountOut,
    fee,
    protocolFee
  };
}
function getLimitOrderLiquidity(bin, supportLimitOrder) {
  if (!supportLimitOrder) {
    return {
      orderAmountX: new BN18(0),
      orderAmountY: new BN18(0)
    };
  }
  const totalOrderAmount = bin.openOrderAmount.add(
    bin.processedOrderRemainingAmount
  );
  const isAskSide = Boolean(bin.limitOrderAskSide);
  if (isAskSide) {
    return {
      orderAmountX: totalOrderAmount,
      orderAmountY: new BN18(0)
    };
  } else {
    return {
      orderAmountX: new BN18(0),
      orderAmountY: totalOrderAmount
    };
  }
}
function getBinMaxAmountOut(bin, swapForY, supportLimitOrder) {
  const { orderAmountX, orderAmountY } = getLimitOrderLiquidity(
    bin,
    supportLimitOrder
  );
  const totalAmount = swapForY ? bin.amountY.add(orderAmountY) : bin.amountX.add(orderAmountX);
  return totalAmount;
}

// src/dlmm/helpers/oracle/wrapper.ts
import BN19 from "bn.js";
import Decimal8 from "decimal.js";
var ORACLE_METADATA_SIZE = 8 + 24;
var OBSERVATION_SIZE = 32;
var Observation = class {
  constructor(cumulativeActiveBinId, createdAt, lastUpdatedAt) {
    this.cumulativeActiveBinId = cumulativeActiveBinId;
    this.createdAt = createdAt;
    this.lastUpdatedAt = lastUpdatedAt;
  }
  isInitialized() {
    return !this.createdAt.isZero() && !this.lastUpdatedAt.isZero();
  }
};
function wrapOracle(oracleAddress, data, binStep, currentActiveBinId, baseTokenDecimals, quoteTokenDecimals, program) {
  const oracleBaseData = data.subarray(0, ORACLE_METADATA_SIZE);
  const oracleState = decodeAccount(program, "oracle", oracleBaseData);
  const observationSlice = data.subarray(ORACLE_METADATA_SIZE);
  let observations = [];
  for (let i = 0; i < oracleState.length.toNumber(); i++) {
    let offset = i * OBSERVATION_SIZE;
    const cumulativeActiveBinIdSlice = observationSlice.subarray(
      offset,
      offset + 16
    );
    const cumulativeActiveBinId = new BN19(
      cumulativeActiveBinIdSlice,
      "le"
    ).fromTwos(128);
    offset += 16;
    const createdAtSlice = observationSlice.subarray(offset, offset + 8);
    const createdAt = new BN19(createdAtSlice, "le");
    offset += 8;
    const lastUpdatedAtSlice = observationSlice.subarray(offset, offset + 8);
    const lastUpdatedAt = new BN19(lastUpdatedAtSlice, "le");
    observations.push(
      new Observation(cumulativeActiveBinId, createdAt, lastUpdatedAt)
    );
  }
  return new DynamicOracle(
    oracleAddress,
    oracleState,
    observations,
    binStep,
    currentActiveBinId,
    baseTokenDecimals,
    quoteTokenDecimals
  );
}
var DynamicOracle = class {
  constructor(oracleAddress, metadata, observations, binStep, currentActiveBinId, baseTokenDecimals, quoteTokenDecimals) {
    this.oracleAddress = oracleAddress;
    this.metadata = metadata;
    this.observations = observations;
    this.binStep = binStep;
    this.currentActiveBinId = currentActiveBinId;
    this.baseTokenDecimals = baseTokenDecimals;
    this.quoteTokenDecimals = quoteTokenDecimals;
  }
  nextIndex() {
    const currentIndex = this.metadata.idx.toNumber();
    const nextIndex = currentIndex + 1;
    return nextIndex >= this.metadata.activeSize.toNumber() ? 0 : nextIndex;
  }
  getEarliestSample() {
    const earliestIndex = this.nextIndex();
    return this.observations[earliestIndex];
  }
  getLatestSample() {
    return this.observations[this.metadata.idx.toNumber()];
  }
  findCumulativeActiveIdByTimestamp(activeId, timestamp) {
    const latestSample = this.getLatestSample();
    if (!latestSample.isInitialized()) {
      return null;
    }
    if (timestamp.gte(latestSample.lastUpdatedAt)) {
      const deltaSeconds = timestamp.sub(latestSample.lastUpdatedAt);
      const accumulatedActiveId = activeId.mul(deltaSeconds);
      return latestSample.cumulativeActiveBinId.add(accumulatedActiveId);
    }
    const earliestSample = this.getEarliestSample();
    if (!earliestSample.isInitialized() || timestamp.lt(earliestSample.lastUpdatedAt)) {
      return null;
    }
    let currentIndex = this.metadata.idx.toNumber();
    while (true) {
      let previousIndex = currentIndex == 0 ? this.metadata.activeSize.toNumber() - 1 : currentIndex - 1;
      if (previousIndex == this.metadata.idx.toNumber()) {
        return null;
      }
      const currentSample = this.observations[currentIndex];
      const previousSample = this.observations[previousIndex];
      if (timestamp.gte(previousSample.lastUpdatedAt)) {
        const totalWeight = currentSample.lastUpdatedAt.sub(
          previousSample.lastUpdatedAt
        );
        if (totalWeight.isZero()) {
          return previousSample.cumulativeActiveBinId;
        }
        const prevWeight = currentSample.lastUpdatedAt.sub(timestamp);
        const nextWeight = timestamp.sub(previousSample.lastUpdatedAt);
        return previousSample.cumulativeActiveBinId.mul(prevWeight).add(currentSample.cumulativeActiveBinId.mul(nextWeight)).div(totalWeight);
      }
      currentIndex = previousIndex;
    }
  }
  getActiveIdByTime(timePoint0, timePoint1) {
    const t0 = BN19.min(timePoint0, timePoint1);
    const t1 = BN19.max(timePoint0, timePoint1);
    const duration = t1.sub(t0);
    if (duration.isZero()) {
      return null;
    }
    const cumulativeActiveBinId0 = this.findCumulativeActiveIdByTimestamp(
      this.currentActiveBinId,
      t0
    );
    if (cumulativeActiveBinId0 === null) {
      return null;
    }
    const cumulativeActiveBinId1 = this.findCumulativeActiveIdByTimestamp(
      this.currentActiveBinId,
      t1
    );
    if (cumulativeActiveBinId1 === null) {
      return null;
    }
    return {
      value: cumulativeActiveBinId1.sub(cumulativeActiveBinId0).div(duration),
      duration
    };
  }
  getActiveId(currentTimestamp) {
    const timePoint0 = this.getEarliestTimestamp();
    if (timePoint0 === null) {
      return null;
    }
    const timePoint1 = currentTimestamp;
    return this.getActiveIdByTime(timePoint0, timePoint1);
  }
  getEarliestTimestamp() {
    const earliestSample = this.getEarliestSample();
    return earliestSample.isInitialized() ? earliestSample.lastUpdatedAt : null;
  }
  getPriceByTime(timePoint0, timePoint1) {
    const result = this.getActiveIdByTime(timePoint0, timePoint1);
    if (result === null) {
      return null;
    }
    return {
      value: getPriceOfBinByBinId(result.value.toNumber(), this.binStep),
      duration: result.duration
    };
  }
  getUiPriceByTime(timePoint0, timePoint1) {
    const result = this.getPriceByTime(timePoint0, timePoint1);
    if (result === null) {
      return null;
    }
    const uiMultiplier = new Decimal8(10).pow(
      this.baseTokenDecimals - this.quoteTokenDecimals
    );
    const quoteAdjustment = new Decimal8(10).pow(this.quoteTokenDecimals);
    return {
      value: result.value.mul(uiMultiplier).mul(quoteAdjustment).floor().div(quoteAdjustment),
      duration: result.duration
    };
  }
  getMaxDuration(currentTimestamp) {
    const earliestTimestamp = this.getEarliestTimestamp();
    if (earliestTimestamp === null) {
      return new BN19(0);
    }
    if (currentTimestamp.lte(earliestTimestamp)) {
      return new BN19(0);
    }
    return currentTimestamp.sub(earliestTimestamp);
  }
};

// src/dlmm/helpers/index.ts
function chunks(array, size) {
  return Array.apply(0, new Array(Math.ceil(array.length / size))).map(
    (_, index) => array.slice(index * size, (index + 1) * size)
  );
}
function range(min, max, mapfn) {
  const length = max - min + 1;
  return Array.from({ length }, (_, i) => mapfn(min + i));
}
async function chunkedFetchMultiplePoolAccount(program, pks, chunkSize = 100) {
  const accounts = (await Promise.all(
    chunks(pks, chunkSize).map(
      (chunk) => program.account.lbPair.fetchMultiple(chunk)
    )
  )).flat();
  return accounts.filter(Boolean);
}
async function chunkedFetchMultipleBinArrayBitmapExtensionAccount(program, pks, chunkSize = 100) {
  const accounts = (await Promise.all(
    chunks(pks, chunkSize).map(
      (chunk) => program.account.binArrayBitmapExtension.fetchMultiple(chunk)
    )
  )).flat();
  return accounts;
}
async function getTokenDecimals(conn, mint) {
  const token = await getMint(conn, mint);
  return await token.decimals;
}
var getOrCreateATAInstruction = async (connection, tokenMint, owner, programId, payer = owner, allowOwnerOffCurve = true) => {
  programId = programId ?? TOKEN_PROGRAM_ID3;
  const toAccount = getAssociatedTokenAddressSync(
    tokenMint,
    owner,
    allowOwnerOffCurve,
    programId,
    ASSOCIATED_TOKEN_PROGRAM_ID
  );
  try {
    await getAccount(connection, toAccount, connection.commitment, programId);
    return { ataPubKey: toAccount, ix: void 0 };
  } catch (e) {
    if (e instanceof TokenAccountNotFoundError || e instanceof TokenInvalidAccountOwnerError) {
      const ix = createAssociatedTokenAccountIdempotentInstruction(
        payer,
        toAccount,
        owner,
        tokenMint,
        programId,
        ASSOCIATED_TOKEN_PROGRAM_ID
      );
      return { ataPubKey: toAccount, ix };
    } else {
      console.error("Error::getOrCreateATAInstruction", e);
      throw e;
    }
  }
};
async function getTokenBalance(conn, tokenAccount) {
  const acc = await getAccount(conn, tokenAccount);
  return acc.amount;
}
var parseLogs = (eventParser, logs) => {
  if (!logs.length)
    throw new Error("No logs found");
  for (const event of eventParser?.parseLogs(logs)) {
    return event.data;
  }
  throw new Error("No events found");
};
var wrapSOLInstruction = (from, to, amount) => {
  return [
    SystemProgram.transfer({
      fromPubkey: from,
      toPubkey: to,
      lamports: amount
    }),
    new TransactionInstruction3({
      keys: [
        {
          pubkey: to,
          isSigner: false,
          isWritable: true
        }
      ],
      data: Buffer.from(new Uint8Array([17])),
      programId: TOKEN_PROGRAM_ID3
    })
  ];
};
var unwrapSOLInstruction = (owner, allowOwnerOffCurve = true) => {
  const wSolATAAccount = getAssociatedTokenAddressSync(
    NATIVE_MINT,
    owner,
    allowOwnerOffCurve
  );
  if (wSolATAAccount) {
    const closedWrappedSolInstruction = createCloseAccountInstruction(
      wSolATAAccount,
      owner,
      owner,
      [],
      TOKEN_PROGRAM_ID3
    );
    return closedWrappedSolInstruction;
  }
  return null;
};
async function chunkedGetMultipleAccountInfos(connection, pks, chunkSize = 100) {
  const accountInfos = (await Promise.all(
    chunks(pks, chunkSize).map(
      (chunk) => connection.getMultipleAccountsInfo(chunk)
    )
  )).flat();
  return accountInfos;
}
async function chunkedGetProgramAccounts(connection, programId, filters, chunkSize = 100, onChunkFetched, isParallelExecution = false) {
  const accountsWithoutData = await connection.getProgramAccounts(programId, {
    filters,
    dataSlice: { offset: 0, length: 0 }
  });
  if (accountsWithoutData.length === 0) {
    return [];
  }
  const pubkeys = accountsWithoutData.map((account) => account.pubkey);
  const totalAccounts = pubkeys.length;
  const chunkedPks = chunks(pubkeys, chunkSize);
  const totalChunks = chunkedPks.length;
  let chunksLoaded = 0;
  let accountsLoaded = 0;
  const chunkResults = new Array(totalChunks);
  const processChunk = async (chunk, chunkIndex) => {
    const chunkAccountInfos = await connection.getMultipleAccountsInfo(chunk);
    chunkResults[chunkIndex] = chunkAccountInfos;
    if (onChunkFetched) {
      const chunkAccounts = [];
      const startIdx = chunkIndex * chunkSize;
      for (let i = 0; i < chunkAccountInfos.length; i++) {
        const accountInfo = chunkAccountInfos[i];
        if (accountInfo) {
          chunkAccounts.push({
            pubkey: pubkeys[startIdx + i],
            account: accountInfo
          });
        }
      }
      chunksLoaded++;
      accountsLoaded += chunkAccounts.length;
      onChunkFetched(chunkAccounts, {
        chunksLoaded,
        totalChunks,
        accountsLoaded,
        totalAccounts
      });
    }
  };
  if (isParallelExecution) {
    await Promise.all(
      chunkedPks.map((chunk, chunkIndex) => processChunk(chunk, chunkIndex))
    );
  } else {
    for (let chunkIndex = 0; chunkIndex < chunkedPks.length; chunkIndex++) {
      await processChunk(chunkedPks[chunkIndex], chunkIndex);
    }
  }
  const result = [];
  for (let chunkIndex = 0; chunkIndex < chunkResults.length; chunkIndex++) {
    const chunkAccountInfos = chunkResults[chunkIndex];
    const startIdx = chunkIndex * chunkSize;
    for (let i = 0; i < chunkAccountInfos.length; i++) {
      const accountInfo = chunkAccountInfos[i];
      if (accountInfo) {
        result.push({
          pubkey: pubkeys[startIdx + i],
          account: accountInfo
        });
      }
    }
  }
  return result;
}
var getEstimatedComputeUnitUsageWithBuffer = async (connection, instructions, feePayer, buffer, altAddress) => {
  if (!buffer) {
    buffer = 0.1;
  }
  buffer = Math.max(0, buffer);
  buffer = Math.min(1, buffer);
  const altAccounts = [];
  if (altAddress) {
    const altAccountInfo = await connection.getAddressLookupTable(altAddress);
    altAccounts.push(altAccountInfo.value);
  }
  const estimatedComputeUnitUsage = await getSimulationComputeUnits(
    connection,
    instructions,
    feePayer,
    altAccounts
  );
  let extraComputeUnitBuffer = estimatedComputeUnitUsage * buffer;
  if (extraComputeUnitBuffer > MAX_CU_BUFFER) {
    extraComputeUnitBuffer = MAX_CU_BUFFER;
  } else if (extraComputeUnitBuffer < MIN_CU_BUFFER) {
    extraComputeUnitBuffer = MIN_CU_BUFFER;
  }
  return estimatedComputeUnitUsage + extraComputeUnitBuffer;
};
var getEstimatedComputeUnitIxWithBuffer = async (connection, instructions, feePayer, buffer, altAddress) => {
  const units = await getEstimatedComputeUnitUsageWithBuffer(
    connection,
    instructions,
    feePayer,
    buffer,
    altAddress
  ).catch((error) => {
    console.error("Error::getEstimatedComputeUnitUsageWithBuffer", error);
    return 14e5;
  });
  return ComputeBudgetProgram2.setComputeUnitLimit({ units });
};
function createProgram(connection, opt) {
  const cluster = opt?.cluster || "mainnet-beta";
  const provider = new AnchorProvider(
    connection,
    {},
    AnchorProvider.defaultOptions()
  );
  return new Program2(
    { ...idl_default, address: opt?.programId ?? LBCLMM_PROGRAM_IDS[cluster] },
    provider
  );
}
function decodeAccount(program, accountName, buffer) {
  return program.coder.accounts.decode(accountName, buffer);
}
function getAccountDiscriminator(accountName) {
  return idl_default.accounts.find(
    (acc) => acc.name.toLowerCase() === accountName.toLowerCase()
  )?.discriminator;
}
function capSlippagePercentage(slippage) {
  if (slippage > 100) {
    slippage = 100;
  }
  if (slippage < 0) {
    slippage = 0;
  }
  return slippage;
}
function getAndCapMaxActiveBinSlippage(slippagePercentage, binStep, maxActiveBinSlippage) {
  return slippagePercentage ? Math.ceil(slippagePercentage / (binStep / 100)) : maxActiveBinSlippage;
}
function getBinCount(minBinId, maxBinId) {
  return maxBinId - minBinId + 1;
}
function getSlippageMaxAmount(amount, slippage) {
  if (slippage == 100) {
    return U64_MAX;
  }
  const amountDecimal = new Decimal9(amount.toString());
  const slippageAppliedAmount = new BN20(
    amountDecimal.mul(new Decimal9(100 + slippage)).div(new Decimal9(100)).floor().toString()
  );
  return slippageAppliedAmount;
}
function getSlippageMinAmount(amount, slippage) {
  const amountDecimal = new Decimal9(amount.toString());
  return new BN20(
    amountDecimal.mul(new Decimal9(100 - slippage)).div(new Decimal9(100)).ceil().toString()
  );
}
function getPositionCountByBinCount(binCount) {
  return Math.ceil(binCount / MAX_BINS_PER_POSITION.toNumber());
}
function resetUninvolvedLiquidityParams(minDeltaId, maxDeltaId, favorXInActiveId, params) {
  const endBidSideDeltaId = favorXInActiveId ? new BN20(-1) : new BN20(0);
  const startAskSideDeltaId = endBidSideDeltaId.addn(1);
  let x0 = params.x0;
  let y0 = params.y0;
  let deltaX = params.deltaX;
  let deltaY = params.deltaY;
  if (maxDeltaId.lte(endBidSideDeltaId)) {
    deltaX = new BN20(0);
    x0 = new BN20(0);
  }
  if (minDeltaId.gte(startAskSideDeltaId)) {
    deltaY = new BN20(0);
    y0 = new BN20(0);
  }
  return {
    x0,
    y0,
    deltaX,
    deltaY
  };
}
async function chunkDepositWithRebalanceEndpoint(dlmm, strategy, slippagePercentage, maxActiveBinSlippage, position, positionMinBinId, positionMaxBinId, liquidityStrategyParameters, owner, payer, isParallel, skipSolWrappingOperation = false) {
  const { slices, accounts: transferHookAccounts } = dlmm.getPotentialToken2022IxDataAndAccounts(0 /* Liquidity */);
  const userTokenX = getAssociatedTokenAddressSync(
    dlmm.lbPair.tokenXMint,
    owner,
    true,
    dlmm.tokenX.owner
  );
  const userTokenY = getAssociatedTokenAddressSync(
    dlmm.lbPair.tokenYMint,
    owner,
    true,
    dlmm.tokenY.owner
  );
  const createUserTokenXIx = createAssociatedTokenAccountIdempotentInstruction(
    payer,
    userTokenX,
    owner,
    dlmm.lbPair.tokenXMint,
    dlmm.tokenX.owner
  );
  const createUserTokenYIx = createAssociatedTokenAccountIdempotentInstruction(
    payer,
    userTokenY,
    owner,
    dlmm.lbPair.tokenYMint,
    dlmm.tokenY.owner
  );
  const bitmapPubkey = deriveBinArrayBitmapExtension(
    dlmm.pubkey,
    dlmm.program.programId
  )[0];
  let calculatedAddLiquidityCU = 0;
  const chunkedAddLiquidityIx = [];
  const chunkedBinRange = chunkBinRange(positionMinBinId, positionMaxBinId);
  const binArrayOrBitmapInitTracking = /* @__PURE__ */ new Set();
  for (let i = 0; i < chunkedBinRange.length; i++) {
    const chunkMinBinId = chunkedBinRange[i].lowerBinId;
    const chunkMaxBinId = chunkedBinRange[i].upperBinId;
    const initBinArrayIxs = [];
    const initBitmapIxs = [];
    const binArrayIndexes = getBinArrayIndexesCoverage(
      new BN20(chunkMinBinId),
      new BN20(chunkMaxBinId)
    );
    const overflowDefaultBinArrayBitmap = binArrayIndexes.reduce(
      (acc, binArrayIndex) => acc || isOverflowDefaultBinArrayBitmap(binArrayIndex),
      false
    );
    if (overflowDefaultBinArrayBitmap) {
      const initBitmapIx = await dlmm.program.methods.initializeBinArrayBitmapExtension().accountsPartial({
        binArrayBitmapExtension: bitmapPubkey,
        lbPair: dlmm.pubkey,
        funder: payer,
        rent: SYSVAR_RENT_PUBKEY
      }).instruction();
      initBitmapIxs.push(initBitmapIx);
      binArrayOrBitmapInitTracking.add(bitmapPubkey.toBase58());
    }
    const binArrayPubkeys = binArrayIndexes.map(
      (index) => deriveBinArray(dlmm.pubkey, index, dlmm.program.programId)[0]
    );
    for (const [idx, binArrayPubkey] of binArrayPubkeys.entries()) {
      const initBinArrayIx = await dlmm.program.methods.initializeBinArray(binArrayIndexes[idx]).accountsPartial({
        binArray: binArrayPubkey,
        funder: payer,
        lbPair: dlmm.pubkey
      }).instruction();
      if (isParallel) {
        initBinArrayIxs.push(initBinArrayIx);
      } else if (!binArrayOrBitmapInitTracking.has(binArrayPubkey.toBase58())) {
        binArrayOrBitmapInitTracking.add(binArrayPubkey.toBase58());
        initBinArrayIxs.push(initBinArrayIx);
        calculatedAddLiquidityCU += DEFAULT_INIT_BIN_ARRAY_CU;
      }
    }
    const minDeltaId = new BN20(chunkMinBinId - dlmm.lbPair.activeId);
    const maxDeltaId = new BN20(chunkMaxBinId - dlmm.lbPair.activeId);
    const { deltaX, deltaY, x0, y0 } = resetUninvolvedLiquidityParams(
      minDeltaId,
      maxDeltaId,
      strategy.singleSidedX,
      {
        ...liquidityStrategyParameters
      }
    );
    const { bitFlag, ...baseAndDelta } = buildBitFlagAndNegateStrategyParameters(x0, y0, deltaX, deltaY);
    const addParam = {
      minDeltaId: minDeltaId.toNumber(),
      maxDeltaId: maxDeltaId.toNumber(),
      x0: baseAndDelta.x0,
      y0: baseAndDelta.y0,
      deltaX: baseAndDelta.deltaX,
      deltaY: baseAndDelta.deltaY,
      bitFlag,
      favorXInActiveId: strategy.singleSidedX,
      padding: Array(36).fill(0)
    };
    const { totalXAmount, totalYAmount } = toAmountIntoBins(
      new BN20(dlmm.lbPair.activeId),
      minDeltaId,
      maxDeltaId,
      deltaX,
      deltaY,
      x0,
      y0,
      new BN20(dlmm.lbPair.binStep),
      strategy.singleSidedX
    ).reduce(
      (acc, bin) => {
        return {
          totalXAmount: acc.totalXAmount.add(bin.amountX),
          totalYAmount: acc.totalYAmount.add(bin.amountY)
        };
      },
      {
        totalXAmount: new BN20(0),
        totalYAmount: new BN20(0)
      }
    );
    const totalXAmountIncludeTransferFee = calculateTransferFeeIncludedAmount(
      totalXAmount,
      dlmm.tokenX.mint,
      dlmm.clock.epoch.toNumber()
    ).amount;
    const totalYAmountIncludeTransferFee = calculateTransferFeeIncludedAmount(
      totalYAmount,
      dlmm.tokenY.mint,
      dlmm.clock.epoch.toNumber()
    ).amount;
    const maxDepositXAmount = getSlippageMaxAmount(
      totalXAmountIncludeTransferFee,
      slippagePercentage
    );
    const maxDepositYAmount = getSlippageMaxAmount(
      totalYAmountIncludeTransferFee,
      slippagePercentage
    );
    let shrinkMode;
    if (isParallel) {
      if (i == 0) {
        shrinkMode = 2 /* NoShrinkRight */;
      } else if (i == chunkBinRange.length - 1) {
        shrinkMode = 1 /* NoShrinkLeft */;
      } else {
        shrinkMode = 3 /* NoShrinkBoth */;
      }
    } else {
      shrinkMode = 0 /* ShrinkBoth */;
    }
    const rebalanceIx = await dlmm.program.methods.rebalanceLiquidity(
      {
        activeId: dlmm.lbPair.activeId,
        maxActiveBinSlippage,
        shouldClaimFee: false,
        shouldClaimReward: false,
        minWithdrawXAmount: new BN20(0),
        minWithdrawYAmount: new BN20(0),
        maxDepositXAmount,
        maxDepositYAmount,
        removes: [],
        adds: [addParam],
        shrinkMode,
        padding: REBALANCE_POSITION_PADDING
      },
      {
        slices
      }
    ).accountsPartial({
      binArrayBitmapExtension: initBitmapIxs.length > 0 ? bitmapPubkey : dlmm.program.programId,
      lbPair: dlmm.pubkey,
      position,
      owner,
      tokenXMint: dlmm.lbPair.tokenXMint,
      tokenYMint: dlmm.lbPair.tokenYMint,
      userTokenX,
      userTokenY,
      tokenXProgram: dlmm.tokenX.owner,
      tokenYProgram: dlmm.tokenY.owner,
      rentPayer: payer
    }).remainingAccounts([
      ...transferHookAccounts,
      ...binArrayPubkeys.map((baPubkey) => ({
        pubkey: baPubkey,
        isWritable: true,
        isSigner: false
      })),
      derivePlaceHolderAccountMeta(dlmm.program.programId)
    ]).instruction();
    calculatedAddLiquidityCU += DEFAULT_ADD_LIQUIDITY_CU;
    const addLiquidityIxs = [];
    addLiquidityIxs.push(...initBitmapIxs, ...initBinArrayIxs);
    if (isParallel) {
      addLiquidityIxs.push(createUserTokenXIx);
      addLiquidityIxs.push(createUserTokenYIx);
    }
    if (dlmm.tokenX.publicKey.equals(NATIVE_MINT) && !skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        owner,
        userTokenX,
        BigInt(totalXAmount.toString())
      );
      if (!isParallel) {
        addLiquidityIxs.push(createUserTokenXIx);
      }
      addLiquidityIxs.push(...wrapSOLIx);
    }
    if (dlmm.tokenY.publicKey.equals(NATIVE_MINT) && !skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        owner,
        userTokenY,
        BigInt(totalYAmount.toString())
      );
      if (!isParallel) {
        addLiquidityIxs.push(createUserTokenYIx);
      }
      addLiquidityIxs.push(...wrapSOLIx);
    }
    addLiquidityIxs.push(rebalanceIx);
    if (dlmm.tokenX.publicKey.equals(NATIVE_MINT) && !totalXAmount.isZero() && !skipSolWrappingOperation) {
      addLiquidityIxs.push(
        createCloseAccountInstruction(
          userTokenX,
          owner,
          owner,
          [],
          TOKEN_PROGRAM_ID3
        )
      );
    }
    if (dlmm.tokenY.publicKey.equals(NATIVE_MINT) && !totalYAmount.isZero() && !skipSolWrappingOperation) {
      addLiquidityIxs.push(
        createCloseAccountInstruction(
          userTokenY,
          owner,
          owner,
          [],
          TOKEN_PROGRAM_ID3
        )
      );
    }
    if (!isParallel) {
      addLiquidityIxs.unshift(
        ComputeBudgetProgram2.setComputeUnitLimit({
          units: Math.min(calculatedAddLiquidityCU, MAX_CU)
        })
      );
    }
    chunkedAddLiquidityIx.push(addLiquidityIxs);
  }
  return chunkedAddLiquidityIx;
}
function encodePositionPermissions(permissions) {
  return permissions.reduce((acc, perm) => {
    return acc | 1 << perm;
  }, 0);
}

// src/dlmm/helpers/accountFilters.ts
import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes";
var presetParameter2BinStepFilter = (binStep) => {
  return {
    memcmp: {
      bytes: bs58.encode(binStep.toArrayLike(Buffer, "le", 2)),
      offset: 8
    }
  };
};
var presetParameter2BaseFactorFilter = (baseFactor) => {
  return {
    memcmp: {
      bytes: bs58.encode(baseFactor.toArrayLike(Buffer, "le", 2)),
      offset: 8 + 2
    }
  };
};
var presetParameter2BaseFeePowerFactor = (baseFeePowerFactor) => {
  return {
    memcmp: {
      bytes: bs58.encode(baseFeePowerFactor.toArrayLike(Buffer, "le", 1)),
      offset: 8 + 22
    }
  };
};
var binArrayLbPairFilter = (lbPair) => {
  return {
    memcmp: {
      bytes: lbPair.toBase58(),
      offset: 8 + 16
    }
  };
};
var positionOwnerFilter = (owner) => {
  return {
    memcmp: {
      bytes: owner.toBase58(),
      offset: 8 + 32
    }
  };
};
var positionLbPairFilter = (lbPair) => {
  return {
    memcmp: {
      bytes: bs58.encode(lbPair.toBuffer()),
      offset: 8
    }
  };
};
var positionV2Filter = () => {
  return {
    memcmp: {
      bytes: bs58.encode(Buffer.from(getAccountDiscriminator("positionV2"))),
      offset: 0
    }
  };
};
var limitOrderFilter = () => {
  return {
    memcmp: {
      bytes: bs58.encode(Buffer.from(getAccountDiscriminator("limitOrder"))),
      offset: 0
    }
  };
};
var limitOrderOwnerFilter = (owner) => {
  return {
    memcmp: {
      bytes: owner.toBase58(),
      offset: 8 + 32
    }
  };
};
var limitOrderLbPairFilter = (lbPair) => {
  return {
    memcmp: {
      bytes: lbPair.toBase58(),
      offset: 8
    }
  };
};

// src/dlmm/helpers/rebalance/strategy/balanced.ts
import BN22 from "bn.js";

// src/dlmm/helpers/rebalance/strategy/index.ts
import BN21 from "bn.js";
var MAX_BPS = new BN21(BASIS_POINT_MAX);
function capBps(bps) {
  return bps.lt(new BN21(0)) ? new BN21(0) : bps.gt(MAX_BPS) ? new BN21(MAX_BPS) : bps;
}

// src/dlmm/helpers/rebalance/strategy/balanced.ts
var BalancedStrategyBuilder = class {
  constructor(activeId, binStep, positionData, topUpAmountX, topUpAmountY, xWithdrawBps, yWithdrawBps, strategy, favorXIfImbalance = false, favorXInActiveBin = false) {
    this.activeId = activeId;
    this.binStep = binStep;
    this.positionData = positionData;
    this.topUpAmountX = topUpAmountX;
    this.topUpAmountY = topUpAmountY;
    this.xWithdrawBps = xWithdrawBps;
    this.yWithdrawBps = yWithdrawBps;
    this.strategy = strategy;
    this.favorXIfImbalance = favorXIfImbalance;
    this.favorXInActiveBin = favorXInActiveBin;
  }
  // Rebalance to active bin by withdrawing all liquidities and redeposit portion of withdrawn liquidity, together with topup amount
  buildRebalanceStrategyParameters() {
    const xWithdrawBps = capBps(this.xWithdrawBps);
    const yWithdrawBps = capBps(this.yWithdrawBps);
    let totalXAmountOut = new BN22(this.positionData.totalXAmount);
    let totalYAmountOut = new BN22(this.positionData.totalYAmount);
    totalXAmountOut = totalXAmountOut.add(new BN22(this.positionData.feeX));
    totalYAmountOut = totalYAmountOut.add(new BN22(this.positionData.feeY));
    const redepositAmountX = totalXAmountOut.mul(MAX_BPS.sub(xWithdrawBps)).div(MAX_BPS);
    const redepositAmountY = totalYAmountOut.mul(MAX_BPS.sub(yWithdrawBps)).div(MAX_BPS);
    const depositAmountX = this.topUpAmountX.add(redepositAmountX);
    const depositAmountY = this.topUpAmountY.add(redepositAmountY);
    const width = this.positionData.upperBinId - this.positionData.lowerBinId + 1;
    const binPerSide = Math.floor(width / 2);
    const rem = width % 2;
    let binPerAsk = binPerSide;
    let binPerBid = binPerSide;
    if (rem == 0) {
      if (this.favorXIfImbalance) {
        binPerAsk += 1;
        binPerBid -= 1;
      } else {
        binPerAsk -= 1;
        binPerBid += 1;
      }
    }
    const minDeltaId = new BN22(binPerBid).neg();
    const maxDeltaId = new BN22(binPerAsk);
    const strategyParameters = buildLiquidityStrategyParameters(
      depositAmountX,
      depositAmountY,
      minDeltaId,
      maxDeltaId,
      this.binStep,
      this.favorXInActiveBin,
      this.activeId,
      getLiquidityStrategyParameterBuilder(this.strategy)
    );
    const depositParam = {
      minDeltaId,
      maxDeltaId,
      x0: strategyParameters.x0,
      y0: strategyParameters.y0,
      deltaX: strategyParameters.deltaX,
      deltaY: strategyParameters.deltaY,
      favorXInActiveBin: this.favorXInActiveBin
    };
    const withdrawParam = {
      minBinId: new BN22(this.positionData.lowerBinId),
      maxBinId: new BN22(this.positionData.upperBinId),
      bps: MAX_BPS
    };
    return {
      shouldClaimFee: true,
      shouldClaimReward: true,
      deposits: [depositParam],
      withdraws: [withdrawParam]
    };
  }
};

// src/dlmm/helpers/limitOrders/wrapper.ts
import BN23 from "bn.js";
import Decimal10 from "decimal.js";
var LimitOrderBinDataWrapper = class {
  constructor(inner) {
    this.inner = inner;
  }
  amount() {
    return this.inner.amount;
  }
  age() {
    return this.inner.age;
  }
  binId() {
    return this.inner.binId;
  }
  isAsk() {
    return Boolean(this.inner.isAsk);
  }
  isEmpty() {
    return this.inner.age == 0 && this.inner.amount.isZero();
  }
};
var LimitOrderV1Wrapper = class {
  constructor(limitOrderAddress, inner, limitOrderBinData) {
    this.limitOrderAddress = limitOrderAddress;
    this.inner = inner;
    this.limitOrderBinData = limitOrderBinData;
  }
  address() {
    return this.limitOrderAddress;
  }
  lbPair() {
    return this.inner.lbPair;
  }
  owner() {
    return this.inner.owner;
  }
  binCount() {
    return this.inner.binCount;
  }
  orders() {
    return this.limitOrderBinData;
  }
  getBinArrayIndexesCoverage() {
    const binArrayIndexes = /* @__PURE__ */ new Set();
    for (const bin of this.limitOrderBinData) {
      const binArrayIndex = binIdToBinArrayIndex(new BN23(bin.binId()));
      binArrayIndexes.add(binArrayIndex.toNumber());
    }
    return [...binArrayIndexes].map((index) => new BN23(index));
  }
  getBinArrayKeysCoverage(programId) {
    return this.getBinArrayIndexesCoverage().map(
      (index) => deriveBinArray(this.lbPair(), index, programId)[0]
    );
  }
  parseInfo(programId, lbPair, baseMint, quoteMint, clock, binArrayMap) {
    let totalAmountXDeposited = new BN23(0);
    let totalAmountYDeposited = new BN23(0);
    let totalFilledAmountX = new BN23(0);
    let totalFilledAmountY = new BN23(0);
    let totalUnfilledAmountX = new BN23(0);
    let totalUnfilledAmountY = new BN23(0);
    let totalSwappedAmountX = new BN23(0);
    let totalSwappedAmountY = new BN23(0);
    let totalFeeAmountX = new BN23(0);
    let totalFeeAmountY = new BN23(0);
    const collectFeeMode = lbPair.parameters.collectFeeMode;
    const parsedLimitOrderBinData = [];
    const tokenXUiMultiplier = new Decimal10(10).pow(
      new Decimal10(baseMint.decimals)
    );
    const tokenYUiMultiplier = new Decimal10(10).pow(
      new Decimal10(quoteMint.decimals)
    );
    for (const loBin of this.limitOrderBinData) {
      const binArrayIndex = binIdToBinArrayIndex(new BN23(loBin.binId()));
      const binArrayPubkey = deriveBinArray(
        this.lbPair(),
        binArrayIndex,
        programId
      )[0];
      const binArrayState = binArrayMap.get(binArrayPubkey.toString());
      if (!binArrayState) {
        throw new Error("Missing bin array for limit order");
      }
      const bin = getBinFromBinArray(loBin.binId(), binArrayState);
      if (!bin) {
        throw new Error("Missing bin for limit order");
      }
      const limitOrderStatus = getLimitOrderStatus(loBin, bin);
      const updatedLimitOrderAmount = getUpdatedLimitOrderAmount(
        limitOrderStatus,
        loBin,
        bin,
        collectFeeMode
      );
      let depositAmountX = new BN23(0);
      let depositAmountY = new BN23(0);
      let swappedAmountX = new BN23(0);
      let swappedAmountY = new BN23(0);
      let filledAmountX = new BN23(0);
      let filledAmountY = new BN23(0);
      let unFilledAmountX = new BN23(0);
      let unFilledAmountY = new BN23(0);
      let feeAmountX = new BN23(0);
      let feeAmountY = new BN23(0);
      if (loBin.isAsk()) {
        depositAmountX = loBin.amount();
        filledAmountX = updatedLimitOrderAmount.fulFilledAmount;
        unFilledAmountX = updatedLimitOrderAmount.unFilledAmount;
        swappedAmountY = updatedLimitOrderAmount.swappedAmount;
      } else {
        depositAmountY = loBin.amount();
        filledAmountY = updatedLimitOrderAmount.fulFilledAmount;
        unFilledAmountY = updatedLimitOrderAmount.unFilledAmount;
        swappedAmountX = updatedLimitOrderAmount.swappedAmount;
      }
      feeAmountX = updatedLimitOrderAmount.feeXAmount;
      feeAmountY = updatedLimitOrderAmount.feeYAmount;
      totalFeeAmountX = totalFeeAmountX.add(feeAmountX);
      totalFeeAmountY = totalFeeAmountY.add(feeAmountY);
      totalAmountXDeposited = totalAmountXDeposited.add(depositAmountX);
      totalAmountYDeposited = totalAmountYDeposited.add(depositAmountY);
      totalFilledAmountX = totalFilledAmountX.add(filledAmountX);
      totalFilledAmountY = totalFilledAmountY.add(filledAmountY);
      totalUnfilledAmountX = totalUnfilledAmountX.add(unFilledAmountX);
      totalUnfilledAmountY = totalUnfilledAmountY.add(unFilledAmountY);
      totalSwappedAmountX = totalSwappedAmountX.add(swappedAmountX);
      totalSwappedAmountY = totalSwappedAmountY.add(swappedAmountY);
      parsedLimitOrderBinData.push({
        binId: loBin.binId(),
        empty: loBin.isEmpty(),
        depositAmountX: new Decimal10(depositAmountX.toString()).div(tokenXUiMultiplier).toString(),
        depositAmountY: new Decimal10(depositAmountY.toString()).div(tokenYUiMultiplier).toString(),
        unfilledAmountX: new Decimal10(unFilledAmountX.toString()).div(tokenXUiMultiplier).toString(),
        unfilledAmountY: new Decimal10(unFilledAmountY.toString()).div(tokenYUiMultiplier).toString(),
        swappedAmountX: new Decimal10(swappedAmountX.toString()).div(tokenXUiMultiplier).toString(),
        swappedAmountY: new Decimal10(swappedAmountY.toString()).div(tokenYUiMultiplier).toString(),
        isAskSide: loBin.isAsk(),
        filledAmountX: new Decimal10(filledAmountX.toString()).div(tokenXUiMultiplier).toString(),
        filledAmountY: new Decimal10(filledAmountY.toString()).div(tokenYUiMultiplier).toString(),
        feeAmountX: new Decimal10(feeAmountX.toString()).div(tokenXUiMultiplier).toString(),
        feeAmountY: new Decimal10(feeAmountY.toString()).div(tokenYUiMultiplier).toString(),
        status: limitOrderStatus
      });
    }
    const totalXAmount = totalFeeAmountX.add(totalSwappedAmountX).add(totalUnfilledAmountX);
    const totalYAmount = totalFeeAmountY.add(totalSwappedAmountY).add(totalUnfilledAmountY);
    const transferFeeExcludedWithdrawableAmountX = calculateTransferFeeExcludedAmount(
      totalXAmount,
      baseMint,
      clock.epoch.toNumber()
    ).amount;
    const transferFeeExcludedWithdrawableAmountY = calculateTransferFeeExcludedAmount(
      totalYAmount,
      quoteMint,
      clock.epoch.toNumber()
    ).amount;
    return {
      totalDepositAmountX: new Decimal10(totalAmountXDeposited.toString()).div(tokenXUiMultiplier).toString(),
      totalDepositAmountY: new Decimal10(totalAmountYDeposited.toString()).div(tokenYUiMultiplier).toString(),
      limitOrderBinData: parsedLimitOrderBinData,
      totalUnfilledAmountX: new Decimal10(totalUnfilledAmountX.toString()).div(tokenXUiMultiplier).toString(),
      totalUnfilledAmountY: new Decimal10(totalUnfilledAmountY.toString()).div(tokenYUiMultiplier).toString(),
      totalFilledAmountX: new Decimal10(totalFilledAmountX.toString()).div(tokenXUiMultiplier).toString(),
      totalFilledAmountY: new Decimal10(totalFilledAmountY.toString()).div(tokenYUiMultiplier).toString(),
      totalSwappedAmountX: new Decimal10(totalSwappedAmountX.toString()).div(tokenXUiMultiplier).toString(),
      totalSwappedAmountY: new Decimal10(totalSwappedAmountY.toString()).div(tokenYUiMultiplier).toString(),
      totalFeeAmountX: new Decimal10(totalFeeAmountX.toString()).div(tokenXUiMultiplier).toString(),
      totalFeeAmountY: new Decimal10(totalFeeAmountY.toString()).div(tokenYUiMultiplier).toString(),
      transferFeeExcludedWithdrawableAmountX: new Decimal10(
        transferFeeExcludedWithdrawableAmountX.toString()
      ).div(tokenXUiMultiplier).toString(),
      transferFeeExcludedWithdrawableAmountY: new Decimal10(
        transferFeeExcludedWithdrawableAmountY.toString()
      ).div(tokenYUiMultiplier).toString()
    };
  }
};
function getUpdatedLimitOrderAmount(limitOrderStatus, limitOrderData, bin, collectFeeMode) {
  let fulFilledAmount = new BN23(0);
  let unFilledAmount = new BN23(0);
  switch (limitOrderStatus) {
    case 0 /* NotFilled */:
      unFilledAmount = limitOrderData.amount();
      break;
    case 1 /* PartialFilled */:
      unFilledAmount = limitOrderData.amount().mul(bin.processedOrderRemainingAmount).add(bin.totalProcessingOrderAmount.sub(new BN23(1))).div(bin.totalProcessingOrderAmount);
      fulFilledAmount = limitOrderData.amount().sub(unFilledAmount);
      break;
    case 2 /* Fulfilled */:
      fulFilledAmount = limitOrderData.amount();
      break;
  }
  const swappedAmount = getAmountIn(
    fulFilledAmount,
    bin.price,
    !limitOrderData.isAsk(),
    1 /* Down */
  );
  const { feeX, feeY } = calculateLimitOrderFee(
    fulFilledAmount,
    limitOrderData.isAsk(),
    collectFeeMode,
    bin
  );
  return {
    fulFilledAmount,
    unFilledAmount,
    swappedAmount,
    feeXAmount: feeX,
    feeYAmount: feeY
  };
}
function calculateLimitOrderFee(fulfilledAmount, isAskSide, collectFeeMode, bin) {
  if (fulfilledAmount.isZero() || bin.fulfilledOrderAmountX.isZero() && isAskSide || bin.fulfilledOrderAmountY.isZero() && !isAskSide) {
    return {
      feeX: new BN23(0),
      feeY: new BN23(0)
    };
  }
  let limitOrderFee = new BN23(0);
  if (isAskSide) {
    limitOrderFee = bin.limitOrderFeeAskSide.mul(fulfilledAmount).div(bin.fulfilledOrderAmountX);
  } else {
    limitOrderFee = bin.limitOrderFeeBidSide.mul(fulfilledAmount).div(bin.fulfilledOrderAmountY);
  }
  switch (collectFeeMode) {
    case 0 /* InputOnly */:
      if (isAskSide) {
        return {
          feeX: new BN23(0),
          feeY: limitOrderFee
        };
      } else {
        return {
          feeX: limitOrderFee,
          feeY: new BN23(0)
        };
      }
    case 1 /* OnlyY */:
      return {
        feeX: new BN23(0),
        feeY: limitOrderFee
      };
  }
}
function getLimitOrderStatus(limitOrderBinData, bin) {
  if (limitOrderBinData.age() == bin.orderAge) {
    return 0 /* NotFilled */;
  } else if (limitOrderBinData.age() + 1 == bin.orderAge) {
    if (bin.openOrderAmount.isZero() && bin.processedOrderRemainingAmount.isZero()) {
      return 2 /* Fulfilled */;
    } else {
      return 1 /* PartialFilled */;
    }
  } else if (limitOrderBinData.age() + 2 <= bin.orderAge) {
    return 2 /* Fulfilled */;
  } else {
    throw new Error("Fail to get limit order status");
  }
}
function wrapLimitOrder(program, key, account) {
  const disc = account.data.subarray(0, 8);
  if (disc.equals(Buffer.from(getAccountDiscriminator("limitOrder")))) {
    const state = decodeAccount(
      program,
      "limitOrder",
      account.data
    );
    const limitOrderBinData = decodeLimitOrderBinData(
      state,
      program,
      account.data.subarray(8 + LIMIT_ORDER_MIN_SIZE)
    ).map((binData) => new LimitOrderBinDataWrapper(binData));
    return new LimitOrderV1Wrapper(key, state, limitOrderBinData);
  } else {
    throw new Error("Unknown position account");
  }
}

// src/dlmm/helpers/limitOrders/index.ts
function decodeLimitOrderBinData(limitOrder, program, bytes) {
  const limitOrderBinData = [];
  for (let i = 0; i < limitOrder.binCount; i++) {
    const offset = i * LIMIT_ORDER_BIN_DATA_SIZE;
    const data = bytes.subarray(offset, offset + LIMIT_ORDER_BIN_DATA_SIZE);
    const decodedLimitOrderBinData = program.coder.types.decode(
      // TODO: Find a type safe way
      "limitOrderBinData",
      data
    );
    limitOrderBinData.push(decodedLimitOrderBinData);
  }
  return limitOrderBinData;
}

// src/dlmm/index.ts
var DLMM = class {
  constructor(pubkey, program, lbPair, binArrayBitmapExtension, tokenX, tokenY, rewards, clock, opt) {
    this.pubkey = pubkey;
    this.program = program;
    this.lbPair = lbPair;
    this.binArrayBitmapExtension = binArrayBitmapExtension;
    this.tokenX = tokenX;
    this.tokenY = tokenY;
    this.rewards = rewards;
    this.clock = clock;
    this.opt = opt;
  }
  /** Static public method */
  /**
   * The function `getLbPairs` retrieves a list of LB pair accounts using a connection and optional
   * parameters.
   * @param {Connection} connection - The `connection` parameter is an instance of the `Connection`
   * class, which represents the connection to the Solana blockchain network.
   * @param {Opt} [opt] - The `opt` parameter is an optional object that contains additional options
   * for the function. It can have the following properties:
   * @returns The function `getLbPairs` returns a Promise that resolves to an array of
   * `LbPairAccount` objects.
   */
  static async getLbPairs(connection, opt) {
    const program = createProgram(connection, opt);
    return program.account.lbPair.all();
  }
  /**
   * Retrieves the public key of a LB pair if it exists. This function expect the RPC have getProgramAccounts RPC method enabled.
   * @param connection The connection to the Solana cluster.
   * @param tokenX The mint address of token X.
   * @param tokenY The mint address of token Y.
   * @param binStep The bin step of the LB pair.
   * @param baseFactor The base factor of the LB pair.
   * @param baseFeePowerFactor The base fee power factor of the LB pair. It allow small bin step to have bigger fee rate.
   * @param opt Optional parameters.
   * @returns The public key of the LB pair if it exists, or null.
   */
  static async getPairPubkeyIfExists(connection, tokenX, tokenY, binStep, baseFactor, baseFeePowerFactor, concreteFunctionType, collectFeeMode, opt) {
    const program = createProgram(connection, opt);
    const [lbPair2Key] = deriveLbPair2(
      tokenX,
      tokenY,
      binStep,
      baseFactor,
      program.programId
    );
    const account2 = await program.account.lbPair.fetchNullable(lbPair2Key);
    if (account2 && account2.parameters.baseFeePowerFactor == baseFeePowerFactor.toNumber()) {
      return lbPair2Key;
    }
    const [lbPairKey] = deriveLbPair(
      tokenX,
      tokenY,
      binStep,
      program.programId
    );
    const account = await program.account.lbPair.fetchNullable(lbPairKey);
    if (account && account.parameters.baseFactor === baseFactor.toNumber() && account.parameters.baseFeePowerFactor === baseFeePowerFactor.toNumber()) {
      return lbPairKey;
    }
    let presetParametersWithIndex = await program.account.presetParameter2.all([
      presetParameter2BinStepFilter(binStep),
      presetParameter2BaseFactorFilter(baseFactor),
      presetParameter2BaseFeePowerFactor(baseFeePowerFactor)
    ]);
    presetParametersWithIndex = presetParametersWithIndex.filter((p) => {
      return p.account.concreteFunctionType == (concreteFunctionType ?? 1 /* LiquidityMining */) && p.account.collectFeeMode == (collectFeeMode ?? 0 /* InputOnly */);
    });
    if (presetParametersWithIndex.length > 0) {
      const possibleLbPairKeys = presetParametersWithIndex.map((account3) => {
        return deriveLbPairWithPresetParamWithIndexKey(
          account3.publicKey,
          tokenX,
          tokenY,
          program.programId
        )[0];
      });
      const accounts = await chunkedGetMultipleAccountInfos(
        program.provider.connection,
        possibleLbPairKeys
      );
      for (let i = 0; i < possibleLbPairKeys.length; i++) {
        const pairKey = possibleLbPairKeys[i];
        const account3 = accounts[i];
        if (account3) {
          return pairKey;
        }
      }
    }
    return null;
  }
  static async getCustomizablePermissionlessLbPairIfExists(connection, tokenX, tokenY, opt) {
    const program = createProgram(connection, opt);
    try {
      const [lpPair] = deriveCustomizablePermissionlessLbPair(
        tokenX,
        tokenY,
        program.programId
      );
      const account = await program.account.lbPair.fetchNullable(lpPair);
      if (account)
        return lpPair;
      return null;
    } catch (error) {
      return null;
    }
  }
  /**
   * The `create` function is a static method that creates a new instance of the `DLMM` class
   * @param {Connection} connection - The `connection` parameter is an instance of the `Connection`
   * class, which represents the connection to the Solana blockchain network.
   * @param {PublicKey} dlmm - The PublicKey of LB Pair.
   * @param {Opt} [opt] - The `opt` parameter is an optional object that can contain additional options
   * for the `create` function. It has the following properties:
   * @returns The `create` function returns a `Promise` that resolves to a `DLMM` object.
   */
  static async create(connection, dlmm, opt) {
    const program = createProgram(connection, opt);
    const binArrayBitMapExtensionPubkey = deriveBinArrayBitmapExtension(
      dlmm,
      program.programId
    )[0];
    let accountsToFetch = [
      dlmm,
      binArrayBitMapExtensionPubkey,
      SYSVAR_CLOCK_PUBKEY2
    ];
    const accountsInfo = await chunkedGetMultipleAccountInfos(
      connection,
      accountsToFetch
    );
    const lbPairAccountInfoBuffer = accountsInfo[0]?.data;
    if (!lbPairAccountInfoBuffer)
      throw new Error(`LB Pair account ${dlmm.toBase58()} not found`);
    const lbPairAccInfo = decodeAccount(
      program,
      "lbPair",
      lbPairAccountInfoBuffer
    );
    const binArrayBitMapAccountInfoBuffer = accountsInfo[1]?.data;
    let binArrayBitMapExtensionAccInfo = null;
    if (binArrayBitMapAccountInfoBuffer) {
      binArrayBitMapExtensionAccInfo = decodeAccount(
        program,
        "binArrayBitmapExtension",
        binArrayBitMapAccountInfoBuffer
      );
    }
    const clockAccountInfoBuffer = accountsInfo[2]?.data;
    if (!clockAccountInfoBuffer)
      throw new Error(`Clock account not found`);
    const clock = ClockLayout.decode(clockAccountInfoBuffer);
    accountsToFetch = [
      lbPairAccInfo.reserveX,
      lbPairAccInfo.reserveY,
      lbPairAccInfo.tokenXMint,
      lbPairAccInfo.tokenYMint,
      lbPairAccInfo.rewardInfos[0].vault,
      lbPairAccInfo.rewardInfos[1].vault,
      lbPairAccInfo.rewardInfos[0].mint,
      lbPairAccInfo.rewardInfos[1].mint
    ];
    const [
      reserveXAccount,
      reserveYAccount,
      tokenXMintAccount,
      tokenYMintAccount,
      reward0VaultAccount,
      reward1VaultAccount,
      reward0MintAccount,
      reward1MintAccount
    ] = await chunkedGetMultipleAccountInfos(
      program.provider.connection,
      accountsToFetch
    );
    let binArrayBitmapExtension;
    if (binArrayBitMapExtensionAccInfo) {
      binArrayBitmapExtension = {
        account: binArrayBitMapExtensionAccInfo,
        publicKey: binArrayBitMapExtensionPubkey
      };
    }
    const reserveXBalance = AccountLayout.decode(reserveXAccount.data);
    const reserveYBalance = AccountLayout.decode(reserveYAccount.data);
    const mintX = unpackMint2(
      lbPairAccInfo.tokenXMint,
      tokenXMintAccount,
      tokenXMintAccount.owner
    );
    const mintY = unpackMint2(
      lbPairAccInfo.tokenYMint,
      tokenYMintAccount,
      tokenYMintAccount.owner
    );
    const [
      tokenXTransferHook,
      tokenYTransferHook,
      reward0TransferHook,
      reward1TransferHook
    ] = await Promise.all([
      getExtraAccountMetasForTransferHook(
        connection,
        lbPairAccInfo.tokenXMint,
        tokenXMintAccount
      ),
      getExtraAccountMetasForTransferHook(
        connection,
        lbPairAccInfo.tokenYMint,
        tokenYMintAccount
      ),
      reward0MintAccount ? getExtraAccountMetasForTransferHook(
        connection,
        lbPairAccInfo.rewardInfos[0].mint,
        reward0MintAccount
      ) : [],
      reward1MintAccount ? getExtraAccountMetasForTransferHook(
        connection,
        lbPairAccInfo.rewardInfos[1].mint,
        reward1MintAccount
      ) : []
    ]);
    const tokenX = {
      publicKey: lbPairAccInfo.tokenXMint,
      reserve: lbPairAccInfo.reserveX,
      amount: reserveXBalance.amount,
      mint: mintX,
      owner: tokenXMintAccount.owner,
      transferHookAccountMetas: tokenXTransferHook
    };
    const tokenY = {
      publicKey: lbPairAccInfo.tokenYMint,
      reserve: lbPairAccInfo.reserveY,
      amount: reserveYBalance.amount,
      mint: mintY,
      owner: tokenYMintAccount.owner,
      transferHookAccountMetas: tokenYTransferHook
    };
    const reward0 = !lbPairAccInfo.rewardInfos[0].mint.equals(
      PublicKey10.default
    ) ? {
      publicKey: lbPairAccInfo.rewardInfos[0].mint,
      reserve: lbPairAccInfo.rewardInfos[0].vault,
      amount: AccountLayout.decode(reward0VaultAccount.data).amount,
      mint: unpackMint2(
        lbPairAccInfo.rewardInfos[0].mint,
        reward0MintAccount,
        reward0MintAccount.owner
      ),
      owner: reward0MintAccount.owner,
      transferHookAccountMetas: reward0TransferHook
    } : null;
    const reward1 = !lbPairAccInfo.rewardInfos[1].mint.equals(
      PublicKey10.default
    ) ? {
      publicKey: lbPairAccInfo.rewardInfos[1].mint,
      reserve: lbPairAccInfo.rewardInfos[1].vault,
      amount: AccountLayout.decode(reward1VaultAccount.data).amount,
      mint: unpackMint2(
        lbPairAccInfo.rewardInfos[1].mint,
        reward1MintAccount,
        reward1MintAccount.owner
      ),
      owner: reward1MintAccount.owner,
      transferHookAccountMetas: reward1TransferHook
    } : null;
    return new DLMM(
      dlmm,
      program,
      lbPairAccInfo,
      binArrayBitmapExtension,
      tokenX,
      tokenY,
      [reward0, reward1],
      clock,
      opt
    );
  }
  /**
   * Similar to `create` function, but it accept multiple lbPairs to be initialized.
   * @param {Connection} connection - The `connection` parameter is an instance of the `Connection`
   * class, which represents the connection to the Solana blockchain network.
   * @param dlmmList - An Array of PublicKey of LB Pairs.
   * @param {Opt} [opt] - An optional parameter of type `Opt`.
   * @returns The function `createMultiple` returns a Promise that resolves to an array of `DLMM`
   * objects.
   */
  static async createMultiple(connection, dlmmList, opt) {
    const program = createProgram(connection, opt);
    const binArrayBitMapExtensions = dlmmList.map(
      (lbPair) => deriveBinArrayBitmapExtension(lbPair, program.programId)[0]
    );
    const accountsToFetch = [
      ...dlmmList,
      ...binArrayBitMapExtensions,
      SYSVAR_CLOCK_PUBKEY2
    ];
    let accountsInfo = await chunkedGetMultipleAccountInfos(
      connection,
      accountsToFetch
    );
    const clockAccount = accountsInfo.pop();
    const clockAccountInfoBuffer = clockAccount?.data;
    if (!clockAccountInfoBuffer)
      throw new Error(`Clock account not found`);
    const clock = ClockLayout.decode(clockAccountInfoBuffer);
    const lbPairArraysMap = /* @__PURE__ */ new Map();
    for (let i = 0; i < dlmmList.length; i++) {
      const lbPairPubKey = dlmmList[i];
      const lbPairAccountInfoBuffer = accountsInfo[i]?.data;
      if (!lbPairAccountInfoBuffer)
        throw new Error(`LB Pair account ${lbPairPubKey.toBase58()} not found`);
      const lbPairAccInfo = decodeAccount(
        program,
        "lbPair",
        lbPairAccountInfoBuffer
      );
      lbPairArraysMap.set(lbPairPubKey.toBase58(), lbPairAccInfo);
    }
    const binArrayBitMapExtensionsMap = /* @__PURE__ */ new Map();
    for (let i = dlmmList.length; i < accountsInfo.length; i++) {
      const index = i - dlmmList.length;
      const lbPairPubkey = dlmmList[index];
      const binArrayBitMapAccountInfoBuffer = accountsInfo[i]?.data;
      if (binArrayBitMapAccountInfoBuffer) {
        const binArrayBitMapExtensionAccInfo = decodeAccount(
          program,
          "binArrayBitmapExtension",
          binArrayBitMapAccountInfoBuffer
        );
        binArrayBitMapExtensionsMap.set(
          lbPairPubkey.toBase58(),
          binArrayBitMapExtensionAccInfo
        );
      }
    }
    const reservePublicKeys = Array.from(lbPairArraysMap.values()).map(({ reserveX, reserveY }) => [reserveX, reserveY]).flat();
    const tokenMintPublicKeys = Array.from(lbPairArraysMap.values()).map(({ tokenXMint, tokenYMint }) => [tokenXMint, tokenYMint]).flat();
    const rewardVaultPublicKeys = Array.from(lbPairArraysMap.values()).map(({ rewardInfos }) => rewardInfos.map(({ vault }) => vault)).flat();
    const rewardMintPublicKeys = Array.from(lbPairArraysMap.values()).map(({ rewardInfos }) => rewardInfos.map(({ mint }) => mint)).flat();
    accountsInfo = await chunkedGetMultipleAccountInfos(
      program.provider.connection,
      [
        ...reservePublicKeys,
        ...tokenMintPublicKeys,
        ...rewardVaultPublicKeys,
        ...rewardMintPublicKeys
      ]
    );
    const offsetToTokenMint = reservePublicKeys.length;
    const offsetToRewardMint = reservePublicKeys.length + tokenMintPublicKeys.length + rewardVaultPublicKeys.length;
    const tokenMintAccounts = accountsInfo.slice(
      offsetToTokenMint,
      offsetToTokenMint + tokenMintPublicKeys.length
    );
    const rewardMintAccounts = accountsInfo.slice(
      offsetToRewardMint,
      offsetToRewardMint + rewardMintPublicKeys.length
    );
    const tokenMintsWithAccount = tokenMintPublicKeys.map((key, idx) => {
      return {
        mintAddress: key,
        mintAccountInfo: tokenMintAccounts[idx]
      };
    }).filter(({ mintAddress }) => mintAddress !== PublicKey10.default);
    const rewardMintsWithAccount = rewardMintPublicKeys.map((key, idx) => {
      return {
        mintAddress: key,
        mintAccountInfo: rewardMintAccounts[idx]
      };
    }).filter(({ mintAddress }) => mintAddress !== PublicKey10.default);
    const uniqueMintWithAccounts = Array.from(
      new Set(tokenMintsWithAccount.concat(rewardMintsWithAccount))
    );
    const mintHookAccountsMap = await getMultipleMintsExtraAccountMetasForTransferHook(
      connection,
      uniqueMintWithAccounts
    );
    const lbClmmImpl = dlmmList.map((lbPair, index) => {
      const lbPairState = lbPairArraysMap.get(lbPair.toBase58());
      if (!lbPairState)
        throw new Error(`LB Pair ${lbPair.toBase58()} state not found`);
      const binArrayBitmapExtensionState = binArrayBitMapExtensionsMap.get(
        lbPair.toBase58()
      );
      const binArrayBitmapExtensionPubkey = binArrayBitMapExtensions[index];
      let binArrayBitmapExtension = null;
      if (binArrayBitmapExtensionState) {
        binArrayBitmapExtension = {
          account: binArrayBitmapExtensionState,
          publicKey: binArrayBitmapExtensionPubkey
        };
      }
      const reserveXAccountInfo = accountsInfo[index * 2];
      const reserveYAccountInfo = accountsInfo[index * 2 + 1];
      let offsetToTokenMint2 = reservePublicKeys.length;
      const tokenXMintAccountInfo = accountsInfo[offsetToTokenMint2 + index * 2];
      const tokenYMintAccountInfo = accountsInfo[offsetToTokenMint2 + index * 2 + 1];
      const offsetToRewardVaultAccountInfos = offsetToTokenMint2 + tokenMintPublicKeys.length;
      const reward0VaultAccountInfo = accountsInfo[offsetToRewardVaultAccountInfos + index * 2];
      const reward1VaultAccountInfo = accountsInfo[offsetToRewardVaultAccountInfos + index * 2 + 1];
      const offsetToRewardMintAccountInfos = offsetToRewardVaultAccountInfos + rewardVaultPublicKeys.length;
      const reward0MintAccountInfo = accountsInfo[offsetToRewardMintAccountInfos + index * 2];
      const reward1MintAccountInfo = accountsInfo[offsetToRewardMintAccountInfos + index * 2 + 1];
      if (!reserveXAccountInfo || !reserveYAccountInfo)
        throw new Error(
          `Reserve account for LB Pair ${lbPair.toBase58()} not found`
        );
      const reserveXBalance = AccountLayout.decode(reserveXAccountInfo.data);
      const reserveYBalance = AccountLayout.decode(reserveYAccountInfo.data);
      const mintX = unpackMint2(
        lbPairState.tokenXMint,
        tokenXMintAccountInfo,
        tokenXMintAccountInfo.owner
      );
      const mintY = unpackMint2(
        lbPairState.tokenYMint,
        tokenYMintAccountInfo,
        tokenYMintAccountInfo.owner
      );
      const tokenX = {
        publicKey: lbPairState.tokenXMint,
        reserve: lbPairState.reserveX,
        mint: mintX,
        amount: reserveXBalance.amount,
        owner: tokenXMintAccountInfo.owner,
        transferHookAccountMetas: mintHookAccountsMap.get(lbPairState.tokenXMint.toBase58()) ?? []
      };
      const tokenY = {
        publicKey: lbPairState.tokenYMint,
        reserve: lbPairState.reserveY,
        amount: reserveYBalance.amount,
        mint: mintY,
        owner: tokenYMintAccountInfo.owner,
        transferHookAccountMetas: mintHookAccountsMap.get(lbPairState.tokenYMint.toBase58()) ?? []
      };
      const reward0 = !lbPairState.rewardInfos[0].mint.equals(
        PublicKey10.default
      ) ? {
        publicKey: lbPairState.rewardInfos[0].mint,
        reserve: lbPairState.rewardInfos[0].vault,
        amount: AccountLayout.decode(reward0VaultAccountInfo.data).amount,
        mint: unpackMint2(
          lbPairState.rewardInfos[0].mint,
          reward0MintAccountInfo,
          reward0MintAccountInfo.owner
        ),
        owner: reward0MintAccountInfo.owner,
        transferHookAccountMetas: mintHookAccountsMap.get(
          lbPairState.rewardInfos[0].mint.toBase58()
        ) ?? []
      } : null;
      const reward1 = !lbPairState.rewardInfos[1].mint.equals(
        PublicKey10.default
      ) ? {
        publicKey: lbPairState.rewardInfos[1].mint,
        reserve: lbPairState.rewardInfos[1].vault,
        amount: AccountLayout.decode(reward1VaultAccountInfo.data).amount,
        mint: unpackMint2(
          lbPairState.rewardInfos[1].mint,
          reward1MintAccountInfo,
          reward1MintAccountInfo.owner
        ),
        owner: reward1MintAccountInfo.owner,
        transferHookAccountMetas: mintHookAccountsMap.get(
          lbPairState.rewardInfos[1].mint.toBase58()
        ) ?? []
      } : null;
      return new DLMM(
        lbPair,
        program,
        lbPairState,
        binArrayBitmapExtension,
        tokenX,
        tokenY,
        [reward0, reward1],
        clock,
        opt
      );
    });
    return lbClmmImpl;
  }
  /**
   * The `getAllPresetParameters` function retrieves all preset parameter accounts
   * for the given DLMM program.
   *
   * @param {Connection} connection - The connection to the Solana cluster.
   * @param {Opt} [opt] - The optional parameters for the function.
   *
   * @returns A promise that resolves to an object containing the preset parameter
   * accounts, with the following properties:
   * - `presetParameter`: The preset parameter accounts for the original `PresetParameter` struct.
   * - `presetParameter2`: The preset parameter accounts for the `PresetParameter2` struct.
   */
  static async getAllPresetParameters(connection, opt) {
    const program = createProgram(connection, opt);
    const [presetParameter, presetParameter2] = await Promise.all([
      program.account.presetParameter.all(),
      program.account.presetParameter2.all()
    ]);
    return {
      presetParameter,
      presetParameter2
    };
  }
  /**
   * The function `getAllLbPairPositionsByUser` retrieves all liquidity pool pair positions for a given
   * user.
   * @param {Connection} connection - The `connection` parameter is an instance of the `Connection`
   * class, which represents the connection to the Solana blockchain.
   * @param {PublicKey} userPubKey - The user's wallet public key.
   * @param {Opt} [opt] - An optional object that contains additional options for the function.
   * @param {GetPositionsOpt} [getPositionsOpt] - Optional settings for chunked position fetching
   * @returns The function `getAllLbPairPositionsByUser` returns a `Promise` that resolves to a `Map`
   * object. The `Map` object contains key-value pairs, where the key is a string representing the LB
   * Pair account, and the value is an object of PositionInfo
   */
  static async getAllLbPairPositionsByUser(connection, userPubKey, opt, getPositionsOpt) {
    const program = createProgram(connection, opt);
    const positionsV2 = await chunkedGetProgramAccounts(
      program.provider.connection,
      program.programId,
      [positionV2Filter(), positionOwnerFilter(userPubKey)],
      getPositionsOpt?.chunkSize,
      getPositionsOpt?.onChunkFetched,
      getPositionsOpt?.isParallelExecution
    );
    const positionWrappers = [
      ...positionsV2.map((p) => wrapPosition(program, p.pubkey, p.account))
    ];
    const binArrayPubkeySetV2 = /* @__PURE__ */ new Set();
    const lbPairSetV2 = /* @__PURE__ */ new Set();
    positionWrappers.forEach((p) => {
      const binArrayKeys = p.getBinArrayKeysCoverage(program.programId);
      binArrayKeys.forEach((binArrayKey) => {
        binArrayPubkeySetV2.add(binArrayKey.toBase58());
      });
      lbPairSetV2.add(p.lbPair().toBase58());
    });
    const binArrayPubkeyArrayV2 = Array.from(binArrayPubkeySetV2).map(
      (pubkey) => new PublicKey10(pubkey)
    );
    const lbPairKeys = Array.from(lbPairSetV2).map(
      (pubkey) => new PublicKey10(pubkey)
    );
    const [clockAccInfo, ...binArraysAccInfo] = await chunkedGetMultipleAccountInfos(connection, [
      SYSVAR_CLOCK_PUBKEY2,
      ...binArrayPubkeyArrayV2,
      ...lbPairKeys
    ]);
    const positionBinArraysMapV2 = /* @__PURE__ */ new Map();
    for (let i = 0; i < binArrayPubkeyArrayV2.length; i++) {
      const binArrayPubkey = binArrayPubkeyArrayV2[i];
      const binArrayAccInfoBufferV2 = binArraysAccInfo[i];
      if (binArrayAccInfoBufferV2) {
        const binArrayAccInfo = decodeAccount(
          program,
          "binArray",
          binArrayAccInfoBufferV2.data
        );
        positionBinArraysMapV2.set(binArrayPubkey.toBase58(), binArrayAccInfo);
      }
    }
    const lbPairMap = /* @__PURE__ */ new Map();
    for (let i = binArrayPubkeyArrayV2.length; i < binArraysAccInfo.length; i++) {
      const lbPairPubkey = lbPairKeys[i - binArrayPubkeyArrayV2.length];
      const lbPairAccInfoBufferV2 = binArraysAccInfo[i];
      if (!lbPairAccInfoBufferV2)
        throw new Error(`LB Pair account ${lbPairPubkey.toBase58()} not found`);
      const lbPairAccInfo = decodeAccount(
        program,
        "lbPair",
        lbPairAccInfoBufferV2.data
      );
      lbPairMap.set(lbPairPubkey.toBase58(), lbPairAccInfo);
    }
    const accountKeys = Array.from(lbPairMap.values()).map(({ reserveX, reserveY, tokenXMint, tokenYMint, rewardInfos }) => [
      reserveX,
      reserveY,
      tokenXMint,
      tokenYMint,
      rewardInfos[0].mint,
      rewardInfos[1].mint
    ]).flat();
    const accountInfos = await chunkedGetMultipleAccountInfos(
      program.provider.connection,
      accountKeys
    );
    const lbPairReserveMap = /* @__PURE__ */ new Map();
    const lbPairMintMap = /* @__PURE__ */ new Map();
    lbPairKeys.forEach((lbPair, idx) => {
      const index = idx * 6;
      const reserveXAccount = accountInfos[index];
      const reserveYAccount = accountInfos[index + 1];
      if (!reserveXAccount || !reserveYAccount)
        throw new Error(
          `Reserve account for LB Pair ${lbPair.toBase58()} not found`
        );
      const reserveAccX = AccountLayout.decode(reserveXAccount.data);
      const reserveAccY = AccountLayout.decode(reserveYAccount.data);
      lbPairReserveMap.set(lbPair.toBase58(), {
        reserveX: reserveAccX.amount,
        reserveY: reserveAccY.amount
      });
      const mintXAccount = accountInfos[index + 2];
      const mintYAccount = accountInfos[index + 3];
      if (!mintXAccount || !mintYAccount)
        throw new Error(
          `Mint account for LB Pair ${lbPair.toBase58()} not found`
        );
      const mintX = unpackMint2(
        reserveAccX.mint,
        mintXAccount,
        mintXAccount.owner
      );
      const mintY = unpackMint2(
        reserveAccY.mint,
        mintYAccount,
        mintYAccount.owner
      );
      const rewardMint0Account = accountInfos[index + 4];
      const rewardMint1Account = accountInfos[index + 5];
      const lbPairState = lbPairMap.get(lbPair.toBase58());
      let rewardMint0 = null;
      let rewardMint1 = null;
      if (!lbPairState.rewardInfos[0].mint.equals(PublicKey10.default)) {
        rewardMint0 = unpackMint2(
          lbPairState.rewardInfos[0].mint,
          rewardMint0Account,
          rewardMint0Account.owner
        );
      }
      if (!lbPairState.rewardInfos[1].mint.equals(PublicKey10.default)) {
        rewardMint1 = unpackMint2(
          lbPairState.rewardInfos[1].mint,
          rewardMint1Account,
          rewardMint1Account.owner
        );
      }
      lbPairMintMap.set(lbPair.toBase58(), {
        mintX,
        mintY,
        rewardMint0,
        rewardMint1
      });
    });
    const clock = ClockLayout.decode(clockAccInfo.data);
    const positionsMap = /* @__PURE__ */ new Map();
    for (const position of positionWrappers) {
      const lbPair = position.lbPair();
      const positionPubkey = position.address();
      const version = position.version();
      const lbPairAcc = lbPairMap.get(lbPair.toBase58());
      const { mintX, mintY, rewardMint0, rewardMint1 } = lbPairMintMap.get(
        lbPair.toBase58()
      );
      const reserveXBalance = lbPairReserveMap.get(lbPair.toBase58())?.reserveX ?? BigInt(0);
      const reserveYBalance = lbPairReserveMap.get(lbPair.toBase58())?.reserveY ?? BigInt(0);
      const { tokenXProgram, tokenYProgram } = getTokenProgramId(lbPairAcc);
      const tokenX = {
        publicKey: lbPairAcc.tokenXMint,
        reserve: lbPairAcc.reserveX,
        amount: reserveXBalance,
        mint: mintX,
        owner: tokenXProgram,
        transferHookAccountMetas: []
        // No need, the TokenReserve created just for processing position info, doesn't require any transaction
      };
      const tokenY = {
        publicKey: lbPairAcc.tokenYMint,
        reserve: lbPairAcc.reserveY,
        amount: reserveYBalance,
        mint: mintY,
        owner: tokenYProgram,
        transferHookAccountMetas: []
        // No need, the TokenReserve created just for processing position info, doesn't require any transaction
      };
      const positionData = await DLMM.processPosition(
        program,
        lbPairAcc,
        clock,
        position,
        mintX,
        mintY,
        rewardMint0,
        rewardMint1,
        positionBinArraysMapV2
      );
      if (positionData) {
        positionsMap.set(lbPair.toBase58(), {
          publicKey: lbPair,
          lbPair: lbPairAcc,
          tokenX,
          tokenY,
          lbPairPositionsData: [
            ...positionsMap.get(lbPair.toBase58())?.lbPairPositionsData ?? [],
            {
              publicKey: positionPubkey,
              positionData,
              version
            }
          ]
        });
      }
    }
    return positionsMap;
  }
  /**
   * The function `getPositionsByUserAndTokenAddress` retrieves all of a user's positions across every
   * DLMM pool that includes the given token mint as either the X or Y token.
   * @param {Connection} connection - The `connection` parameter is an instance of the `Connection`
   * class, which represents the connection to the Solana blockchain.
   * @param {PublicKey} userPubKey - The user's wallet public key.
   * @param {PublicKey} tokenMint - The token mint used to filter pools. Only positions in pools whose
   * `tokenXMint` or `tokenYMint` matches this mint are returned.
   * @param {Opt} [opt] - An optional object that contains additional options for the function.
   * @param {GetPositionsOpt} [getPositionsOpt] - Optional settings for chunked position fetching
   * @returns The function `getPositionsByUserAndTokenAddress` returns a `Promise` that resolves to a
   * `Map` object. The `Map` object contains key-value pairs, where the key is a string representing the
   * LB Pair account, and the value is an object of PositionInfo. Only pools containing `tokenMint` are
   * included.
   */
  static async getPositionsByUserAndTokenAddress(connection, userPubKey, tokenMint, opt, getPositionsOpt) {
    const allPositions = await DLMM.getAllLbPairPositionsByUser(
      connection,
      userPubKey,
      opt,
      getPositionsOpt
    );
    const targetMint = tokenMint.toBase58();
    const filteredPositions = /* @__PURE__ */ new Map();
    for (const [lbPairKey, positionInfo] of allPositions) {
      const tokenXMint = positionInfo.lbPair.tokenXMint.toBase58();
      const tokenYMint = positionInfo.lbPair.tokenYMint.toBase58();
      if (tokenXMint === targetMint || tokenYMint === targetMint) {
        filteredPositions.set(lbPairKey, positionInfo);
      }
    }
    return filteredPositions;
  }
  /**
   * The function `getLimitOrdersByUserAndTokenAddress` retrieves all of a user's limit orders across
   * every DLMM pool that includes the given token mint as either the X or Y token.
   * @param {Connection} connection - The `connection` parameter is an instance of the `Connection`
   * class, which represents the connection to the Solana blockchain.
   * @param {PublicKey} userPubKey - The user's wallet public key.
   * @param {PublicKey} tokenMint - The token mint used to filter pools. Only limit orders in pools
   * whose `tokenXMint` or `tokenYMint` matches this mint are returned.
   * @param {Opt} [opt] - An optional object that contains additional options for the function.
   * @returns The function `getLimitOrdersByUserAndTokenAddress` returns a `Promise` that resolves to a
   * `Map` object keyed by LB Pair account (base58), where each value is a `LimitOrderInfo` containing
   * the LB pair state, token reserves, and the parsed limit orders for that pool.
   */
  static async getLimitOrdersByUserAndTokenAddress(connection, userPubKey, tokenMint, opt) {
    const program = createProgram(connection, opt);
    const limitOrderAccounts = await chunkedGetProgramAccounts(
      program.provider.connection,
      program.programId,
      [limitOrderFilter(), limitOrderOwnerFilter(userPubKey)]
    );
    const limitOrderWrappers = limitOrderAccounts.map(
      ({ pubkey, account }) => wrapLimitOrder(program, pubkey, account)
    );
    if (limitOrderWrappers.length === 0) {
      return /* @__PURE__ */ new Map();
    }
    const lbPairKeys = Array.from(
      new Set(limitOrderWrappers.map((lo) => lo.lbPair().toBase58()))
    ).map((key) => new PublicKey10(key));
    const lbPairAccInfos = await chunkedGetMultipleAccountInfos(
      connection,
      lbPairKeys
    );
    const lbPairMap = /* @__PURE__ */ new Map();
    lbPairKeys.forEach((lbPairPubkey, i) => {
      const accInfo = lbPairAccInfos[i];
      if (!accInfo) {
        throw new Error(`LB Pair account ${lbPairPubkey.toBase58()} not found`);
      }
      lbPairMap.set(
        lbPairPubkey.toBase58(),
        decodeAccount(program, "lbPair", accInfo.data)
      );
    });
    const targetMint = tokenMint.toBase58();
    const matchingLbPairKeys = lbPairKeys.filter((lbPairPubkey) => {
      const lbPairState = lbPairMap.get(lbPairPubkey.toBase58());
      return lbPairState.tokenXMint.toBase58() === targetMint || lbPairState.tokenYMint.toBase58() === targetMint;
    });
    if (matchingLbPairKeys.length === 0) {
      return /* @__PURE__ */ new Map();
    }
    const matchingLbPairSet = new Set(
      matchingLbPairKeys.map((key) => key.toBase58())
    );
    const matchingLimitOrders = limitOrderWrappers.filter(
      (lo) => matchingLbPairSet.has(lo.lbPair().toBase58())
    );
    const reserveAndMintKeys = matchingLbPairKeys.map((lbPairPubkey) => {
      const { reserveX, reserveY, tokenXMint, tokenYMint } = lbPairMap.get(
        lbPairPubkey.toBase58()
      );
      return [reserveX, reserveY, tokenXMint, tokenYMint];
    }).flat();
    const binArrayPubkeySet = /* @__PURE__ */ new Set();
    matchingLimitOrders.forEach((lo) => {
      lo.getBinArrayKeysCoverage(program.programId).forEach((key) => {
        binArrayPubkeySet.add(key.toBase58());
      });
    });
    const binArrayKeys = Array.from(binArrayPubkeySet).map(
      (key) => new PublicKey10(key)
    );
    const [clockAccInfo, ...rest] = await chunkedGetMultipleAccountInfos(
      connection,
      [SYSVAR_CLOCK_PUBKEY2, ...binArrayKeys, ...reserveAndMintKeys]
    );
    const binArraysAccInfo = rest.slice(0, binArrayKeys.length);
    const reserveAndMintAccInfo = rest.slice(binArrayKeys.length);
    const clock = ClockLayout.decode(clockAccInfo.data);
    const binArrayMap = /* @__PURE__ */ new Map();
    binArrayKeys.forEach((binArrayPubkey, i) => {
      const accInfo = binArraysAccInfo[i];
      if (accInfo) {
        binArrayMap.set(
          binArrayPubkey.toBase58(),
          decodeAccount(program, "binArray", accInfo.data)
        );
      }
    });
    const seenMints = /* @__PURE__ */ new Set();
    const mintsWithAccount = matchingLbPairKeys.flatMap((lbPairPubkey, idx) => {
      const { tokenXMint, tokenYMint } = lbPairMap.get(
        lbPairPubkey.toBase58()
      );
      const index = idx * 4;
      return [
        {
          mintAddress: tokenXMint,
          mintAccountInfo: reserveAndMintAccInfo[index + 2]
        },
        {
          mintAddress: tokenYMint,
          mintAccountInfo: reserveAndMintAccInfo[index + 3]
        }
      ];
    }).filter(({ mintAddress, mintAccountInfo }) => {
      if (!mintAccountInfo || seenMints.has(mintAddress.toBase58())) {
        return false;
      }
      seenMints.add(mintAddress.toBase58());
      return true;
    });
    const mintHookAccountsMap = await getMultipleMintsExtraAccountMetasForTransferHook(
      connection,
      mintsWithAccount
    );
    const lbPairTokenMap = /* @__PURE__ */ new Map();
    matchingLbPairKeys.forEach((lbPairPubkey, idx) => {
      const index = idx * 4;
      const reserveXAccount = reserveAndMintAccInfo[index];
      const reserveYAccount = reserveAndMintAccInfo[index + 1];
      const mintXAccount = reserveAndMintAccInfo[index + 2];
      const mintYAccount = reserveAndMintAccInfo[index + 3];
      if (!reserveXAccount || !reserveYAccount) {
        throw new Error(
          `Reserve account for LB Pair ${lbPairPubkey.toBase58()} not found`
        );
      }
      if (!mintXAccount || !mintYAccount) {
        throw new Error(
          `Mint account for LB Pair ${lbPairPubkey.toBase58()} not found`
        );
      }
      const lbPairState = lbPairMap.get(lbPairPubkey.toBase58());
      const reserveAccX = AccountLayout.decode(reserveXAccount.data);
      const reserveAccY = AccountLayout.decode(reserveYAccount.data);
      const mintX = unpackMint2(
        reserveAccX.mint,
        mintXAccount,
        mintXAccount.owner
      );
      const mintY = unpackMint2(
        reserveAccY.mint,
        mintYAccount,
        mintYAccount.owner
      );
      const { tokenXProgram, tokenYProgram } = getTokenProgramId(lbPairState);
      const tokenX = {
        publicKey: lbPairState.tokenXMint,
        reserve: lbPairState.reserveX,
        amount: reserveAccX.amount,
        mint: mintX,
        owner: tokenXProgram,
        transferHookAccountMetas: mintHookAccountsMap.get(lbPairState.tokenXMint.toBase58()) ?? []
      };
      const tokenY = {
        publicKey: lbPairState.tokenYMint,
        reserve: lbPairState.reserveY,
        amount: reserveAccY.amount,
        mint: mintY,
        owner: tokenYProgram,
        transferHookAccountMetas: mintHookAccountsMap.get(lbPairState.tokenYMint.toBase58()) ?? []
      };
      lbPairTokenMap.set(lbPairPubkey.toBase58(), {
        tokenX,
        tokenY,
        mintX,
        mintY
      });
    });
    const limitOrdersMap = /* @__PURE__ */ new Map();
    for (const lo of matchingLimitOrders) {
      const lbPairKey = lo.lbPair().toBase58();
      const lbPairState = lbPairMap.get(lbPairKey);
      const { tokenX, tokenY, mintX, mintY } = lbPairTokenMap.get(lbPairKey);
      const parsedLo = lo.parseInfo(
        program.programId,
        lbPairState,
        mintX,
        mintY,
        clock,
        binArrayMap
      );
      const entry = {
        publicKey: lo.address(),
        limitOrderData: parsedLo
      };
      const existing = limitOrdersMap.get(lbPairKey);
      if (existing) {
        existing.limitOrders.push(entry);
      } else {
        limitOrdersMap.set(lbPairKey, {
          publicKey: lo.lbPair(),
          lbPair: lbPairState,
          tokenX,
          tokenY,
          limitOrders: [entry]
        });
      }
    }
    return limitOrdersMap;
  }
  static getPricePerLamport(tokenXDecimal, tokenYDecimal, price) {
    return new Decimal11(price).mul(new Decimal11(10 ** (tokenYDecimal - tokenXDecimal))).toString();
  }
  static getBinIdFromPrice(price, binStep, min) {
    const binStepNum = new Decimal11(binStep).div(new Decimal11(BASIS_POINT_MAX));
    const binId = new Decimal11(price).log().dividedBy(new Decimal11(1).add(binStepNum).log());
    return (min ? binId.floor() : binId.ceil()).toNumber();
  }
  /**
   * The function `getLbPairLockInfo` retrieves all pair positions that has locked liquidity.
   * @param {number} [lockDurationOpt] - An optional value indicating the minimum position lock duration that the function should return.
   * Depending on the lbPair activationType, the param should be a number of seconds or a number of slots.
   * @param {GetPositionsOpt} [getPositionsOpt] - Optional settings for chunked position fetching
   * @returns The function `getLbPairLockInfo` returns a `Promise` that resolves to a `PairLockInfo`
   * object. The `PairLockInfo` object contains an array of `PositionLockInfo` objects.
   */
  async getLbPairLockInfo(lockDurationOpt, getPositionsOpt) {
    const lockDuration = lockDurationOpt | 0;
    const positionAccounts = await chunkedGetProgramAccounts(
      this.program.provider.connection,
      this.program.programId,
      [positionLbPairFilter(this.pubkey)],
      getPositionsOpt?.chunkSize,
      getPositionsOpt?.onChunkFetched,
      getPositionsOpt?.isParallelExecution
    );
    const lbPairPositions = positionAccounts.map((acc) => {
      return wrapPosition(this.program, acc.pubkey, acc.account);
    });
    const clockAccInfo = await this.program.provider.connection.getAccountInfo(
      SYSVAR_CLOCK_PUBKEY2
    );
    const clock = ClockLayout.decode(clockAccInfo.data);
    const currentPoint = this.lbPair.activationType == 0 /* Slot */ ? clock.slot : clock.unixTimestamp;
    const minLockReleasePoint = currentPoint.add(new BN24(lockDuration));
    const positionsWithLock = lbPairPositions.filter(
      (p) => p.lockReleasePoint().gt(minLockReleasePoint)
    );
    if (positionsWithLock.length == 0) {
      return {
        positions: []
      };
    }
    const binArrayPubkeySetV2 = /* @__PURE__ */ new Set();
    positionsWithLock.forEach((position) => {
      const binArrayKeys = position.getBinArrayKeysCoverage(
        this.program.programId
      );
      binArrayKeys.forEach((key) => {
        binArrayPubkeySetV2.add(key.toBase58());
      });
    });
    const binArrayPubkeyArrayV2 = Array.from(binArrayPubkeySetV2).map(
      (pubkey) => new PublicKey10(pubkey)
    );
    const binArraysAccInfo = await chunkedGetMultipleAccountInfos(
      this.program.provider.connection,
      binArrayPubkeyArrayV2
    );
    const positionBinArraysMapV2 = /* @__PURE__ */ new Map();
    for (let i = 0; i < binArraysAccInfo.length; i++) {
      const binArrayPubkey = binArrayPubkeyArrayV2[i];
      const binArrayAccBufferV2 = binArraysAccInfo[i];
      if (!binArrayAccBufferV2)
        throw new Error(
          `Bin Array account ${binArrayPubkey.toBase58()} not found`
        );
      const binArrayAccInfo = decodeAccount(
        this.program,
        "binArray",
        binArrayAccBufferV2.data
      );
      positionBinArraysMapV2.set(binArrayPubkey.toBase58(), binArrayAccInfo);
    }
    const positionsLockInfo = await Promise.all(
      positionsWithLock.map(async (position) => {
        const positionData = await DLMM.processPosition(
          this.program,
          this.lbPair,
          clock,
          position,
          this.tokenX.mint,
          this.tokenY.mint,
          this.rewards[0].mint,
          this.rewards[1].mint,
          positionBinArraysMapV2
        );
        return {
          positionAddress: position.address(),
          owner: position.owner(),
          lockReleasePoint: position.lockReleasePoint().toNumber(),
          tokenXAmount: positionData.totalXAmount,
          tokenYAmount: positionData.totalYAmount
        };
      })
    );
    return {
      positions: positionsLockInfo
    };
  }
  /** Public methods */
  /**
   * Create a new customizable permissionless pair. Support both token and token 2022.
   * @param connection A connection to the Solana cluster.
   * @param binStep The bin step for the pair.
   * @param tokenX The mint of the first token.
   * @param tokenY The mint of the second token.
   * @param activeId The ID of the initial active bin. Represent the starting price.
   * @param feeBps The fee rate for swaps in the pair, in basis points.
   * @param activationType The type of activation for the pair.
   * @param hasAlphaVault Whether the pair has an alpha vault.
   * @param creatorKey The public key of the creator of the pair.
   * @param activationPoint The timestamp at which the pair will be activated.
   * @param creatorPoolOnOffControl Whether the creator has control over enable or disable the pool.
   * @params concreteFunctionType The concrete function type of the pair, limit order or liquidity mining. Default to limit order if not provided.
   * @params collectFeeMode The collect fee mode of the pair, input only or only token Y. Default to input only if not provided.
   * @param opt An options object.
   * @returns A transaction that creates the pair.
   */
  static async createCustomizablePermissionlessLbPair2(connection, binStep, tokenX, tokenY, activeId, feeBps, activationType, hasAlphaVault, creatorKey, activationPoint, creatorPoolOnOffControl, concreteFunctionType, collectFeeMode, opt) {
    const program = createProgram(connection, opt);
    const [tokenBadgeX] = deriveTokenBadge(tokenX, program.programId);
    const [tokenBadgeY] = deriveTokenBadge(tokenY, program.programId);
    const [
      tokenXAccount,
      tokenYAccount,
      tokenBadgeXAccount,
      tokenBadgeYAccount
    ] = await connection.getMultipleAccountsInfo([
      tokenX,
      tokenY,
      tokenBadgeX,
      tokenBadgeY
    ]);
    const [lbPair] = deriveCustomizablePermissionlessLbPair(
      tokenX,
      tokenY,
      program.programId
    );
    const [reserveX] = deriveReserve(tokenX, lbPair, program.programId);
    const [reserveY] = deriveReserve(tokenY, lbPair, program.programId);
    const [oracle] = deriveOracle(lbPair, program.programId);
    const activeBinArrayIndex = binIdToBinArrayIndex(activeId);
    const binArrayBitmapExtension = isOverflowDefaultBinArrayBitmap(
      activeBinArrayIndex
    ) ? deriveBinArrayBitmapExtension(lbPair, program.programId)[0] : null;
    const [baseFactor, baseFeePowerFactor] = computeBaseFactorFromFeeBps(
      binStep,
      feeBps
    );
    const ixData = {
      activeId: activeId.toNumber(),
      binStep: binStep.toNumber(),
      baseFactor: baseFactor.toNumber(),
      concreteFunctionType: concreteFunctionType ? concreteFunctionType : 0 /* LimitOrder */,
      collectFeeMode: collectFeeMode ? collectFeeMode : 0 /* InputOnly */,
      activationType,
      activationPoint: activationPoint ? activationPoint : null,
      hasAlphaVault,
      creatorPoolOnOffControl: creatorPoolOnOffControl ? creatorPoolOnOffControl : false,
      baseFeePowerFactor: baseFeePowerFactor.toNumber(),
      padding: Array(60).fill(0)
    };
    const preInstructions = [];
    const userTokenX = getAssociatedTokenAddressSync2(
      tokenX,
      creatorKey,
      true,
      tokenXAccount.owner
    );
    const createUserTokenXIx = createAssociatedTokenAccountIdempotentInstruction2(
      creatorKey,
      userTokenX,
      creatorKey,
      tokenX,
      tokenXAccount.owner
    );
    preInstructions.push(createUserTokenXIx);
    const userTokenY = getAssociatedTokenAddressSync2(
      tokenY,
      creatorKey,
      true,
      tokenYAccount.owner
    );
    const createUserTokenYIx = createAssociatedTokenAccountIdempotentInstruction2(
      creatorKey,
      userTokenY,
      creatorKey,
      tokenY,
      tokenYAccount.owner
    );
    preInstructions.push(createUserTokenYIx);
    const postInstructions = [];
    if ((tokenX.equals(NATIVE_MINT2) || tokenY.equals(NATIVE_MINT2)) && !opt?.skipSolWrappingOperation) {
      const wrapAmount = BigInt(1);
      if (tokenX.equals(NATIVE_MINT2)) {
        const wrapSOLIxX = wrapSOLInstruction(
          creatorKey,
          userTokenX,
          wrapAmount
        );
        preInstructions.push(...wrapSOLIxX);
      }
      if (tokenY.equals(NATIVE_MINT2)) {
        const wrapSOLIxY = wrapSOLInstruction(
          creatorKey,
          userTokenY,
          wrapAmount
        );
        preInstructions.push(...wrapSOLIxY);
      }
      const unwrapSOLIx = await unwrapSOLInstruction(creatorKey);
      if (unwrapSOLIx) {
        postInstructions.push(unwrapSOLIx);
      }
    }
    return program.methods.initializeCustomizablePermissionlessLbPair2(ixData).accountsPartial({
      tokenBadgeX: tokenBadgeXAccount ? tokenBadgeX : program.programId,
      tokenBadgeY: tokenBadgeYAccount ? tokenBadgeY : program.programId,
      lbPair,
      reserveX,
      reserveY,
      binArrayBitmapExtension,
      tokenMintX: tokenX,
      tokenMintY: tokenY,
      oracle,
      systemProgram: SystemProgram2.programId,
      userTokenX,
      userTokenY,
      funder: creatorKey,
      tokenProgramX: tokenXAccount.owner,
      tokenProgramY: tokenYAccount.owner
    }).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
  }
  /**
   * Create a new customizable permissionless pair. Support only token program.
   * @param connection A connection to the Solana cluster.
   * @param binStep The bin step for the pair.
   * @param tokenX The mint of the first token.
   * @param tokenY The mint of the second token.
   * @param activeId The ID of the initial active bin. Represent the starting price.
   * @param feeBps The fee rate for swaps in the pair, in basis points.
   * @param activationType The type of activation for the pair.
   * @param hasAlphaVault Whether the pair has an alpha vault.
   * @param creatorKey The public key of the creator of the pair.
   * @param activationPoint The timestamp at which the pair will be activated.
   * @param creatorPoolOnOffControl Whether the creator has control over enable or disable the pool.
   * @params concreteFunctionType The concrete function type of the pair, limit order or liquidity mining. Default to limit order if not provided.
   * @params collectFeeMode The collect fee
   * @param opt An options object.
   * @returns A transaction that creates the pair.
   */
  static async createCustomizablePermissionlessLbPair(connection, binStep, tokenX, tokenY, activeId, feeBps, activationType, hasAlphaVault, creatorKey, activationPoint, creatorPoolOnOffControl, concreteFunctionType, collectFeeMode, opt) {
    const program = createProgram(connection, opt);
    const [lbPair] = deriveCustomizablePermissionlessLbPair(
      tokenX,
      tokenY,
      program.programId
    );
    const [tokenXAccount, tokenYAccount] = await connection.getMultipleAccountsInfo([tokenX, tokenY]);
    const [reserveX] = deriveReserve(tokenX, lbPair, program.programId);
    const [reserveY] = deriveReserve(tokenY, lbPair, program.programId);
    const [oracle] = deriveOracle(lbPair, program.programId);
    const activeBinArrayIndex = binIdToBinArrayIndex(activeId);
    const binArrayBitmapExtension = isOverflowDefaultBinArrayBitmap(
      activeBinArrayIndex
    ) ? deriveBinArrayBitmapExtension(lbPair, program.programId)[0] : null;
    const [baseFactor, baseFeePowerFactor] = computeBaseFactorFromFeeBps(
      binStep,
      feeBps
    );
    if (!baseFeePowerFactor.isZero()) {
      throw "base factor for the give fee bps overflow u16";
    }
    const ixData = {
      activeId: activeId.toNumber(),
      binStep: binStep.toNumber(),
      baseFactor: baseFactor.toNumber(),
      concreteFunctionType: concreteFunctionType ? concreteFunctionType : 0 /* LimitOrder */,
      collectFeeMode: collectFeeMode ? collectFeeMode : 0 /* InputOnly */,
      activationType,
      activationPoint: activationPoint ? activationPoint : null,
      hasAlphaVault,
      baseFeePowerFactor: 0,
      creatorPoolOnOffControl: creatorPoolOnOffControl ? creatorPoolOnOffControl : false,
      padding: Array(60).fill(0)
    };
    const preInstructions = [];
    const userTokenX = getAssociatedTokenAddressSync2(
      tokenX,
      creatorKey,
      true,
      tokenXAccount.owner
    );
    const createUserTokenXIx = createAssociatedTokenAccountIdempotentInstruction2(
      creatorKey,
      userTokenX,
      creatorKey,
      tokenX,
      tokenXAccount.owner
    );
    preInstructions.push(createUserTokenXIx);
    const userTokenY = getAssociatedTokenAddressSync2(
      tokenY,
      creatorKey,
      true,
      tokenYAccount.owner
    );
    const createUserTokenYIx = createAssociatedTokenAccountIdempotentInstruction2(
      creatorKey,
      userTokenY,
      creatorKey,
      tokenY,
      tokenYAccount.owner
    );
    preInstructions.push(createUserTokenYIx);
    const postInstructions = [];
    if ((tokenX.equals(NATIVE_MINT2) || tokenY.equals(NATIVE_MINT2)) && !opt?.skipSolWrappingOperation) {
      const wrapAmount = BigInt(1);
      if (tokenX.equals(NATIVE_MINT2)) {
        const wrapSOLIxX = wrapSOLInstruction(
          creatorKey,
          userTokenX,
          wrapAmount
        );
        preInstructions.push(...wrapSOLIxX);
      }
      if (tokenY.equals(NATIVE_MINT2)) {
        const wrapSOLIxY = wrapSOLInstruction(
          creatorKey,
          userTokenY,
          wrapAmount
        );
        preInstructions.push(...wrapSOLIxY);
      }
      const unwrapSOLIx = await unwrapSOLInstruction(creatorKey);
      if (unwrapSOLIx) {
        postInstructions.push(unwrapSOLIx);
      }
    }
    return program.methods.initializeCustomizablePermissionlessLbPair(ixData).accountsPartial({
      lbPair,
      reserveX,
      reserveY,
      binArrayBitmapExtension,
      tokenMintX: tokenX,
      tokenMintY: tokenY,
      oracle,
      systemProgram: SystemProgram2.programId,
      userTokenX,
      userTokenY,
      funder: creatorKey
    }).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
  }
  /**
   * Create a new liquidity pair. Support only token program.
   * @param connection A connection to the Solana cluster.
   * @param funder The public key of the funder of the pair.
   * @param tokenX The mint of the first token.
   * @param tokenY The mint of the second token.
   * @param binStep The bin step for the pair.
   * @param baseFactor The base factor for the pair.
   * @param presetParameter The public key of the preset parameter account.
   * @param activeId The ID of the initial active bin. Represent the starting price.
   * @param opt An options object.
   * @returns A transaction that creates the pair.
   * @throws If the pair already exists.
   */
  static async createLbPair(connection, funder, tokenX, tokenY, binStep, baseFactor, presetParameter, activeId, opt) {
    const program = createProgram(connection, opt);
    const existsPool = await this.getPairPubkeyIfExists(
      connection,
      tokenX,
      tokenY,
      binStep,
      baseFactor,
      new BN24(0)
    );
    if (existsPool) {
      throw new Error("Pool already exists");
    }
    const [lbPair] = deriveLbPair2(
      tokenX,
      tokenY,
      binStep,
      baseFactor,
      program.programId
    );
    const [reserveX] = deriveReserve(tokenX, lbPair, program.programId);
    const [reserveY] = deriveReserve(tokenY, lbPair, program.programId);
    const [oracle] = deriveOracle(lbPair, program.programId);
    const activeBinArrayIndex = binIdToBinArrayIndex(activeId);
    const binArrayBitmapExtension = isOverflowDefaultBinArrayBitmap(
      activeBinArrayIndex
    ) ? deriveBinArrayBitmapExtension(lbPair, program.programId)[0] : null;
    return program.methods.initializeLbPair(activeId.toNumber(), binStep.toNumber()).accountsPartial({
      funder,
      lbPair,
      rent: SYSVAR_RENT_PUBKEY2,
      reserveX,
      reserveY,
      binArrayBitmapExtension,
      tokenMintX: tokenX,
      tokenMintY: tokenY,
      tokenProgram: TOKEN_PROGRAM_ID4,
      oracle,
      presetParameter,
      systemProgram: SystemProgram2.programId
    }).transaction();
  }
  /**
   * Create a new liquidity pair. Support both token and token2022 program.
   * @param connection A connection to the Solana cluster.
   * @param funder The public key of the funder of the pair.
   * @param tokenX The mint of the first token.
   * @param tokenY The mint of the second token.
   * @param presetParameter The public key of the preset parameter account.
   * @param activeId The ID of the initial active bin. Represent the starting price.
   * @param opt An options object.
   * @returns A transaction that creates the pair.
   * @throws If the pair already exists.
   */
  static async createLbPair2(connection, funder, tokenX, tokenY, presetParameter, activeId, opt) {
    const program = createProgram(connection, opt);
    const [tokenBadgeX] = deriveTokenBadge(tokenX, program.programId);
    const [tokenBadgeY] = deriveTokenBadge(tokenY, program.programId);
    const [
      tokenXAccount,
      tokenYAccount,
      tokenBadgeXAccount,
      tokenBadgeYAccount
    ] = await connection.getMultipleAccountsInfo([
      tokenX,
      tokenY,
      tokenBadgeX,
      tokenBadgeY
    ]);
    const presetParameterState = await program.account.presetParameter2.fetch(presetParameter);
    const existsPool = await this.getPairPubkeyIfExists(
      connection,
      tokenX,
      tokenY,
      new BN24(presetParameterState.binStep),
      new BN24(presetParameterState.baseFactor),
      new BN24(presetParameterState.baseFeePowerFactor),
      presetParameterState.concreteFunctionType,
      presetParameterState.collectFeeMode,
      {
        cluster: opt?.cluster,
        programId: opt?.programId
      }
    );
    if (existsPool) {
      throw new Error("Pool already exists");
    }
    const [lbPair] = deriveLbPairWithPresetParamWithIndexKey(
      presetParameter,
      tokenX,
      tokenY,
      program.programId
    );
    const [reserveX] = deriveReserve(tokenX, lbPair, program.programId);
    const [reserveY] = deriveReserve(tokenY, lbPair, program.programId);
    const [oracle] = deriveOracle(lbPair, program.programId);
    const activeBinArrayIndex = binIdToBinArrayIndex(activeId);
    const binArrayBitmapExtension = isOverflowDefaultBinArrayBitmap(
      activeBinArrayIndex
    ) ? deriveBinArrayBitmapExtension(lbPair, program.programId)[0] : null;
    return program.methods.initializeLbPair2({
      activeId: activeId.toNumber(),
      padding: Array(96).fill(0)
    }).accountsPartial({
      funder,
      lbPair,
      reserveX,
      reserveY,
      binArrayBitmapExtension,
      tokenMintX: tokenX,
      tokenMintY: tokenY,
      tokenBadgeX: tokenBadgeXAccount ? tokenBadgeX : program.programId,
      tokenBadgeY: tokenBadgeYAccount ? tokenBadgeY : program.programId,
      tokenProgramX: tokenXAccount.owner,
      tokenProgramY: tokenYAccount.owner,
      oracle,
      presetParameter,
      systemProgram: SystemProgram2.programId
    }).transaction();
  }
  /**
   * The function `refetchStates` retrieves and updates various states and data related to bin arrays
   * and lb pairs.
   */
  async refetchStates() {
    const binArrayBitmapExtensionPubkey = deriveBinArrayBitmapExtension(
      this.pubkey,
      this.program.programId
    )[0];
    const [
      lbPairAccountInfo,
      binArrayBitmapExtensionAccountInfo,
      reserveXAccountInfo,
      reserveYAccountInfo,
      mintXAccountInfo,
      mintYAccountInfo,
      reward0VaultAccountInfo,
      reward1VaultAccountInfo,
      rewardMint0AccountInfo,
      rewardMint1AccountInfo,
      clockAccountInfo
    ] = await chunkedGetMultipleAccountInfos(this.program.provider.connection, [
      this.pubkey,
      binArrayBitmapExtensionPubkey,
      this.lbPair.reserveX,
      this.lbPair.reserveY,
      this.lbPair.tokenXMint,
      this.lbPair.tokenYMint,
      this.lbPair.rewardInfos[0].vault,
      this.lbPair.rewardInfos[1].vault,
      this.lbPair.rewardInfos[0].mint,
      this.lbPair.rewardInfos[1].mint,
      SYSVAR_CLOCK_PUBKEY2
    ]);
    const lbPairState = decodeAccount(
      this.program,
      "lbPair",
      lbPairAccountInfo.data
    );
    if (binArrayBitmapExtensionAccountInfo) {
      const binArrayBitmapExtensionState = decodeAccount(
        this.program,
        "binArrayBitmapExtension",
        binArrayBitmapExtensionAccountInfo.data
      );
      if (binArrayBitmapExtensionState) {
        this.binArrayBitmapExtension = {
          account: binArrayBitmapExtensionState,
          publicKey: binArrayBitmapExtensionPubkey
        };
      }
    }
    const reserveXBalance = AccountLayout.decode(reserveXAccountInfo.data);
    const reserveYBalance = AccountLayout.decode(reserveYAccountInfo.data);
    const [
      tokenXTransferHook,
      tokenYTransferHook,
      reward0TransferHook,
      reward1TransferHook
    ] = await Promise.all([
      getExtraAccountMetasForTransferHook(
        this.program.provider.connection,
        lbPairState.tokenXMint,
        mintXAccountInfo
      ),
      getExtraAccountMetasForTransferHook(
        this.program.provider.connection,
        lbPairState.tokenYMint,
        mintYAccountInfo
      ),
      rewardMint0AccountInfo ? getExtraAccountMetasForTransferHook(
        this.program.provider.connection,
        lbPairState.rewardInfos[0].mint,
        rewardMint0AccountInfo
      ) : [],
      rewardMint1AccountInfo ? getExtraAccountMetasForTransferHook(
        this.program.provider.connection,
        lbPairState.rewardInfos[1].mint,
        rewardMint1AccountInfo
      ) : []
    ]);
    const mintX = unpackMint2(
      this.tokenX.publicKey,
      mintXAccountInfo,
      mintXAccountInfo.owner
    );
    const mintY = unpackMint2(
      this.tokenY.publicKey,
      mintYAccountInfo,
      mintYAccountInfo.owner
    );
    this.tokenX = {
      amount: reserveXBalance.amount,
      mint: mintX,
      publicKey: lbPairState.tokenXMint,
      reserve: lbPairState.reserveX,
      owner: mintXAccountInfo.owner,
      transferHookAccountMetas: tokenXTransferHook
    };
    this.tokenY = {
      amount: reserveYBalance.amount,
      mint: mintY,
      publicKey: lbPairState.tokenYMint,
      reserve: lbPairState.reserveY,
      owner: mintYAccountInfo.owner,
      transferHookAccountMetas: tokenYTransferHook
    };
    this.rewards[0] = null;
    this.rewards[1] = null;
    if (!lbPairState.rewardInfos[0].mint.equals(PublicKey10.default)) {
      this.rewards[0] = {
        publicKey: lbPairState.rewardInfos[0].mint,
        reserve: lbPairState.rewardInfos[0].vault,
        mint: unpackMint2(
          lbPairState.rewardInfos[0].mint,
          rewardMint0AccountInfo,
          rewardMint0AccountInfo.owner
        ),
        amount: AccountLayout.decode(reward0VaultAccountInfo.data).amount,
        owner: rewardMint0AccountInfo.owner,
        transferHookAccountMetas: reward0TransferHook
      };
    }
    if (!lbPairState.rewardInfos[1].mint.equals(PublicKey10.default)) {
      this.rewards[1] = {
        publicKey: lbPairState.rewardInfos[1].mint,
        reserve: lbPairState.rewardInfos[1].vault,
        mint: unpackMint2(
          lbPairState.rewardInfos[1].mint,
          rewardMint1AccountInfo,
          rewardMint1AccountInfo.owner
        ),
        amount: AccountLayout.decode(reward1VaultAccountInfo.data).amount,
        owner: rewardMint1AccountInfo.owner,
        transferHookAccountMetas: reward1TransferHook
      };
    }
    const clock = ClockLayout.decode(clockAccountInfo.data);
    this.clock = clock;
    this.lbPair = lbPairState;
  }
  /**
   * Set the status of a permissionless LB pair to either enabled or disabled. This require pool field `creator_pool_on_off_control` to be true and type `CustomizablePermissionless`.
   * Pool creator can enable/disable the pair anytime before the pool is opened / activated. Once the pool activation time is passed, the pool creator can only enable the pair.
   * Useful for token launches which do not have fixed activation time.
   * @param enable If true, the pair will be enabled. If false, the pair will be disabled.
   * @param creator The public key of the pool creator.
   * @returns a Promise that resolves to the transaction.
   */
  async setPairStatusPermissionless(enable, creator) {
    const status = enable ? 0 : 1;
    const tx = await this.program.methods.setPairStatusPermissionless(status).accountsPartial({
      lbPair: this.pubkey,
      signer: creator
    }).transaction();
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      feePayer: this.lbPair.creator,
      blockhash,
      lastValidBlockHeight
    }).add(tx);
  }
  /**
   * The function `getBinArrays` returns an array of `BinArrayAccount` objects
   * @returns a Promise that resolves to an array of BinArrayAccount objects.
   */
  async getBinArrays() {
    return this.program.account.binArray.all([
      binArrayLbPairFilter(this.pubkey)
    ]);
  }
  /**
   * The function `getBinArrayAroundActiveBin` retrieves a specified number of `BinArrayAccount`
   * objects from the blockchain, based on the active bin and its surrounding bin arrays.
   * @param
   *    swapForY - The `swapForY` parameter is a boolean value that indicates whether the swap is using quote token as input.
   *    [count=4] - The `count` parameter is the number of bin arrays to retrieve on left and right respectively. By default, it is set to 4.
   * @returns an array of `BinArrayAccount` objects.
   */
  async getBinArrayForSwap(swapForY, count = 4) {
    await this.refetchStates();
    const binArraysPubkey = /* @__PURE__ */ new Set();
    let shouldStop = false;
    let activeIdToLoop = this.lbPair.activeId;
    while (!shouldStop) {
      const binArrayIndex = findNextBinArrayIndexWithLiquidity(
        swapForY,
        new BN24(activeIdToLoop),
        this.lbPair,
        this.binArrayBitmapExtension?.account ?? null
      );
      if (binArrayIndex === null)
        shouldStop = true;
      else {
        const [binArrayPubKey] = deriveBinArray(
          this.pubkey,
          binArrayIndex,
          this.program.programId
        );
        binArraysPubkey.add(binArrayPubKey.toBase58());
        const [lowerBinId, upperBinId] = getBinArrayLowerUpperBinId(binArrayIndex);
        activeIdToLoop = swapForY ? lowerBinId.toNumber() - 1 : upperBinId.toNumber() + 1;
      }
      if (binArraysPubkey.size === count)
        shouldStop = true;
    }
    const accountsToFetch = Array.from(binArraysPubkey).map(
      (pubkey) => new PublicKey10(pubkey)
    );
    const binArraysAccInfoBuffer = await chunkedGetMultipleAccountInfos(
      this.program.provider.connection,
      accountsToFetch
    );
    const binArrays = await Promise.all(
      binArraysAccInfoBuffer.map(async (accInfo, idx) => {
        const account = decodeAccount(
          this.program,
          "binArray",
          accInfo.data
        );
        const publicKey = accountsToFetch[idx];
        return {
          account,
          publicKey
        };
      })
    );
    return binArrays;
  }
  /**
   * The function `calculateFeeInfo` calculates the base fee rate percentage and maximum fee rate percentage
   * given the base factor, bin step, and optional base fee power factor.
   * @param baseFactor - The base factor of the pair.
   * @param binStep - The bin step of the pair.
   * @param baseFeePowerFactor - Optional parameter to allow small bin step to have bigger fee rate. Default to 0.
   * @returns an object of type `Omit<FeeInfo, "protocolFeePercentage">` with the following properties: baseFeeRatePercentage and maxFeeRatePercentage.
   */
  static calculateFeeInfo(baseFactor, binStep, baseFeePowerFactor) {
    const baseFeeRate = new BN24(baseFactor).mul(new BN24(binStep)).mul(new BN24(10)).mul(new BN24(10).pow(new BN24(baseFeePowerFactor ?? 0)));
    const baseFeeRatePercentage = new Decimal11(baseFeeRate.toString()).mul(new Decimal11(100)).div(new Decimal11(FEE_PRECISION.toString()));
    const maxFeeRatePercentage = new Decimal11(MAX_FEE_RATE.toString()).mul(new Decimal11(100)).div(new Decimal11(FEE_PRECISION.toString()));
    return {
      baseFeeRatePercentage,
      maxFeeRatePercentage
    };
  }
  /**
   * The function `getFeeInfo` calculates and returns the base fee rate percentage, maximum fee rate
   * percentage, and protocol fee percentage.
   * @returns an object of type `FeeInfo` with the following properties: baseFeeRatePercentage, maxFeeRatePercentage, and protocolFeePercentage.
   */
  getFeeInfo() {
    const { baseFactor, protocolShare } = this.lbPair.parameters;
    const { baseFeeRatePercentage, maxFeeRatePercentage } = DLMM.calculateFeeInfo(
      baseFactor,
      this.lbPair.binStep,
      this.lbPair.parameters.baseFeePowerFactor
    );
    const protocolFeePercentage = new Decimal11(protocolShare.toString()).mul(new Decimal11(100)).div(new Decimal11(BASIS_POINT_MAX));
    return {
      baseFeeRatePercentage,
      maxFeeRatePercentage,
      protocolFeePercentage
    };
  }
  /**
   * The function calculates and returns a dynamic fee
   * @returns a Decimal value representing the dynamic fee.
   */
  getDynamicFee() {
    let vParameterClone = Object.assign({}, this.lbPair.vParameters);
    let activeId = new BN24(this.lbPair.activeId);
    const sParameters3 = this.lbPair.parameters;
    const currentTimestamp = Date.now() / 1e3;
    DLMM.updateReference(
      activeId.toNumber(),
      vParameterClone,
      sParameters3,
      currentTimestamp
    );
    DLMM.updateVolatilityAccumulator(
      vParameterClone,
      sParameters3,
      activeId.toNumber()
    );
    const totalFee = getTotalFee(
      this.lbPair.binStep,
      sParameters3,
      vParameterClone
    );
    return new Decimal11(totalFee.toString()).div(new Decimal11(FEE_PRECISION.toString())).mul(100);
  }
  /**
   * The function `getEmissionRate` returns the emission rates for two rewards.
   * @returns an object of type `EmissionRate`. The object has two properties: `rewardOne` and
   * `rewardTwo`, both of which are of type `Decimal`.
   */
  getEmissionRate() {
    const now = Date.now() / 1e3;
    const [rewardOneEmissionRate, rewardTwoEmissionRate] = this.lbPair.rewardInfos.map(
      ({ rewardRate, rewardDurationEnd }) => now > rewardDurationEnd.toNumber() ? void 0 : rewardRate
    );
    return {
      rewardOne: rewardOneEmissionRate ? new Decimal11(rewardOneEmissionRate.toString()).div(PRECISION) : void 0,
      rewardTwo: rewardTwoEmissionRate ? new Decimal11(rewardTwoEmissionRate.toString()).div(PRECISION) : void 0
    };
  }
  /**
   * The function `getBinsAroundActiveBin` retrieves a specified number of bins to the left and right
   * of the active bin and returns them along with the active bin ID.
   * @param {number} numberOfBinsToTheLeft - The parameter `numberOfBinsToTheLeft` represents the
   * number of bins to the left of the active bin that you want to retrieve. It determines how many
   * bins you want to include in the result that are positioned to the left of the active bin.
   * @param {number} numberOfBinsToTheRight - The parameter `numberOfBinsToTheRight` represents the
   * number of bins to the right of the active bin that you want to retrieve.
   * @returns an object with two properties: "activeBin" and "bins". The value of "activeBin" is the
   * value of "this.lbPair.activeId", and the value of "bins" is the result of calling the "getBins"
   * function with the specified parameters.
   */
  async getBinsAroundActiveBin(numberOfBinsToTheLeft, numberOfBinsToTheRight) {
    const lowerBinId = this.lbPair.activeId - numberOfBinsToTheLeft - 1;
    const upperBinId = this.lbPair.activeId + numberOfBinsToTheRight + 1;
    const bins = await this.getBins(
      this.pubkey,
      lowerBinId,
      upperBinId,
      this.tokenX.mint.decimals,
      this.tokenY.mint.decimals
    );
    return { activeBin: this.lbPair.activeId, bins };
  }
  /**
   * The function `getBinsBetweenMinAndMaxPrice` retrieves a list of bins within a specified price
   * range.
   * @param {number} minPrice - The minimum price value for filtering the bins.
   * @param {number} maxPrice - The `maxPrice` parameter is the maximum price value that you want to
   * use for filtering the bins.
   * @returns an object with two properties: "activeBin" and "bins". The value of "activeBin" is the
   * active bin ID of the lbPair, and the value of "bins" is an array of BinLiquidity objects.
   */
  async getBinsBetweenMinAndMaxPrice(minPrice, maxPrice) {
    const lowerBinId = this.getBinIdFromPrice(minPrice, true) - 1;
    const upperBinId = this.getBinIdFromPrice(maxPrice, false) + 1;
    const bins = await this.getBins(
      this.pubkey,
      lowerBinId,
      upperBinId,
      this.tokenX.mint.decimals,
      this.tokenY.mint.decimals
    );
    return { activeBin: this.lbPair.activeId, bins };
  }
  /**
   * The function `getBinsBetweenLowerAndUpperBound` retrieves a list of bins between a lower and upper
   * bin ID and returns the active bin ID and the list of bins.
   * @param {number} lowerBinId - The lowerBinId parameter is a number that represents the ID of the
   * lowest bin.
   * @param {number} upperBinId - The upperBinID parameter is a number that represents the ID of the
   * highest bin.
   * @param {BinArray} [lowerBinArrays] - The `lowerBinArrays` parameter is an optional parameter of
   * type `BinArray`. It represents an array of bins that are below the lower bin ID.
   * @param {BinArray} [upperBinArrays] - The parameter `upperBinArrays` is an optional parameter of
   * type `BinArray`. It represents an array of bins that are above the upper bin ID.
   * @returns an object with two properties: "activeBin" and "bins". The value of "activeBin" is the
   * active bin ID of the lbPair, and the value of "bins" is an array of BinLiquidity objects.
   */
  async getBinsBetweenLowerAndUpperBound(lowerBinId, upperBinId, lowerBinArray, upperBinArray) {
    const bins = await this.getBins(
      this.pubkey,
      lowerBinId,
      upperBinId,
      this.tokenX.mint.decimals,
      this.tokenY.mint.decimals,
      lowerBinArray,
      upperBinArray
    );
    return { activeBin: this.lbPair.activeId, bins };
  }
  /**
   * The function converts a real price of bin to a lamport value
   * @param {number} price - The `price` parameter is a number representing the price of a token.
   * @returns {string} price per Lamport of bin
   */
  toPricePerLamport(price) {
    return DLMM.getPricePerLamport(
      this.tokenX.mint.decimals,
      this.tokenY.mint.decimals,
      price
    );
  }
  /**
   * The function converts a price per lamport value to a real price of bin
   * @param {number} pricePerLamport - The parameter `pricePerLamport` is a number representing the
   * price per lamport.
   * @returns {string} real price of bin
   */
  fromPricePerLamport(pricePerLamport) {
    return new Decimal11(pricePerLamport).div(
      new Decimal11(
        10 ** (this.tokenY.mint.decimals - this.tokenX.mint.decimals)
      )
    ).toString();
  }
  /**
   * The function retrieves the active bin ID and its corresponding price.
   * @returns an object with two properties: "binId" which is a number, and "price" which is a string.
   */
  async getActiveBin() {
    const { activeId } = await this.program.account.lbPair.fetch(this.pubkey);
    const [activeBinState] = await this.getBins(
      this.pubkey,
      activeId,
      activeId,
      this.tokenX.mint.decimals,
      this.tokenY.mint.decimals
    );
    return activeBinState;
  }
  /**
   * The function get bin ID based on a given price and a boolean flag indicating whether to
   * round down or up.
   * @param {number} price - The price parameter is a number that represents the price value.
   * @param {boolean} min - The "min" parameter is a boolean value that determines whether to round
   * down or round up the calculated binId. If "min" is true, the binId will be rounded down (floor),
   * otherwise it will be rounded up (ceil).
   * @returns {number} which is the binId calculated based on the given price and whether the minimum
   * value should be used.
   */
  getBinIdFromPrice(price, min) {
    return DLMM.getBinIdFromPrice(price, this.lbPair.binStep, min);
  }
  /**
   * The function `getLimitOrderByUserAndLbPair` retrieves all limit orders for a user in the current LB pair
   * and parses them with on-chain bin array and clock state.
   * @param {PublicKey} userPubKey - The public key of the user who owns the limit orders.
   * @returns A Promise that resolves to an array of parsed limit orders with their public keys.
   */
  async getLimitOrderByUserAndLbPair(userPubKey) {
    const limitOrderAccounts = await chunkedGetProgramAccounts(
      this.program.provider.connection,
      this.program.programId,
      [
        limitOrderFilter(),
        limitOrderOwnerFilter(userPubKey),
        limitOrderLbPairFilter(this.pubkey)
      ]
    );
    const limitOrders = limitOrderAccounts.map(
      ({ account, pubkey }) => {
        return wrapLimitOrder(this.program, pubkey, account);
      }
    );
    const binArrayPubkeysSet = /* @__PURE__ */ new Set();
    limitOrders.forEach((lo) => {
      const binArrayPubkeys = lo.getBinArrayKeysCoverage(
        this.program.programId
      );
      binArrayPubkeys.forEach((key) => {
        binArrayPubkeysSet.add(key.toString());
      });
    });
    const binArrayPubkeyArrays = Array.from(binArrayPubkeysSet).map(
      (pubkey) => new PublicKey10(pubkey)
    );
    const lbPairAndBinArrays = await chunkedGetMultipleAccountInfos(
      this.program.provider.connection,
      [this.pubkey, SYSVAR_CLOCK_PUBKEY2, ...binArrayPubkeyArrays]
    );
    const [lbPairAccInfo, clockAccInfo, ...binArraysAccInfo] = lbPairAndBinArrays;
    const clock = ClockLayout.decode(clockAccInfo.data);
    const lbPairState = decodeAccount(
      this.program,
      "lbPair",
      lbPairAccInfo.data
    );
    const binArrayMap = /* @__PURE__ */ new Map();
    for (let i = 0; i < binArraysAccInfo.length; i++) {
      const binArrayPubkey = binArrayPubkeyArrays[i];
      const binArrayAccInfo = binArraysAccInfo[i];
      const binArrayState = decodeAccount(
        this.program,
        "binArray",
        binArrayAccInfo.data
      );
      binArrayMap.set(binArrayPubkey.toBase58(), binArrayState);
    }
    const parsedLimitOrder = limitOrders.map(
      (lo) => {
        const parsedLo = lo.parseInfo(
          this.program.programId,
          lbPairState,
          this.tokenX.mint,
          this.tokenY.mint,
          clock,
          binArrayMap
        );
        return {
          publicKey: lo.address(),
          limitOrderData: parsedLo
        };
      }
    );
    return parsedLimitOrder;
  }
  /**
   * Fetches and parses a single limit order by address for the current LB pair.
   *
   * This method loads the limit order account, the LB pair state, clock sysvar,
   * and all required bin arrays to produce a parsed limit order view.
   * @param {PublicKey} limitOrder - The public key of the limit order account.
   * @returns A Promise that resolves to the parsed limit order with its public key.
   */
  async getLimitOrder(limitOrder) {
    const limitOrderAccount = await this.program.provider.connection.getAccountInfo(limitOrder);
    const limitOrderState = wrapLimitOrder(
      this.program,
      limitOrder,
      limitOrderAccount
    );
    const binArrayPubkeyArrays = limitOrderState.getBinArrayKeysCoverage(
      this.program.programId
    );
    const lbPairAndBinArrays = await chunkedGetMultipleAccountInfos(
      this.program.provider.connection,
      [this.pubkey, SYSVAR_CLOCK_PUBKEY2, ...binArrayPubkeyArrays]
    );
    const [lbPairAccInfo, clockAccInfo, ...binArraysAccInfo] = lbPairAndBinArrays;
    const clock = ClockLayout.decode(clockAccInfo.data);
    const lbPairState = decodeAccount(
      this.program,
      "lbPair",
      lbPairAccInfo.data
    );
    const binArrayMap = /* @__PURE__ */ new Map();
    for (let i = 0; i < binArraysAccInfo.length; i++) {
      const binArrayPubkey = binArrayPubkeyArrays[i];
      const binArrayAccInfo = binArraysAccInfo[i];
      const binArrayState = decodeAccount(
        this.program,
        "binArray",
        binArrayAccInfo.data
      );
      binArrayMap.set(binArrayPubkey.toBase58(), binArrayState);
    }
    const parsedLo = limitOrderState.parseInfo(
      this.program.programId,
      lbPairState,
      this.tokenX.mint,
      this.tokenY.mint,
      clock,
      binArrayMap
    );
    return {
      publicKey: limitOrder,
      limitOrderData: parsedLo
    };
  }
  /**
   * The function `getPositionsByUserAndLbPair` retrieves positions by user and LB pair, including
   * active bin and user positions.
   * @param {PublicKey} [userPubKey] - The `userPubKey` parameter is an optional parameter of type
   * `PublicKey`. It represents the public key of a user. If no `userPubKey` is provided, the function
   * will return an object with an empty `userPositions` array and the active bin information obtained
   * from the `getActive
   * @param {GetPositionsOpt} [getPositionsOpt] - Optional settings for chunked position fetching
   * @returns The function `getPositionsByUserAndLbPair` returns a Promise that resolves to an object
   * with two properties:
   *    - "activeBin" which is an object with two properties: "binId" and "price". The value of "binId"
   *     is the active bin ID of the lbPair, and the value of "price" is the price of the active bin.
   *   - "userPositions" which is an array of Position objects.
   */
  async getPositionsByUserAndLbPair(userPubKey, getPositionsOpt) {
    const promiseResults = await Promise.all([
      this.getActiveBin(),
      userPubKey && chunkedGetProgramAccounts(
        this.program.provider.connection,
        this.program.programId,
        [
          positionV2Filter(),
          positionOwnerFilter(userPubKey),
          positionLbPairFilter(this.pubkey)
        ],
        getPositionsOpt?.chunkSize,
        getPositionsOpt?.onChunkFetched,
        getPositionsOpt?.isParallelExecution
      )
    ]);
    const [activeBin, positionsV2] = promiseResults;
    if (!activeBin) {
      throw new Error("Error fetching active bin");
    }
    if (!userPubKey) {
      return {
        activeBin,
        userPositions: []
      };
    }
    const positions = [
      ...positionsV2.map(
        (p) => wrapPosition(this.program, p.pubkey, p.account)
      )
    ];
    if (!positions) {
      throw new Error("Error fetching positions");
    }
    const binArrayPubkeySetV2 = /* @__PURE__ */ new Set();
    positions.forEach((position) => {
      const binArrayKeys = position.getBinArrayKeysCoverage(
        this.program.programId
      );
      binArrayKeys.forEach((key) => {
        binArrayPubkeySetV2.add(key.toBase58());
      });
    });
    const binArrayPubkeyArrayV2 = Array.from(binArrayPubkeySetV2).map(
      (pubkey) => new PublicKey10(pubkey)
    );
    const lbPairAndBinArrays = await chunkedGetMultipleAccountInfos(
      this.program.provider.connection,
      [this.pubkey, SYSVAR_CLOCK_PUBKEY2, ...binArrayPubkeyArrayV2]
    );
    const [lbPairAccInfo, clockAccInfo, ...binArraysAccInfo] = lbPairAndBinArrays;
    const positionBinArraysMapV2 = /* @__PURE__ */ new Map();
    for (let i = 0; i < binArraysAccInfo.length; i++) {
      const binArrayPubkey = binArrayPubkeyArrayV2[i];
      const binArrayAccBufferV2 = binArraysAccInfo[i];
      if (binArrayAccBufferV2) {
        const binArrayAccInfo = decodeAccount(
          this.program,
          "binArray",
          binArrayAccBufferV2.data
        );
        positionBinArraysMapV2.set(binArrayPubkey.toBase58(), binArrayAccInfo);
      }
    }
    if (!lbPairAccInfo)
      throw new Error(`LB Pair account ${this.pubkey.toBase58()} not found`);
    const clock = ClockLayout.decode(clockAccInfo.data);
    const userPositions = await Promise.all(
      positions.map(async (position) => {
        return {
          publicKey: position.address(),
          positionData: await DLMM.processPosition(
            this.program,
            this.lbPair,
            clock,
            position,
            this.tokenX.mint,
            this.tokenY.mint,
            this.rewards[0]?.mint,
            this.rewards[1]?.mint,
            positionBinArraysMapV2
          ),
          version: position.version()
        };
      })
    );
    return {
      activeBin,
      userPositions
    };
  }
  /**
   * Estimates the cost to extend a position by a specified number of bins. Max position length is 1400
   *
   * The function calculates the rent cost required to expand a position and the cost
   * to create necessary bin arrays for the new position range.
   *
   * @param currentMinBinId - The current minimum bin ID of the position.
   * @param currentMaxBinId - The current maximum bin ID of the position.
   * @param binCountToExpand - The number of bins to expand the position by.
   * @returns An object containing:
   *   - positionExtendCost: The estimated rent cost in lamports for extending the position.
   *   - binArrayCost: The estimated cost for creating necessary bin arrays.
   */
  async quoteExtendPosition(currentMinBinId, currentMaxBinId, binCountToExpand) {
    const positionExtendCost = await getPositionExpandRentExemption(
      currentMinBinId,
      currentMaxBinId,
      this.program.provider.connection,
      binCountToExpand
    );
    const lowerBinArrayIndex = binIdToBinArrayIndex(currentMinBinId);
    const upperBinArrayIndex = binIdToBinArrayIndex(currentMaxBinId);
    const binArraysCount = (await this.binArraysToBeCreate(lowerBinArrayIndex, upperBinArrayIndex)).length;
    const binArrayCost = new Decimal11(binArraysCount).mul(
      new Decimal11(BIN_ARRAY_FEE)
    );
    return {
      positionExtendCost: new Decimal11(positionExtendCost).div(
        new Decimal11(LAMPORTS_PER_SOL2)
      ),
      binArrayCost
    };
  }
  async quoteCreatePosition({ strategy }) {
    const { minBinId, maxBinId } = strategy;
    const binCount = maxBinId - minBinId + 1;
    let positionCount = Math.floor(binCount / MAX_BINS_PER_POSITION.toNumber());
    if (binCount % MAX_BINS_PER_POSITION.toNumber() > 0) {
      positionCount++;
    }
    let positionReallocCost = 0;
    let lastUpperBinId = minBinId;
    for (let i = 0; i < positionCount; i++) {
      const lowerBinId = lastUpperBinId;
      const upperBinId = Math.min(
        maxBinId,
        lowerBinId + DEFAULT_BIN_PER_POSITION.toNumber() - 1
      );
      const maxUpperBinId = Math.min(
        maxBinId,
        upperBinId + MAX_BINS_PER_POSITION.toNumber() - 1
      );
      const binToExpand = maxUpperBinId - upperBinId;
      const { positionExtendCost } = await this.quoteExtendPosition(
        new BN24(lowerBinId),
        new BN24(upperBinId),
        new BN24(binToExpand)
      );
      positionReallocCost += positionExtendCost.toNumber();
      lastUpperBinId = upperBinId;
    }
    const lowerBinArrayIndex = binIdToBinArrayIndex(new BN24(minBinId));
    const upperBinArrayIndex = BN24.max(
      binIdToBinArrayIndex(new BN24(maxBinId)),
      lowerBinArrayIndex.add(new BN24(1))
    );
    let bitmapExtensionCost = 0;
    if (isOverflowDefaultBinArrayBitmap(lowerBinArrayIndex) || isOverflowDefaultBinArrayBitmap(upperBinArrayIndex)) {
      bitmapExtensionCost = BIN_ARRAY_BITMAP_FEE;
    }
    const binArraysCount = (await this.binArraysToBeCreate(lowerBinArrayIndex, upperBinArrayIndex)).length;
    const transactionCount = Math.ceil(
      (maxBinId - minBinId + 1) / DEFAULT_BIN_PER_POSITION.toNumber()
    );
    const binArrayCost = binArraysCount * BIN_ARRAY_FEE;
    return {
      positionCount,
      positionCost: positionCount * POSITION_FEE,
      positionReallocCost,
      bitmapExtensionCost,
      binArraysCount,
      binArrayCost,
      transactionCount
    };
  }
  /**
   * Quote the cost to create a limit order
   * @param bins - Array of bin IDs (absolute, or relative offsets from active bin if relativeBin is set) to place limit orders in.
   * @param relativeBin - When set, the `bin.id` in `params.bins` will be treated as relative to the current active bin, which mean bin.id = bin.id + activeId. Otherwise, it will be absolute bin id.
   */
  async quoteCreateLimitOrder({
    bins,
    relativeBin
  }) {
    const binCount = bins.length;
    if (binCount <= 0 || binCount > MAX_BIN_PER_LIMIT_ORDER.toNumber()) {
      throw new Error(
        `Bin count must be between 1 and ${MAX_BIN_PER_LIMIT_ORDER.toNumber()}`
      );
    }
    for (let i = 1; i < binCount; i++) {
      const prevBinId = bins[i - 1].id;
      const currentBinId = bins[i].id;
      if (currentBinId <= prevBinId) {
        throw new Error(`Bin IDs must be in increasing order`);
      }
    }
    const resolvedBinIds = bins.map(
      (bin) => relativeBin == null ? bin.id : bin.id + this.lbPair.activeId
    );
    const { binArrayBitmapExtension, binArrayAccountMetas } = getBinArrayInfoForNonContiguousBinIds(
      resolvedBinIds,
      this.program.programId,
      this.pubkey
    );
    const requireBitmapExtension = !binArrayBitmapExtension.equals(
      this.program.programId
    );
    const limitOrderAccountSize = 8 + LIMIT_ORDER_MIN_SIZE + binCount * LIMIT_ORDER_BIN_DATA_SIZE;
    const limitOrderCost = await this.program.provider.connection.getMinimumBalanceForRentExemption(
      limitOrderAccountSize
    );
    const binArrayPubkeys = binArrayAccountMetas.map((acc) => acc.pubkey);
    const accountsToFetch = [...binArrayPubkeys];
    if (requireBitmapExtension) {
      accountsToFetch.push(binArrayBitmapExtension);
    }
    const accounts = await chunkedGetMultipleAccountInfos(
      this.program.provider.connection,
      accountsToFetch
    );
    const binArrayAccounts = accounts.splice(0, binArrayPubkeys.length);
    const bitmapExtensionAccount = accounts.splice(0, accounts.length).pop();
    const uninitializedBinArrayCount = binArrayAccounts.filter(
      (acc) => acc === null
    ).length;
    let bitmapExtensionCost = 0;
    if (requireBitmapExtension && !bitmapExtensionAccount) {
      bitmapExtensionCost = BIN_ARRAY_BITMAP_FEE;
    }
    const binArrayCost = uninitializedBinArrayCount * BIN_ARRAY_FEE;
    return {
      limitOrderCost: limitOrderCost / LAMPORTS_PER_SOL2,
      binArraysCount: uninitializedBinArrayCount,
      binArrayCost,
      bitmapExtensionCost
    };
  }
  /**
   * Creates an empty position and initializes the corresponding bin arrays if needed.
   * @param param0 The settings of the requested new position.
   * @returns A promise that resolves into a transaction for creating the requested position.
   */
  async createEmptyPosition({
    positionPubKey,
    minBinId,
    maxBinId,
    user
  }) {
    const createPositionIx = await this.program.methods.initializePosition(minBinId, maxBinId - minBinId + 1).accountsPartial({
      payer: user,
      position: positionPubKey,
      lbPair: this.pubkey,
      owner: user,
      rent: SYSVAR_RENT_PUBKEY2
    }).instruction();
    const binArrayIndexes = getBinArrayIndexesCoverage(
      new BN24(minBinId),
      new BN24(maxBinId)
    );
    const createBinArrayIxs = await this.createBinArraysIfNeeded(
      binArrayIndexes,
      user
    );
    const instructions = [createPositionIx, ...createBinArrayIxs];
    const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
      this.program.provider.connection,
      instructions,
      user
    );
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      blockhash,
      lastValidBlockHeight,
      feePayer: user
    }).add(setCUIx, ...instructions);
  }
  /**
   * The function `getPosition` retrieves position information for a given public key and processes it
   * using various data to return a `LbPosition` object.
   * @param {PublicKey} positionPubKey - The `getPosition` function you provided is an asynchronous
   * function that fetches position information based on a given public key. Here's a breakdown of the
   * parameters used in the function:
   * @returns The `getPosition` function returns a Promise that resolves to an object of type
   * `LbPosition`. The object contains the following properties:
   * - `publicKey`: The public key of the position account
   * - `positionData`: Position Object
   * - `version`: The version of the position (in this case, `Position.V2`)
   */
  async getPosition(positionPubKey) {
    const positionAccountInfo = await this.program.provider.connection.getAccountInfo(positionPubKey);
    if (!positionAccountInfo) {
      throw new Error(
        `Position account ${positionPubKey.toBase58()} not found`
      );
    }
    let position = wrapPosition(
      this.program,
      positionPubKey,
      positionAccountInfo
    );
    const binArrayKeys = position.getBinArrayKeysCoverage(
      this.program.programId
    );
    const [clockAccInfo, ...binArrayAccountsInfo] = await chunkedGetMultipleAccountInfos(this.program.provider.connection, [
      SYSVAR_CLOCK_PUBKEY2,
      ...binArrayKeys
    ]);
    const clock = ClockLayout.decode(clockAccInfo.data);
    const binArrayMap = /* @__PURE__ */ new Map();
    for (let i = 0; i < binArrayAccountsInfo.length; i++) {
      if (binArrayAccountsInfo[i]) {
        const binArrayState = decodeAccount(
          this.program,
          "binArray",
          binArrayAccountsInfo[i].data
        );
        binArrayMap.set(binArrayKeys[i].toBase58(), binArrayState);
      }
    }
    return {
      publicKey: positionPubKey,
      positionData: await DLMM.processPosition(
        this.program,
        this.lbPair,
        clock,
        position,
        this.tokenX.mint,
        this.tokenY.mint,
        this.rewards[0]?.mint,
        this.rewards[1]?.mint,
        binArrayMap
      ),
      version: position.version()
    };
  }
  /**
   * Creates multiple positions and adds liquidity by strategy. It allow parallel execution of transactions.
   * @param positionKeypairGenerator A function that generates a specified number of keypairs.
   * @param totalXAmount The total amount of token X to be added.
   * @param totalYAmount The total amount of token Y to be added.
   * @param strategy The strategy for adding liquidity.
   * @param owner The owner of the position.
   * @param payer The payer of the transaction.
   * @param slippagePercentage The slippage percentage for adding liquidity.
   * @returns An object with two properties: `initPositionIxs` and `addLiquidityIxs`.
   */
  async initializeMultiplePositionAndAddLiquidityByStrategy2(positionKeypairGenerator, totalXAmount, totalYAmount, strategy, owner, payer, slippagePercentage, altAddress) {
    const maxActiveBinSlippage = getAndCapMaxActiveBinSlippage(
      slippagePercentage,
      this.lbPair.binStep,
      MAX_ACTIVE_BIN_SLIPPAGE
    );
    const { minBinId, maxBinId } = strategy;
    const binCount = getBinCount(minBinId, maxBinId);
    const defaultAltAddressString = altAddress ?? ALT_ADDRESS[this.opt?.cluster];
    if (defaultAltAddressString) {
      altAddress = new PublicKey10(defaultAltAddressString);
    }
    const maxResizeIxAllowed = altAddress ? 5 : 3;
    const maxBinPerParallelizedPosition = DEFAULT_BIN_PER_POSITION.toNumber() + MAX_RESIZE_LENGTH.toNumber() * maxResizeIxAllowed;
    const positionCount = Math.ceil(binCount / maxBinPerParallelizedPosition);
    const positionKeypairs = await positionKeypairGenerator(positionCount);
    const liquidityStrategyParameters = buildLiquidityStrategyParameters(
      totalXAmount,
      totalYAmount,
      new BN24(minBinId - this.lbPair.activeId),
      new BN24(maxBinId - this.lbPair.activeId),
      new BN24(this.lbPair.binStep),
      strategy.singleSidedX,
      new BN24(this.lbPair.activeId),
      getLiquidityStrategyParameterBuilder(strategy.strategyType)
    );
    let startBinId = minBinId;
    const response = { instructionsByPositions: [], lookupTableAddress: altAddress };
    for (const position of positionKeypairs) {
      const txsIxs = [];
      const endBinId = Math.min(
        startBinId + maxBinPerParallelizedPosition - 1,
        maxBinId
      );
      const finalPositionWidth = endBinId - startBinId + 1;
      const initialPositionWidth = finalPositionWidth > DEFAULT_BIN_PER_POSITION.toNumber() ? DEFAULT_BIN_PER_POSITION.toNumber() : finalPositionWidth;
      const initPositionIx = await this.program.methods.initializePosition2(startBinId, initialPositionWidth).accountsPartial({
        position: position.publicKey,
        lbPair: this.pubkey,
        owner,
        payer
      }).instruction();
      const extendPositionIxs = [];
      let currentEndBinId = startBinId + initialPositionWidth - 1;
      while (true) {
        if (currentEndBinId == endBinId)
          break;
        currentEndBinId = Math.min(
          currentEndBinId + MAX_RESIZE_LENGTH.toNumber(),
          endBinId
        );
        const increaseLengthIx = await this.program.methods.increasePositionLength2(currentEndBinId).accountsPartial({
          lbPair: this.pubkey,
          position: position.publicKey,
          funder: payer,
          owner
        }).instruction();
        extendPositionIxs.push(increaseLengthIx);
      }
      const addLiquidityIxs = await chunkDepositWithRebalanceEndpoint(
        this,
        strategy,
        slippagePercentage,
        maxActiveBinSlippage,
        position.publicKey,
        startBinId,
        endBinId,
        liquidityStrategyParameters,
        owner,
        payer,
        true,
        this.opt?.skipSolWrappingOperation
      );
      for (const instructions of addLiquidityIxs) {
        const txIxs = [];
        txIxs.push(initPositionIx);
        txIxs.push(...extendPositionIxs);
        txIxs.push(...instructions);
        const setCuIx = await getEstimatedComputeUnitIxWithBuffer(
          this.program.provider.connection,
          txIxs,
          payer,
          0.1,
          altAddress
        );
        txIxs.unshift(setCuIx);
        txsIxs.push(txIxs);
      }
      response.instructionsByPositions.push({
        positionKeypair: position,
        transactionInstructions: txsIxs
      });
      startBinId = endBinId + 1;
    }
    return response;
  }
  /**
   * Creates multiple positions and adds liquidity by strategy without chainsaw issues.
   * @param positionKeypairGenerator A function that generates a specified number of keypairs.
   * @param totalXAmount The total amount of token X to be added.
   * @param totalYAmount The total amount of token Y to be added.
   * @param strategy The strategy for adding liquidity.
   * @param owner The owner of the position.
   * @param payer The payer of the transaction.
   * @param slippagePercentage The slippage percentage for adding liquidity.
   * @returns An object with two properties: `initPositionIxs` and `addLiquidityIxs`.
   */
  async initializeMultiplePositionAndAddLiquidityByStrategy(positionKeypairGenerator, totalXAmount, totalYAmount, strategy, owner, payer, slippagePercentage) {
    const maxActiveBinSlippage = getAndCapMaxActiveBinSlippage(
      slippagePercentage,
      this.lbPair.binStep,
      MAX_ACTIVE_BIN_SLIPPAGE
    );
    const { minBinId, maxBinId } = strategy;
    const binCount = getBinCount(minBinId, maxBinId);
    const positionCount = getPositionCountByBinCount(binCount);
    const positionKeypairs = await positionKeypairGenerator(positionCount);
    const liquidityStrategyParameters = buildLiquidityStrategyParameters(
      totalXAmount,
      totalYAmount,
      new BN24(minBinId - this.lbPair.activeId),
      new BN24(maxBinId - this.lbPair.activeId),
      new BN24(this.lbPair.binStep),
      strategy.singleSidedX,
      new BN24(this.lbPair.activeId),
      getLiquidityStrategyParameterBuilder(strategy.strategyType)
    );
    const instructionsByPositions = [];
    let startBinId = minBinId;
    const initializeAtaIxs = [];
    if (!this.tokenX.publicKey.equals(NATIVE_MINT2)) {
      const ownerAtaX = getAssociatedTokenAddressSync2(
        this.tokenX.publicKey,
        owner,
        true,
        this.tokenX.owner
      );
      initializeAtaIxs.push(
        createAssociatedTokenAccountIdempotentInstruction2(
          owner,
          ownerAtaX,
          owner,
          this.tokenX.publicKey,
          this.tokenX.owner
        )
      );
    }
    if (!this.tokenY.publicKey.equals(NATIVE_MINT2)) {
      const ownerAtaY = getAssociatedTokenAddressSync2(
        this.tokenY.publicKey,
        owner,
        true,
        this.tokenY.owner
      );
      initializeAtaIxs.push(
        createAssociatedTokenAccountIdempotentInstruction2(
          owner,
          ownerAtaY,
          owner,
          this.tokenY.publicKey,
          this.tokenY.owner
        )
      );
    }
    for (const position of positionKeypairs) {
      const endBinId = Math.min(
        startBinId + MAX_BINS_PER_POSITION.toNumber() - 1,
        maxBinId
      );
      const binCount2 = getBinCount(startBinId, endBinId);
      const positionWidth = Math.min(
        binCount2,
        DEFAULT_BIN_PER_POSITION.toNumber()
      );
      const initPositionIx = await this.program.methods.initializePosition(startBinId, positionWidth).accountsPartial({
        position: position.publicKey,
        lbPair: this.pubkey,
        owner,
        payer,
        rent: SYSVAR_RENT_PUBKEY2
      }).instruction();
      const chunkedAddLiquidityIx = await chunkDepositWithRebalanceEndpoint(
        this,
        strategy,
        slippagePercentage,
        maxActiveBinSlippage,
        position.publicKey,
        startBinId,
        endBinId,
        liquidityStrategyParameters,
        owner,
        payer,
        false,
        this.opt?.skipSolWrappingOperation
      );
      instructionsByPositions.push({
        positionKeypair: position,
        initializePositionIx: initPositionIx,
        initializeAtaIxs,
        addLiquidityIxs: chunkedAddLiquidityIx
      });
      startBinId = endBinId + 1;
    }
    return {
      instructionsByPositions
    };
  }
  /**
   * Adds liquidity to an existing position using a specified strategy, allowing for chunkable transactions.
   * If adding liquidity to bin out of position range, it will automatically expand. The limitation is 70 bins.
   *
   * @param {TInitializePositionAndAddLiquidityParamsByStrategy} params - The parameters required for adding liquidity.
   * @param {PublicKey} params.positionPubKey - The public key of the position to which liquidity is being added.
   * @param {BN} params.totalXAmount - The total amount of token X to be added as liquidity.
   * @param {BN} params.totalYAmount - The total amount of token Y to be added as liquidity.
   * @param {StrategyParameters} params.strategy - The strategy parameters for adding liquidity.
   * @param {PublicKey} params.user - The public key of the user adding liquidity.
   * @param {number} params.slippage - The slippage percentage allowed for the transaction.
   *
   * @returns {Promise<Transaction[]>} A promise that resolves to an array of transactions for adding liquidity.
   */
  async addLiquidityByStrategyChunkable({
    positionPubKey,
    totalXAmount,
    totalYAmount,
    strategy,
    user,
    slippage
  }) {
    const maxActiveBinSlippage = getAndCapMaxActiveBinSlippage(
      slippage,
      this.lbPair.binStep,
      MAX_ACTIVE_BIN_SLIPPAGE
    );
    const { minBinId, maxBinId } = strategy;
    const liquidityStrategyParameters = buildLiquidityStrategyParameters(
      totalXAmount,
      totalYAmount,
      new BN24(minBinId - this.lbPair.activeId),
      new BN24(maxBinId - this.lbPair.activeId),
      new BN24(this.lbPair.binStep),
      strategy.singleSidedX,
      new BN24(this.lbPair.activeId),
      getLiquidityStrategyParameterBuilder(strategy.strategyType)
    );
    const chunkedAddLiquidityIx = await chunkDepositWithRebalanceEndpoint(
      this,
      strategy,
      slippage,
      maxActiveBinSlippage,
      positionPubKey,
      minBinId,
      maxBinId,
      liquidityStrategyParameters,
      user,
      user,
      true,
      this.opt?.skipSolWrappingOperation
    );
    const latestBlockhashInfo = await this.program.provider.connection.getLatestBlockhash();
    return chunkedAddLiquidityIx.map((ixs) => {
      return new Transaction({
        ...latestBlockhashInfo,
        feePayer: user
      }).add(...ixs);
    });
  }
  /**
   * The function `initializePositionAndAddLiquidityByStrategy` function is used to initializes a position and adds liquidity
   * @param {TInitializePositionAndAddLiquidityParamsByStrategy}
   *    - `positionPubKey`: The public key of the position account. (usually use `new Keypair()`)
   *    - `totalXAmount`: The total amount of token X to be added to the liquidity pool.
   *    - `totalYAmount`: The total amount of token Y to be added to the liquidity pool.
   *    - `strategy`: The strategy parameters to be used for the liquidity pool (Can use `calculateStrategyParameter` to calculate).
   *    - `user`: The public key of the user account.
   *    - `slippage`: The slippage percentage to be used for the liquidity pool.
   * @returns {Promise<Transaction>} The function `initializePositionAndAddLiquidityByStrategy` returns a `Promise` that
   * resolves to either a single `Transaction` object.
   */
  async initializePositionAndAddLiquidityByStrategy({
    positionPubKey,
    totalXAmount,
    totalYAmount,
    strategy,
    user,
    slippage
  }) {
    const { maxBinId, minBinId } = strategy;
    const maxActiveBinSlippage = slippage ? Math.ceil(slippage / (this.lbPair.binStep / 100)) : MAX_ACTIVE_BIN_SLIPPAGE;
    const preInstructions = [];
    const initializePositionIx = await this.program.methods.initializePosition(minBinId, maxBinId - minBinId + 1).accountsPartial({
      payer: user,
      position: positionPubKey,
      lbPair: this.pubkey,
      owner: user,
      rent: SYSVAR_RENT_PUBKEY2
    }).instruction();
    preInstructions.push(initializePositionIx);
    const binArrayIndexes = getBinArrayIndexesCoverage(
      new BN24(minBinId),
      new BN24(maxBinId)
    );
    const binArrayAccountMetas = getBinArrayAccountMetasCoverage(
      new BN24(minBinId),
      new BN24(maxBinId),
      this.pubkey,
      this.program.programId
    );
    const createBinArrayIxs = await this.createBinArraysIfNeeded(
      binArrayIndexes,
      user
    );
    preInstructions.push(...createBinArrayIxs);
    const [
      { ataPubKey: userTokenX, ix: createPayerTokenXIx },
      { ataPubKey: userTokenY, ix: createPayerTokenYIx }
    ] = await Promise.all([
      getOrCreateATAInstruction(
        this.program.provider.connection,
        this.tokenX.publicKey,
        user,
        this.tokenX.owner
      ),
      getOrCreateATAInstruction(
        this.program.provider.connection,
        this.tokenY.publicKey,
        user,
        this.tokenY.owner
      )
    ]);
    createPayerTokenXIx && preInstructions.push(createPayerTokenXIx);
    createPayerTokenYIx && preInstructions.push(createPayerTokenYIx);
    if (this.tokenX.publicKey.equals(NATIVE_MINT2) && !totalXAmount.isZero() && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        user,
        userTokenX,
        BigInt(totalXAmount.toString())
      );
      preInstructions.push(...wrapSOLIx);
    }
    if (this.tokenY.publicKey.equals(NATIVE_MINT2) && !totalYAmount.isZero() && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        user,
        userTokenY,
        BigInt(totalYAmount.toString())
      );
      preInstructions.push(...wrapSOLIx);
    }
    const postInstructions = [];
    if ([
      this.tokenX.publicKey.toBase58(),
      this.tokenY.publicKey.toBase58()
    ].includes(NATIVE_MINT2.toBase58()) && !this.opt?.skipSolWrappingOperation) {
      const closeWrappedSOLIx = await unwrapSOLInstruction(user);
      closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
    }
    const minBinArrayIndex = binIdToBinArrayIndex(new BN24(minBinId));
    const maxBinArrayIndex = binIdToBinArrayIndex(new BN24(maxBinId));
    const useExtension = isOverflowDefaultBinArrayBitmap(minBinArrayIndex) || isOverflowDefaultBinArrayBitmap(maxBinArrayIndex);
    const binArrayBitmapExtension = useExtension ? deriveBinArrayBitmapExtension(this.pubkey, this.program.programId)[0] : null;
    const activeId = this.lbPair.activeId;
    const strategyParameters = toStrategyParameters(strategy);
    const liquidityParams = {
      amountX: totalXAmount,
      amountY: totalYAmount,
      activeId,
      maxActiveBinSlippage,
      strategyParameters
    };
    const addLiquidityAccounts = {
      position: positionPubKey,
      lbPair: this.pubkey,
      userTokenX,
      userTokenY,
      reserveX: this.lbPair.reserveX,
      reserveY: this.lbPair.reserveY,
      tokenXMint: this.lbPair.tokenXMint,
      tokenYMint: this.lbPair.tokenYMint,
      binArrayBitmapExtension,
      sender: user,
      tokenXProgram: this.tokenX.owner,
      tokenYProgram: this.tokenY.owner,
      memoProgram: MEMO_PROGRAM_ID
    };
    const { slices, accounts: transferHookAccounts } = this.getPotentialToken2022IxDataAndAccounts(0 /* Liquidity */);
    const programMethod = this.program.methods.addLiquidityByStrategy2(
      liquidityParams,
      {
        slices
      }
    );
    const addLiquidityIx = await programMethod.accountsPartial(addLiquidityAccounts).remainingAccounts(transferHookAccounts).remainingAccounts(binArrayAccountMetas).instruction();
    const instructions = [
      ...preInstructions,
      addLiquidityIx,
      ...postInstructions
    ];
    const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
      this.program.provider.connection,
      instructions,
      user
    );
    instructions.unshift(setCUIx);
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      blockhash,
      lastValidBlockHeight,
      feePayer: user
    }).add(...instructions);
  }
  /**
   * @deprecated Use `initializePositionAndAddLiquidityByStrategy` instead which support both token and token2022.
   * The function `initializePositionAndAddLiquidityByWeight` function is used to initializes a position and adds liquidity
   * @param {TInitializePositionAndAddLiquidityParams}
   *    - `positionPubKey`: The public key of the position account. (usually use `new Keypair()`)
   *    - `totalXAmount`: The total amount of token X to be added to the liquidity pool.
   *    - `totalYAmount`: The total amount of token Y to be added to the liquidity pool.
   *    - `xYAmountDistribution`: An array of objects of type `XYAmountDistribution` that represents (can use `calculateSpotDistribution`, `calculateBidAskDistribution` & `calculateNormalDistribution`)
   *    - `user`: The public key of the user account.
   *    - `slippage`: The slippage percentage to be used for the liquidity pool.
   * @returns {Promise<Transaction|Transaction[]>} The function `initializePositionAndAddLiquidityByWeight` returns a `Promise` that
   * resolves to either a single `Transaction` object (if less than 26bin involved) or an array of `Transaction` objects.
   */
  async initializePositionAndAddLiquidityByWeight({
    positionPubKey,
    totalXAmount,
    totalYAmount,
    xYAmountDistribution,
    user,
    slippage
  }) {
    const { lowerBinId, upperBinId, binIds } = this.processXYAmountDistribution(xYAmountDistribution);
    const maxActiveBinSlippage = slippage ? Math.ceil(slippage / (this.lbPair.binStep / 100)) : MAX_ACTIVE_BIN_SLIPPAGE;
    if (upperBinId >= lowerBinId + DEFAULT_BIN_PER_POSITION.toNumber()) {
      throw new Error(
        `Position must be within a range of 1 to ${DEFAULT_BIN_PER_POSITION.toNumber()} bins.`
      );
    }
    const preInstructions = [];
    const initializePositionIx = await this.program.methods.initializePosition(lowerBinId, upperBinId - lowerBinId + 1).accountsPartial({
      payer: user,
      position: positionPubKey,
      lbPair: this.pubkey,
      owner: user,
      rent: SYSVAR_RENT_PUBKEY2
    }).instruction();
    preInstructions.push(initializePositionIx);
    const lowerBinArrayIndex = binIdToBinArrayIndex(new BN24(lowerBinId));
    const [binArrayLower] = deriveBinArray(
      this.pubkey,
      lowerBinArrayIndex,
      this.program.programId
    );
    const upperBinArrayIndex = BN24.max(
      lowerBinArrayIndex.add(new BN24(1)),
      binIdToBinArrayIndex(new BN24(upperBinId))
    );
    const [binArrayUpper] = deriveBinArray(
      this.pubkey,
      upperBinArrayIndex,
      this.program.programId
    );
    const createBinArrayIxs = await this.createBinArraysIfNeeded(
      [lowerBinArrayIndex, upperBinArrayIndex],
      user
    );
    preInstructions.push(...createBinArrayIxs);
    const [
      { ataPubKey: userTokenX, ix: createPayerTokenXIx },
      { ataPubKey: userTokenY, ix: createPayerTokenYIx }
    ] = await Promise.all([
      getOrCreateATAInstruction(
        this.program.provider.connection,
        this.tokenX.publicKey,
        user,
        this.tokenX.owner
      ),
      getOrCreateATAInstruction(
        this.program.provider.connection,
        this.tokenY.publicKey,
        user,
        this.tokenY.owner
      )
    ]);
    createPayerTokenXIx && preInstructions.push(createPayerTokenXIx);
    createPayerTokenYIx && preInstructions.push(createPayerTokenYIx);
    if (this.tokenX.publicKey.equals(NATIVE_MINT2) && !totalXAmount.isZero() && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        user,
        userTokenX,
        BigInt(totalXAmount.toString())
      );
      preInstructions.push(...wrapSOLIx);
    }
    if (this.tokenY.publicKey.equals(NATIVE_MINT2) && !totalYAmount.isZero() && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        user,
        userTokenY,
        BigInt(totalYAmount.toString())
      );
      preInstructions.push(...wrapSOLIx);
    }
    const postInstructions = [];
    if ([
      this.tokenX.publicKey.toBase58(),
      this.tokenY.publicKey.toBase58()
    ].includes(NATIVE_MINT2.toBase58()) && !this.opt?.skipSolWrappingOperation) {
      const closeWrappedSOLIx = await unwrapSOLInstruction(user);
      closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
    }
    const minBinId = Math.min(...binIds);
    const maxBinId = Math.max(...binIds);
    const minBinArrayIndex = binIdToBinArrayIndex(new BN24(minBinId));
    const maxBinArrayIndex = binIdToBinArrayIndex(new BN24(maxBinId));
    const useExtension = isOverflowDefaultBinArrayBitmap(minBinArrayIndex) || isOverflowDefaultBinArrayBitmap(maxBinArrayIndex);
    const binArrayBitmapExtension = useExtension ? deriveBinArrayBitmapExtension(this.pubkey, this.program.programId)[0] : null;
    const activeId = this.lbPair.activeId;
    const binLiquidityDist = toWeightDistribution(
      totalXAmount,
      totalYAmount,
      xYAmountDistribution.map((item) => ({
        binId: item.binId,
        xAmountBpsOfTotal: item.xAmountBpsOfTotal,
        yAmountBpsOfTotal: item.yAmountBpsOfTotal
      })),
      this.lbPair.binStep
    );
    if (binLiquidityDist.length === 0) {
      throw new Error("No liquidity to add");
    }
    const liquidityParams = {
      amountX: totalXAmount,
      amountY: totalYAmount,
      binLiquidityDist,
      activeId,
      maxActiveBinSlippage
    };
    const addLiquidityAccounts = {
      position: positionPubKey,
      lbPair: this.pubkey,
      userTokenX,
      userTokenY,
      reserveX: this.lbPair.reserveX,
      reserveY: this.lbPair.reserveY,
      tokenXMint: this.lbPair.tokenXMint,
      tokenYMint: this.lbPair.tokenYMint,
      binArrayLower,
      binArrayUpper,
      binArrayBitmapExtension,
      sender: user,
      tokenXProgram: TOKEN_PROGRAM_ID4,
      tokenYProgram: TOKEN_PROGRAM_ID4
    };
    const oneSideLiquidityParams = {
      amount: totalXAmount.isZero() ? totalYAmount : totalXAmount,
      activeId,
      maxActiveBinSlippage,
      binLiquidityDist
    };
    const oneSideAddLiquidityAccounts = {
      binArrayLower,
      binArrayUpper,
      lbPair: this.pubkey,
      binArrayBitmapExtension: null,
      sender: user,
      position: positionPubKey,
      reserve: totalXAmount.isZero() ? this.lbPair.reserveY : this.lbPair.reserveX,
      tokenMint: totalXAmount.isZero() ? this.lbPair.tokenYMint : this.lbPair.tokenXMint,
      tokenProgram: TOKEN_PROGRAM_ID4,
      userToken: totalXAmount.isZero() ? userTokenY : userTokenX
    };
    const isOneSideDeposit = totalXAmount.isZero() || totalYAmount.isZero();
    const programMethod = isOneSideDeposit ? this.program.methods.addLiquidityOneSide(oneSideLiquidityParams) : this.program.methods.addLiquidityByWeight(liquidityParams);
    if (xYAmountDistribution.length < MAX_BIN_LENGTH_ALLOWED_IN_ONE_TX) {
      const addLiqIx2 = await programMethod.accountsPartial(
        isOneSideDeposit ? oneSideAddLiquidityAccounts : addLiquidityAccounts
      ).instruction();
      const instructions = [...preInstructions, addLiqIx2, ...postInstructions];
      const setCUIx2 = await getEstimatedComputeUnitIxWithBuffer(
        this.program.provider.connection,
        instructions,
        user
      );
      instructions.unshift(setCUIx2);
      const { blockhash: blockhash2, lastValidBlockHeight: lastValidBlockHeight2 } = await this.program.provider.connection.getLatestBlockhash("confirmed");
      return new Transaction({
        blockhash: blockhash2,
        lastValidBlockHeight: lastValidBlockHeight2,
        feePayer: user
      }).add(...instructions);
    }
    const addLiqIx = await programMethod.accountsPartial(
      isOneSideDeposit ? oneSideAddLiquidityAccounts : addLiquidityAccounts
    ).instruction();
    const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
      this.program.provider.connection,
      [addLiqIx],
      user,
      DEFAULT_ADD_LIQUIDITY_CU
      // The function return multiple transactions that dependent on each other, simulation will fail
    );
    const mainInstructions = [setCUIx, addLiqIx];
    const transactions = [];
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    if (preInstructions.length) {
      const preInstructionsTx = new Transaction({
        blockhash,
        lastValidBlockHeight,
        feePayer: user
      }).add(...preInstructions);
      transactions.push(preInstructionsTx);
    }
    const mainTx = new Transaction({
      blockhash,
      lastValidBlockHeight,
      feePayer: user
    }).add(...mainInstructions);
    transactions.push(mainTx);
    if (postInstructions.length) {
      const postInstructionsTx = new Transaction({
        blockhash,
        lastValidBlockHeight,
        feePayer: user
      }).add(...postInstructions);
      transactions.push(postInstructionsTx);
    }
    return transactions;
  }
  /**
   * The `addLiquidityByStrategy` function is used to add liquidity to existing position
   * @param {TInitializePositionAndAddLiquidityParamsByStrategy}
   *    - `positionPubKey`: The public key of the position account. (usually use `new Keypair()`)
   *    - `totalXAmount`: The total amount of token X to be added to the liquidity pool.
   *    - `totalYAmount`: The total amount of token Y to be added to the liquidity pool.
   *    - `strategy`: The strategy parameters to be used for the liquidity pool (Can use `calculateStrategyParameter` to calculate).
   *    - `user`: The public key of the user account.
   *    - `slippage`: The slippage percentage to be used for the liquidity pool.
   * @returns {Promise<Transaction>} The function `addLiquidityByWeight` returns a `Promise` that resolves to either a single
   * `Transaction` object
   */
  async addLiquidityByStrategy({
    positionPubKey,
    totalXAmount,
    totalYAmount,
    strategy,
    user,
    slippage
  }) {
    const { maxBinId, minBinId } = strategy;
    const maxActiveBinSlippage = slippage ? Math.ceil(slippage / (this.lbPair.binStep / 100)) : MAX_ACTIVE_BIN_SLIPPAGE;
    const preInstructions = [];
    const minBinArrayIndex = binIdToBinArrayIndex(new BN24(minBinId));
    const maxBinArrayIndex = binIdToBinArrayIndex(new BN24(maxBinId));
    const useExtension = isOverflowDefaultBinArrayBitmap(minBinArrayIndex) || isOverflowDefaultBinArrayBitmap(maxBinArrayIndex);
    const binArrayBitmapExtension = useExtension ? deriveBinArrayBitmapExtension(this.pubkey, this.program.programId)[0] : null;
    const strategyParameters = toStrategyParameters(strategy);
    const binArrayIndexes = getBinArrayIndexesCoverage(
      new BN24(minBinId),
      new BN24(maxBinId)
    );
    const binArrayAccountsMeta = getBinArrayAccountMetasCoverage(
      new BN24(minBinId),
      new BN24(maxBinId),
      this.pubkey,
      this.program.programId
    );
    const createBinArrayIxs = await this.createBinArraysIfNeeded(
      binArrayIndexes,
      user
    );
    preInstructions.push(...createBinArrayIxs);
    const [
      { ataPubKey: userTokenX, ix: createPayerTokenXIx },
      { ataPubKey: userTokenY, ix: createPayerTokenYIx }
    ] = await Promise.all([
      getOrCreateATAInstruction(
        this.program.provider.connection,
        this.tokenX.publicKey,
        user,
        this.tokenX.owner
      ),
      getOrCreateATAInstruction(
        this.program.provider.connection,
        this.tokenY.publicKey,
        user,
        this.tokenY.owner
      )
    ]);
    createPayerTokenXIx && preInstructions.push(createPayerTokenXIx);
    createPayerTokenYIx && preInstructions.push(createPayerTokenYIx);
    if (this.tokenX.publicKey.equals(NATIVE_MINT2) && !totalXAmount.isZero() && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        user,
        userTokenX,
        BigInt(totalXAmount.toString())
      );
      preInstructions.push(...wrapSOLIx);
    }
    if (this.tokenY.publicKey.equals(NATIVE_MINT2) && !totalYAmount.isZero() && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        user,
        userTokenY,
        BigInt(totalYAmount.toString())
      );
      preInstructions.push(...wrapSOLIx);
    }
    const postInstructions = [];
    if ([
      this.tokenX.publicKey.toBase58(),
      this.tokenY.publicKey.toBase58()
    ].includes(NATIVE_MINT2.toBase58()) && !this.opt?.skipSolWrappingOperation) {
      const closeWrappedSOLIx = await unwrapSOLInstruction(user);
      closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
    }
    const liquidityParams = {
      amountX: totalXAmount,
      amountY: totalYAmount,
      activeId: this.lbPair.activeId,
      maxActiveBinSlippage,
      strategyParameters
    };
    const addLiquidityAccounts = {
      position: positionPubKey,
      lbPair: this.pubkey,
      userTokenX,
      userTokenY,
      reserveX: this.lbPair.reserveX,
      reserveY: this.lbPair.reserveY,
      tokenXMint: this.lbPair.tokenXMint,
      tokenYMint: this.lbPair.tokenYMint,
      binArrayBitmapExtension,
      sender: user,
      tokenXProgram: this.tokenX.owner,
      tokenYProgram: this.tokenY.owner,
      memoProgram: MEMO_PROGRAM_ID
    };
    const { slices, accounts: transferHookAccounts } = this.getPotentialToken2022IxDataAndAccounts(0 /* Liquidity */);
    const programMethod = this.program.methods.addLiquidityByStrategy2(
      liquidityParams,
      {
        slices
      }
    );
    const addLiquidityIx = await programMethod.accounts(addLiquidityAccounts).remainingAccounts(transferHookAccounts).remainingAccounts(binArrayAccountsMeta).instruction();
    const instructions = [
      ...preInstructions,
      addLiquidityIx,
      ...postInstructions
    ];
    const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
      this.program.provider.connection,
      instructions,
      user
    );
    instructions.unshift(setCUIx);
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      blockhash,
      lastValidBlockHeight,
      feePayer: user
    }).add(...instructions);
  }
  /**
   * The `addLiquidityByWeight2` function is used to add liquidity to existing position
   * @param {TInitializePositionAndAddLiquidityParams}
   *    - `positionPubKey`: The public key of the position account. (usually use `new Keypair()`)
   *    - `totalXAmount`: The total amount of token X to be added to the liquidity pool.
   *    - `totalYAmount`: The total amount of token Y to be added to the liquidity pool.
   *    - `xYAmountDistribution`: An array of objects of type `XYAmountDistribution` that represents (can use `calculateSpotDistribution`, `calculateBidAskDistribution` & `calculateNormalDistribution`)
   *    - `user`: The public key of the user account.
   *    - `slippage`: The slippage percentage to be used for the liquidity pool.
   *    - `binPerChunk`: The number of bins per chunk when chunking into multiple transactions
   * @returns {Promise<Transaction[]>} The function `addLiquidityByWeight2` returns a `Promise` that resolves to transactions
   */
  async addLiquidityByWeight2({
    positionPubKey,
    totalXAmount,
    totalYAmount,
    xYAmountDistribution,
    user,
    slippage
  }, binPerChunk) {
    const maxActiveBinSlippage = slippage ? Math.ceil(slippage / (this.lbPair.binStep / 100)) : MAX_ACTIVE_BIN_SLIPPAGE;
    const positionAccount = await this.program.account.positionV2.fetch(positionPubKey);
    const { lowerBinId, upperBinId, binIds } = this.processXYAmountDistribution(xYAmountDistribution);
    if (lowerBinId < positionAccount.lowerBinId)
      throw new Error(
        `Lower Bin ID (${lowerBinId}) lower than Position Lower Bin Id (${positionAccount.lowerBinId})`
      );
    if (upperBinId > positionAccount.upperBinId)
      throw new Error(
        `Upper Bin ID (${upperBinId}) higher than Position Upper Bin Id (${positionAccount.upperBinId})`
      );
    const userTokenX = getAssociatedTokenAddressSync2(
      this.tokenX.mint.address,
      user,
      true,
      this.tokenX.owner
    );
    const userTokenY = getAssociatedTokenAddressSync2(
      this.tokenY.mint.address,
      user,
      true,
      this.tokenY.owner
    );
    const createUserTokenXIx = createAssociatedTokenAccountIdempotentInstruction2(
      user,
      userTokenX,
      user,
      this.lbPair.tokenXMint,
      this.tokenX.owner
    );
    const createUserTokenYIx = createAssociatedTokenAccountIdempotentInstruction2(
      user,
      userTokenY,
      user,
      this.lbPair.tokenYMint,
      this.tokenY.owner
    );
    const fromBinId = Math.min(...binIds);
    const toBinId = Math.max(...binIds);
    const chunkedBinRange = chunkBinRange(fromBinId, toBinId, binPerChunk);
    const groupedInstructions = [];
    for (const { lowerBinId: lowerBinId2, upperBinId: upperBinId2 } of chunkedBinRange) {
      const binArrayAccountsMeta = getBinArrayAccountMetasCoverage(
        new BN24(lowerBinId2),
        new BN24(upperBinId2),
        this.pubkey,
        this.program.programId
      );
      const lowerBinArrayIndex = binIdToBinArrayIndex(new BN24(lowerBinId2));
      const upperBinArrayIndex = binIdToBinArrayIndex(new BN24(upperBinId2));
      const useExtension = isOverflowDefaultBinArrayBitmap(lowerBinArrayIndex) || isOverflowDefaultBinArrayBitmap(upperBinArrayIndex);
      const binArrayBitmapExtension = useExtension ? deriveBinArrayBitmapExtension(this.pubkey, this.program.programId)[0] : null;
      const { slices, accounts: transferHookAccounts } = this.getPotentialToken2022IxDataAndAccounts(0 /* Liquidity */);
      const binCount = upperBinId2 - lowerBinId2 + 1;
      const chunkedXYAmountDistribution = xYAmountDistribution.splice(
        0,
        binCount
      );
      const chunkedQuoteDistribution = [];
      let totalChunkedXAmount = new BN24(0);
      let totalChunkedYAmount = new BN24(0);
      let totalYValue = new BN24(0);
      for (let i = 0; i < chunkedXYAmountDistribution.length; i++) {
        const distribution = chunkedXYAmountDistribution[i];
        const yAmount = totalYAmount.mul(distribution.yAmountBpsOfTotal).div(new BN24(BASIS_POINT_MAX));
        const xAmount = totalXAmount.mul(distribution.xAmountBpsOfTotal).div(new BN24(BASIS_POINT_MAX));
        const binPrice = getQPriceFromId(
          new BN24(distribution.binId),
          new BN24(this.lbPair.binStep)
        );
        const yValueOfX = totalXAmount.mul(distribution.xAmountBpsOfTotal).mul(binPrice).shrn(SCALE_OFFSET).div(new BN24(BASIS_POINT_MAX));
        totalChunkedXAmount = totalChunkedXAmount.add(xAmount);
        totalChunkedYAmount = totalChunkedYAmount.add(yAmount);
        totalYValue = totalYValue.add(yAmount.add(yValueOfX));
        chunkedQuoteDistribution.push({
          binId: distribution.binId,
          yValue: yValueOfX.add(yAmount)
        });
      }
      const chunkedBinLiquidityDistribution = chunkedQuoteDistribution.map(
        ({ binId, yValue }) => {
          const weight = yValue.mul(new BN24(65535)).div(totalYValue);
          return {
            binId,
            weight: weight.toNumber()
          };
        }
      );
      const preInstructions = [
        createUserTokenXIx,
        createUserTokenYIx
      ];
      const postInstructions = [];
      const createBinArrayIxs = await this.createBinArraysIfNeeded(
        [lowerBinArrayIndex, upperBinArrayIndex],
        user
      );
      preInstructions.push(...createBinArrayIxs);
      if (this.tokenX.publicKey.equals(NATIVE_MINT2) && !totalChunkedXAmount.isZero() && !this.opt?.skipSolWrappingOperation) {
        const wrapSOLIx = wrapSOLInstruction(
          user,
          userTokenX,
          BigInt(totalChunkedXAmount.toString())
        );
        preInstructions.push(...wrapSOLIx);
        const closeWrappedSOLIx = await unwrapSOLInstruction(user);
        closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
      }
      if (this.tokenY.publicKey.equals(NATIVE_MINT2) && !totalChunkedYAmount.isZero() && !this.opt?.skipSolWrappingOperation) {
        const wrapSOLIx = wrapSOLInstruction(
          user,
          userTokenY,
          BigInt(totalChunkedYAmount.toString())
        );
        preInstructions.push(...wrapSOLIx);
        const closeWrappedSOLIx = await unwrapSOLInstruction(user);
        closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
      }
      const addLiqIx = await this.program.methods.addLiquidityByWeight2(
        {
          amountX: totalChunkedXAmount,
          amountY: totalChunkedYAmount,
          activeId: this.lbPair.activeId,
          maxActiveBinSlippage,
          binLiquidityDist: chunkedBinLiquidityDistribution
        },
        {
          slices
        }
      ).accountsPartial({
        position: positionPubKey,
        lbPair: this.pubkey,
        userTokenX,
        userTokenY,
        reserveX: this.lbPair.reserveX,
        reserveY: this.lbPair.reserveY,
        tokenXMint: this.lbPair.tokenXMint,
        tokenYMint: this.lbPair.tokenYMint,
        sender: user,
        tokenXProgram: this.tokenX.owner,
        tokenYProgram: this.tokenY.owner,
        binArrayBitmapExtension
      }).remainingAccounts([...transferHookAccounts, ...binArrayAccountsMeta]).instruction();
      const instruction = [...preInstructions, addLiqIx, ...postInstructions];
      groupedInstructions.push(instruction);
    }
    const groupedInstructionsWithCUIx = await Promise.all(
      groupedInstructions.map(async (ixs) => {
        const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
          this.program.provider.connection,
          ixs,
          user,
          0.3
          // Extra 30% buffer CU
        );
        return [setCUIx, ...ixs];
      })
    );
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return groupedInstructionsWithCUIx.map((ixs) => {
      return new Transaction({
        blockhash,
        lastValidBlockHeight,
        feePayer: user
      }).add(...ixs);
    });
  }
  /**
   * @deprecated Use `addLiquidityByStrategy` instead which support both token and token2022.
   * The `addLiquidityByWeight` function is used to add liquidity to existing position
   * @param {TInitializePositionAndAddLiquidityParams}
   *    - `positionPubKey`: The public key of the position account. (usually use `new Keypair()`)
   *    - `totalXAmount`: The total amount of token X to be added to the liquidity pool.
   *    - `totalYAmount`: The total amount of token Y to be added to the liquidity pool.
   *    - `xYAmountDistribution`: An array of objects of type `XYAmountDistribution` that represents (can use `calculateSpotDistribution`, `calculateBidAskDistribution` & `calculateNormalDistribution`)
   *    - `user`: The public key of the user account.
   *    - `slippage`: The slippage percentage to be used for the liquidity pool.
   * @returns {Promise<Transaction|Transaction[]>} The function `addLiquidityByWeight` returns a `Promise` that resolves to either a single
   * `Transaction` object (if less than 26bin involved) or an array of `Transaction` objects.
   */
  async addLiquidityByWeight({
    positionPubKey,
    totalXAmount,
    totalYAmount,
    xYAmountDistribution,
    user,
    slippage
  }) {
    const maxActiveBinSlippage = slippage ? Math.ceil(slippage / (this.lbPair.binStep / 100)) : MAX_ACTIVE_BIN_SLIPPAGE;
    const positionAccount = await this.program.account.positionV2.fetch(positionPubKey);
    const { lowerBinId, upperBinId, binIds } = this.processXYAmountDistribution(xYAmountDistribution);
    if (lowerBinId < positionAccount.lowerBinId)
      throw new Error(
        `Lower Bin ID (${lowerBinId}) lower than Position Lower Bin Id (${positionAccount.lowerBinId})`
      );
    if (upperBinId > positionAccount.upperBinId)
      throw new Error(
        `Upper Bin ID (${upperBinId}) higher than Position Upper Bin Id (${positionAccount.upperBinId})`
      );
    const minBinId = Math.min(...binIds);
    const maxBinId = Math.max(...binIds);
    const minBinArrayIndex = binIdToBinArrayIndex(new BN24(minBinId));
    const maxBinArrayIndex = binIdToBinArrayIndex(new BN24(maxBinId));
    const useExtension = isOverflowDefaultBinArrayBitmap(minBinArrayIndex) || isOverflowDefaultBinArrayBitmap(maxBinArrayIndex);
    const binArrayBitmapExtension = useExtension ? deriveBinArrayBitmapExtension(this.pubkey, this.program.programId)[0] : null;
    const activeId = this.lbPair.activeId;
    const binLiquidityDist = toWeightDistribution(
      totalXAmount,
      totalYAmount,
      xYAmountDistribution.map((item) => ({
        binId: item.binId,
        xAmountBpsOfTotal: item.xAmountBpsOfTotal,
        yAmountBpsOfTotal: item.yAmountBpsOfTotal
      })),
      this.lbPair.binStep
    );
    if (binLiquidityDist.length === 0) {
      throw new Error("No liquidity to add");
    }
    const lowerBinArrayIndex = binIdToBinArrayIndex(
      new BN24(positionAccount.lowerBinId)
    );
    const [binArrayLower] = deriveBinArray(
      this.pubkey,
      lowerBinArrayIndex,
      this.program.programId
    );
    const upperBinArrayIndex = BN24.max(
      lowerBinArrayIndex.add(new BN24(1)),
      binIdToBinArrayIndex(new BN24(positionAccount.upperBinId))
    );
    const [binArrayUpper] = deriveBinArray(
      this.pubkey,
      upperBinArrayIndex,
      this.program.programId
    );
    const preInstructions = [];
    const createBinArrayIxs = await this.createBinArraysIfNeeded(
      [lowerBinArrayIndex, upperBinArrayIndex],
      user
    );
    preInstructions.push(...createBinArrayIxs);
    const [
      { ataPubKey: userTokenX, ix: createPayerTokenXIx },
      { ataPubKey: userTokenY, ix: createPayerTokenYIx }
    ] = await Promise.all([
      getOrCreateATAInstruction(
        this.program.provider.connection,
        this.tokenX.publicKey,
        user,
        this.tokenX.owner
      ),
      getOrCreateATAInstruction(
        this.program.provider.connection,
        this.tokenY.publicKey,
        user,
        this.tokenY.owner
      )
    ]);
    createPayerTokenXIx && preInstructions.push(createPayerTokenXIx);
    createPayerTokenYIx && preInstructions.push(createPayerTokenYIx);
    if (this.tokenX.publicKey.equals(NATIVE_MINT2) && !totalXAmount.isZero() && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        user,
        userTokenX,
        BigInt(totalXAmount.toString())
      );
      preInstructions.push(...wrapSOLIx);
    }
    if (this.tokenY.publicKey.equals(NATIVE_MINT2) && !totalYAmount.isZero() && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        user,
        userTokenY,
        BigInt(totalYAmount.toString())
      );
      preInstructions.push(...wrapSOLIx);
    }
    const postInstructions = [];
    if ([
      this.tokenX.publicKey.toBase58(),
      this.tokenY.publicKey.toBase58()
    ].includes(NATIVE_MINT2.toBase58()) && !this.opt?.skipSolWrappingOperation) {
      const closeWrappedSOLIx = await unwrapSOLInstruction(user);
      closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
    }
    const liquidityParams = {
      amountX: totalXAmount,
      amountY: totalYAmount,
      binLiquidityDist,
      activeId,
      maxActiveBinSlippage
    };
    const addLiquidityAccounts = {
      position: positionPubKey,
      lbPair: this.pubkey,
      userTokenX,
      userTokenY,
      reserveX: this.lbPair.reserveX,
      reserveY: this.lbPair.reserveY,
      tokenXMint: this.lbPair.tokenXMint,
      tokenYMint: this.lbPair.tokenYMint,
      binArrayLower,
      binArrayUpper,
      binArrayBitmapExtension,
      sender: user,
      tokenXProgram: TOKEN_PROGRAM_ID4,
      tokenYProgram: TOKEN_PROGRAM_ID4
    };
    const oneSideLiquidityParams = {
      amount: totalXAmount.isZero() ? totalYAmount : totalXAmount,
      activeId,
      maxActiveBinSlippage,
      binLiquidityDist
    };
    const oneSideAddLiquidityAccounts = {
      binArrayLower,
      binArrayUpper,
      lbPair: this.pubkey,
      binArrayBitmapExtension: null,
      sender: user,
      position: positionPubKey,
      reserve: totalXAmount.isZero() ? this.lbPair.reserveY : this.lbPair.reserveX,
      tokenMint: totalXAmount.isZero() ? this.lbPair.tokenYMint : this.lbPair.tokenXMint,
      tokenProgram: TOKEN_PROGRAM_ID4,
      userToken: totalXAmount.isZero() ? userTokenY : userTokenX
    };
    const isOneSideDeposit = totalXAmount.isZero() || totalYAmount.isZero();
    const programMethod = isOneSideDeposit ? this.program.methods.addLiquidityOneSide(oneSideLiquidityParams) : this.program.methods.addLiquidityByWeight(liquidityParams);
    if (xYAmountDistribution.length < MAX_BIN_LENGTH_ALLOWED_IN_ONE_TX) {
      const addLiqIx2 = await programMethod.accountsPartial(
        isOneSideDeposit ? oneSideAddLiquidityAccounts : addLiquidityAccounts
      ).instruction();
      const instructions = [...preInstructions, addLiqIx2, ...postInstructions];
      const setCUIx2 = await getEstimatedComputeUnitIxWithBuffer(
        this.program.provider.connection,
        instructions,
        user
      );
      instructions.unshift(setCUIx2);
      const { blockhash: blockhash2, lastValidBlockHeight: lastValidBlockHeight2 } = await this.program.provider.connection.getLatestBlockhash("confirmed");
      return new Transaction({
        blockhash: blockhash2,
        lastValidBlockHeight: lastValidBlockHeight2,
        feePayer: user
      }).add(...instructions);
    }
    const addLiqIx = await programMethod.accountsPartial(
      isOneSideDeposit ? oneSideAddLiquidityAccounts : addLiquidityAccounts
    ).instruction();
    const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
      this.program.provider.connection,
      [addLiqIx],
      user
    );
    const mainInstructions = [setCUIx, addLiqIx];
    const transactions = [];
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    if (preInstructions.length) {
      const preInstructionsTx = new Transaction({
        blockhash,
        lastValidBlockHeight,
        feePayer: user
      }).add(...preInstructions);
      transactions.push(preInstructionsTx);
    }
    const mainTx = new Transaction({
      blockhash,
      lastValidBlockHeight,
      feePayer: user
    }).add(...mainInstructions);
    transactions.push(mainTx);
    if (postInstructions.length) {
      const postInstructionsTx = new Transaction({
        blockhash,
        lastValidBlockHeight,
        feePayer: user
      }).add(...postInstructions);
      transactions.push(postInstructionsTx);
    }
    return transactions;
  }
  /**
   * The `removeLiquidity` function is used to remove liquidity from a position,
   * with the option to claim rewards and close the position.
   * @param
   *    - `user`: The public key of the user account.
   *    - `position`: The public key of the position account.
   *    - `fromBinId`: The ID of the starting bin to remove liquidity from. Must within position range.
   *    - `toBinId`: The ID of the ending bin to remove liquidity from. Must within position range.
   *    - `liquiditiesBpsToRemove`: An array of numbers (percentage) that represent the liquidity to remove from each bin.
   *    - `shouldClaimAndClose`: A boolean flag that indicates whether to claim rewards and close the position.
   *    - `skipUnwrapSOL`: A boolean flag that indicates whether to skip unwrapping SOL. Enable this when using zap-sdk to ensure accuracy in SOL zap out amount when SOL is in token
   * @returns {Promise<Transaction[]>}
   */
  async removeLiquidity({
    user,
    position,
    fromBinId,
    toBinId,
    bps,
    shouldClaimAndClose = false,
    skipUnwrapSOL = false
  }) {
    const positionAccount = await this.program.provider.connection.getAccountInfo(position);
    const positionState = wrapPosition(this.program, position, positionAccount);
    const lbPair = positionState.lbPair();
    const owner = positionState.owner();
    const feeOwner = positionState.feeOwner();
    const liquidityShares = positionState.liquidityShares();
    const feeInfos = positionState.feeInfos();
    const rewardInfos = positionState.rewardInfos();
    const binDataWithBinId = liquidityShares.map((share, i) => {
      const feeInfo = feeInfos[i];
      const rewardInfo = rewardInfos[i];
      const hasFees = feeInfo && (!feeInfo.feeXPending.isZero() || !feeInfo.feeYPending.isZero());
      const hasRewards = rewardInfo && rewardInfo.rewardPendings.some((pending) => !pending.isZero());
      return {
        share,
        binId: positionState.lowerBinId().add(new BN24(i)),
        hasFeesOrRewards: hasFees || hasRewards
      };
    });
    const binIdsWithLiquidity = binDataWithBinId.filter((bin) => {
      return !bin.share.isZero();
    });
    const binIdsWithLiquidityOrFees = binDataWithBinId.filter((bin) => {
      return !bin.share.isZero() || bin.hasFeesOrRewards;
    });
    const hasLiquidity = binIdsWithLiquidity.length > 0;
    if (!hasLiquidity && !shouldClaimAndClose) {
      throw new Error("No liquidity to remove");
    }
    const activeBins = shouldClaimAndClose ? binIdsWithLiquidityOrFees : binIdsWithLiquidity;
    const lowerActiveBinId = activeBins[0].binId.toNumber();
    const upperActiveBinId = activeBins[activeBins.length - 1].binId.toNumber();
    if (fromBinId < lowerActiveBinId) {
      fromBinId = lowerActiveBinId;
    }
    if (toBinId > upperActiveBinId) {
      toBinId = upperActiveBinId;
    }
    const walletToReceiveFee = feeOwner.equals(PublicKey10.default) ? user : feeOwner;
    const userTokenX = getAssociatedTokenAddressSync2(
      this.lbPair.tokenXMint,
      owner,
      true,
      this.tokenX.owner
    );
    const userTokenY = getAssociatedTokenAddressSync2(
      this.lbPair.tokenYMint,
      owner,
      true,
      this.tokenY.owner
    );
    const feeOwnerTokenX = getAssociatedTokenAddressSync2(
      this.lbPair.tokenXMint,
      walletToReceiveFee,
      true,
      this.tokenX.owner
    );
    const feeOwnerTokenY = getAssociatedTokenAddressSync2(
      this.lbPair.tokenYMint,
      walletToReceiveFee,
      true,
      this.tokenY.owner
    );
    const createUserTokenXIx = createAssociatedTokenAccountIdempotentInstruction2(
      user,
      userTokenX,
      owner,
      this.lbPair.tokenXMint,
      this.tokenX.owner
    );
    const createUserTokenYIx = createAssociatedTokenAccountIdempotentInstruction2(
      user,
      userTokenY,
      owner,
      this.lbPair.tokenYMint,
      this.tokenY.owner
    );
    const createFeeOwnerTokenXIx = createAssociatedTokenAccountIdempotentInstruction2(
      user,
      feeOwnerTokenX,
      walletToReceiveFee,
      this.lbPair.tokenXMint,
      this.tokenX.owner
    );
    const createFeeOwnerTokenYIx = createAssociatedTokenAccountIdempotentInstruction2(
      user,
      feeOwnerTokenY,
      walletToReceiveFee,
      this.lbPair.tokenYMint,
      this.tokenY.owner
    );
    const chunkedBinRange = chunkBinRange(fromBinId, toBinId);
    const groupedInstructions = [];
    for (const { lowerBinId, upperBinId } of chunkedBinRange) {
      const binArrayAccountsMeta = getBinArrayAccountMetasCoverage(
        new BN24(lowerBinId),
        new BN24(upperBinId),
        this.pubkey,
        this.program.programId
      );
      const { slices, accounts: transferHookAccounts } = this.getPotentialToken2022IxDataAndAccounts(0 /* Liquidity */);
      const preInstructions = [];
      const postInstructions = [];
      if (shouldClaimAndClose) {
        const claimSwapFeeIx = await this.program.methods.claimFee2(lowerBinId, upperBinId, {
          slices
        }).accountsPartial({
          lbPair: this.pubkey,
          sender: user,
          position,
          reserveX: this.lbPair.reserveX,
          reserveY: this.lbPair.reserveY,
          tokenXMint: this.tokenX.publicKey,
          tokenYMint: this.tokenY.publicKey,
          userTokenX: feeOwnerTokenX,
          userTokenY: feeOwnerTokenY,
          tokenProgramX: this.tokenX.owner,
          tokenProgramY: this.tokenY.owner,
          memoProgram: MEMO_PROGRAM_ID
        }).remainingAccounts(transferHookAccounts).remainingAccounts(binArrayAccountsMeta).instruction();
        preInstructions.push(createFeeOwnerTokenXIx);
        preInstructions.push(createFeeOwnerTokenYIx);
        postInstructions.push(claimSwapFeeIx);
        for (let i = 0; i < 2; i++) {
          const rewardInfo = this.lbPair.rewardInfos[i];
          if (!rewardInfo || rewardInfo.mint.equals(PublicKey10.default))
            continue;
          const userRewardAccount = getAssociatedTokenAddressSync2(
            rewardInfo.mint,
            user,
            true,
            this.rewards[i].owner
          );
          const createUserRewardAccountIx = createAssociatedTokenAccountIdempotentInstruction2(
            user,
            userRewardAccount,
            user,
            rewardInfo.mint,
            this.rewards[i].owner
          );
          preInstructions.push(createUserRewardAccountIx);
          const { slices: slices2, accounts: transferHookAccounts2 } = this.getPotentialToken2022IxDataAndAccounts(1 /* Reward */, i);
          const claimRewardIx = await this.program.methods.claimReward2(new BN24(i), lowerBinId, upperBinId, {
            slices: slices2
          }).accountsPartial({
            lbPair: this.pubkey,
            sender: user,
            position,
            rewardVault: rewardInfo.vault,
            rewardMint: rewardInfo.mint,
            tokenProgram: this.rewards[i].owner,
            userTokenAccount: userRewardAccount,
            memoProgram: MEMO_PROGRAM_ID
          }).remainingAccounts(transferHookAccounts2).remainingAccounts(binArrayAccountsMeta).instruction();
          postInstructions.push(claimRewardIx);
        }
        const closePositionIx = await this.program.methods.closePositionIfEmpty().accountsPartial({
          rentReceiver: owner,
          // Must be position owner
          position,
          sender: user
        }).instruction();
        postInstructions.push(closePositionIx);
      }
      if ([
        this.tokenX.publicKey.toBase58(),
        this.tokenY.publicKey.toBase58()
      ].includes(NATIVE_MINT2.toBase58()) && (!skipUnwrapSOL || !this.opt?.skipSolWrappingOperation)) {
        const closeWrappedSOLIx = await unwrapSOLInstruction(user);
        closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
      }
      preInstructions.push(createUserTokenXIx);
      preInstructions.push(createUserTokenYIx);
      const binArrayBitmapExtension = this.binArrayBitmapExtension ? this.binArrayBitmapExtension.publicKey : this.program.programId;
      const instructions = [...preInstructions];
      if (hasLiquidity) {
        const removeLiquidityTx = await this.program.methods.removeLiquidityByRange2(lowerBinId, upperBinId, bps.toNumber(), {
          slices
        }).accountsPartial({
          position,
          lbPair,
          userTokenX,
          userTokenY,
          reserveX: this.lbPair.reserveX,
          reserveY: this.lbPair.reserveY,
          tokenXMint: this.tokenX.publicKey,
          tokenYMint: this.tokenY.publicKey,
          binArrayBitmapExtension,
          tokenXProgram: this.tokenX.owner,
          tokenYProgram: this.tokenY.owner,
          sender: user,
          memoProgram: MEMO_PROGRAM_ID
        }).remainingAccounts(transferHookAccounts).remainingAccounts(binArrayAccountsMeta).instruction();
        instructions.push(removeLiquidityTx);
      }
      instructions.push(...postInstructions);
      groupedInstructions.push(instructions);
    }
    const groupedInstructionsWithCUIx = await Promise.all(
      groupedInstructions.map(async (ixs) => {
        const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
          this.program.provider.connection,
          ixs,
          user,
          0.3
          // Extra 30% buffer CU
        );
        return [setCUIx, ...ixs];
      })
    );
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return groupedInstructionsWithCUIx.map((ixs) => {
      return new Transaction({
        blockhash,
        lastValidBlockHeight,
        feePayer: user
      }).add(...ixs);
    });
  }
  /**
   * The `closePositionIfEmpty` function closes a position if it is empty. Else, it does nothing.
   */
  async closePositionIfEmpty({
    owner,
    position
  }) {
    const closePositionIfEmptyIx = await this.program.methods.closePositionIfEmpty().accountsPartial({
      rentReceiver: owner,
      position: position.publicKey,
      sender: owner
    }).instruction();
    const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
      this.program.provider.connection,
      [closePositionIfEmptyIx],
      owner
    );
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      blockhash,
      lastValidBlockHeight,
      feePayer: owner
    }).add(setCUIx, closePositionIfEmptyIx);
  }
  /**
   * The `closePosition` function closes a position
   * @param
   *    - `owner`: The public key of the owner of the position.
   *    - `position`: The public key of the position account.
   * @returns {Promise<Transaction>}
   */
  async closePosition({
    owner,
    position
  }) {
    const closePositionIx = await this.program.methods.closePosition2().accountsPartial({
      rentReceiver: owner,
      position: position.publicKey,
      sender: owner
    }).instruction();
    const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
      this.program.provider.connection,
      [closePositionIx],
      owner
    );
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      blockhash,
      lastValidBlockHeight,
      feePayer: owner
    }).add(setCUIx, closePositionIx);
  }
  /**
   * The `swapQuoteExactOut` function returns a quote for a swap
   * @param
   *    - `outAmount`: Amount of lamport to swap out
   *    - `swapForY`: Swap token X to Y when it is true, else reversed.
   *    - `allowedSlippage`: Allowed slippage for the swap. Expressed in BPS. To convert from slippage percentage to BPS unit: SLIPPAGE_PERCENTAGE * 100
   *    - `maxExtraBinArrays`: Maximum number of extra binArrays to return
   * @returns {SwapQuote}
   *    - `inAmount`: Amount of lamport to swap in
   *    - `outAmount`: Amount of lamport to swap out
   *    - `fee`: Fee amount
   *    - `protocolFee`: Protocol fee amount
   *    - `maxInAmount`: Maximum amount of lamport to swap in
   *    - `binArraysPubkey`: Array of bin arrays involved in the swap
   * @throws {DlmmSdkError}
   *
   */
  swapQuoteExactOut(outAmount, swapForY, allowedSlippage, binArrays, maxExtraBinArrays = 0) {
    const currentTimestamp = Date.now() / 1e3;
    const [inMint, outMint] = swapForY ? [this.tokenX.mint, this.tokenY.mint] : [this.tokenY.mint, this.tokenX.mint];
    let outAmountLeft = calculateTransferFeeIncludedAmount(
      outAmount,
      outMint,
      this.clock.epoch.toNumber()
    ).amount;
    if (maxExtraBinArrays < 0 || maxExtraBinArrays > MAX_EXTRA_BIN_ARRAYS) {
      throw new DlmmSdkError(
        "INVALID_MAX_EXTRA_BIN_ARRAYS",
        `maxExtraBinArrays must be a value between 0 and ${MAX_EXTRA_BIN_ARRAYS}`
      );
    }
    let vParameterClone = Object.assign({}, this.lbPair.vParameters);
    let activeId = new BN24(this.lbPair.activeId);
    const binStep = this.lbPair.binStep;
    const sParameters3 = this.lbPair.parameters;
    const supportLimitOrder = isSupportLimitOrder(this.lbPair);
    const feeOnInput = getFeeMode(this.lbPair, swapForY).feeOnInput;
    DLMM.updateReference(
      activeId.toNumber(),
      vParameterClone,
      sParameters3,
      currentTimestamp
    );
    let startBinId = activeId;
    let binArraysForSwap = /* @__PURE__ */ new Map();
    let actualInAmount = new BN24(0);
    let feeAmount = new BN24(0);
    let protocolFeeAmount = new BN24(0);
    while (!outAmountLeft.isZero()) {
      let binArrayAccountToSwap = findNextBinArrayWithLiquidity(
        swapForY,
        activeId,
        this.lbPair,
        this.binArrayBitmapExtension?.account ?? null,
        binArrays
      );
      if (binArrayAccountToSwap == null) {
        throw new DlmmSdkError(
          "SWAP_QUOTE_INSUFFICIENT_LIQUIDITY",
          "Insufficient liquidity in binArrays"
        );
      }
      binArraysForSwap.set(binArrayAccountToSwap.publicKey, true);
      if (isBinIdWithinBinArray(activeId, binArrayAccountToSwap.account.index)) {
        const bin = getBinFromBinArray(
          activeId.toNumber(),
          binArrayAccountToSwap.account
        );
        const maxOutAmount = getBinMaxAmountOut(
          bin,
          swapForY,
          supportLimitOrder
        );
        if (!maxOutAmount.isZero()) {
          DLMM.updateVolatilityAccumulator(
            vParameterClone,
            sParameters3,
            activeId.toNumber()
          );
          const { amountIn, amountOut, fee, protocolFee } = swapExactOutQuoteAtBin(
            bin,
            binStep,
            sParameters3,
            vParameterClone,
            outAmountLeft,
            swapForY,
            supportLimitOrder,
            feeOnInput
          );
          if (!amountOut.isZero()) {
            outAmountLeft = outAmountLeft.sub(amountOut);
            actualInAmount = actualInAmount.add(amountIn);
            feeAmount = feeAmount.add(fee);
            protocolFeeAmount = protocolFeeAmount.add(protocolFee);
          }
        }
      }
      if (!outAmountLeft.isZero()) {
        if (swapForY) {
          activeId = activeId.sub(new BN24(1));
        } else {
          activeId = activeId.add(new BN24(1));
        }
      }
    }
    const startPrice = getPriceOfBinByBinId(
      startBinId.toNumber(),
      this.lbPair.binStep
    );
    const endPrice = getPriceOfBinByBinId(
      activeId.toNumber(),
      this.lbPair.binStep
    );
    const priceImpact = startPrice.sub(endPrice).abs().div(startPrice).mul(new Decimal11(100));
    actualInAmount = calculateTransferFeeIncludedAmount(
      actualInAmount,
      inMint,
      this.clock.epoch.toNumber()
    ).amount;
    const maxInAmount = actualInAmount.mul(new BN24(BASIS_POINT_MAX).add(allowedSlippage)).div(new BN24(BASIS_POINT_MAX));
    if (maxExtraBinArrays > 0 && maxExtraBinArrays <= MAX_EXTRA_BIN_ARRAYS) {
      const extraBinArrays = new Array();
      while (extraBinArrays.length < maxExtraBinArrays) {
        let binArrayAccountToSwap = findNextBinArrayWithLiquidity(
          swapForY,
          activeId,
          this.lbPair,
          this.binArrayBitmapExtension?.account ?? null,
          binArrays
        );
        if (binArrayAccountToSwap == null) {
          break;
        }
        const binArrayAccountToSwapExisted = binArraysForSwap.has(
          binArrayAccountToSwap.publicKey
        );
        if (binArrayAccountToSwapExisted) {
          if (swapForY) {
            activeId = activeId.sub(new BN24(1));
          } else {
            activeId = activeId.add(new BN24(1));
          }
        } else {
          extraBinArrays.push(binArrayAccountToSwap.publicKey);
          const [lowerBinId, upperBinId] = getBinArrayLowerUpperBinId(
            binArrayAccountToSwap.account.index
          );
          if (swapForY) {
            activeId = lowerBinId.sub(new BN24(1));
          } else {
            activeId = upperBinId.add(new BN24(1));
          }
        }
      }
      extraBinArrays.forEach((binArrayPubkey) => {
        binArraysForSwap.set(binArrayPubkey, true);
      });
    }
    const binArraysPubkey = Array.from(binArraysForSwap.keys());
    return {
      inAmount: actualInAmount,
      maxInAmount,
      outAmount,
      priceImpact,
      fee: feeAmount,
      protocolFee: protocolFeeAmount,
      binArraysPubkey
    };
  }
  /**
   * The `swapQuote` function returns a quote for a swap
   * @param
   *    - `inAmount`: Amount of lamport to swap in
   *    - `swapForY`: Swap token X to Y when it is true, else reversed.
   *    - `allowedSlippage`: Allowed slippage for the swap. Expressed in BPS. To convert from slippage percentage to BPS unit: SLIPPAGE_PERCENTAGE * 100
   *    - `binArrays`: binArrays for swapQuote.
   *    - `isPartialFill`: Flag to check whether the the swapQuote is partial fill, default = false.
   *    - `maxExtraBinArrays`: Maximum number of extra binArrays to return
   * @returns {SwapQuote}
   *    - `consumedInAmount`: Amount of lamport to swap in
   *    - `outAmount`: Amount of lamport to swap out
   *    - `fee`: Fee amount
   *    - `protocolFee`: Protocol fee amount
   *    - `minOutAmount`: Minimum amount of lamport to swap out
   *    - `priceImpact`: Price impact of the swap
   *    - `binArraysPubkey`: Array of bin arrays involved in the swap
   * @throws {DlmmSdkError}
   */
  swapQuote(inAmount, swapForY, allowedSlippage, binArrays, isPartialFill, maxExtraBinArrays = 0) {
    const currentTimestamp = Date.now() / 1e3;
    if (maxExtraBinArrays < 0 || maxExtraBinArrays > MAX_EXTRA_BIN_ARRAYS) {
      throw new DlmmSdkError(
        "INVALID_MAX_EXTRA_BIN_ARRAYS",
        `maxExtraBinArrays must be a value between 0 and ${MAX_EXTRA_BIN_ARRAYS}`
      );
    }
    const [inMint, outMint] = swapForY ? [this.tokenX.mint, this.tokenY.mint] : [this.tokenY.mint, this.tokenX.mint];
    let transferFeeExcludedAmountIn = calculateTransferFeeExcludedAmount(
      inAmount,
      inMint,
      this.clock.epoch.toNumber()
    ).amount;
    let inAmountLeft = transferFeeExcludedAmountIn;
    let vParameterClone = Object.assign({}, this.lbPair.vParameters);
    let activeId = new BN24(this.lbPair.activeId);
    const binStep = this.lbPair.binStep;
    const sParameters3 = this.lbPair.parameters;
    const supportLimitOrder = isSupportLimitOrder(this.lbPair);
    const feeOnInput = getFeeMode(this.lbPair, swapForY).feeOnInput;
    DLMM.updateReference(
      activeId.toNumber(),
      vParameterClone,
      sParameters3,
      currentTimestamp
    );
    let startBin = null;
    let binArraysForSwap = /* @__PURE__ */ new Map();
    let totalOutAmount = new BN24(0);
    let feeAmount = new BN24(0);
    let protocolFeeAmount = new BN24(0);
    let lastFilledActiveBinId = activeId;
    while (!inAmountLeft.isZero()) {
      let binArrayAccountToSwap = findNextBinArrayWithLiquidity(
        swapForY,
        activeId,
        this.lbPair,
        this.binArrayBitmapExtension?.account ?? null,
        binArrays
      );
      if (binArrayAccountToSwap == null) {
        if (isPartialFill) {
          break;
        } else {
          throw new DlmmSdkError(
            "SWAP_QUOTE_INSUFFICIENT_LIQUIDITY",
            "Insufficient liquidity in binArrays for swapQuote"
          );
        }
      }
      binArraysForSwap.set(binArrayAccountToSwap.publicKey, true);
      if (isBinIdWithinBinArray(activeId, binArrayAccountToSwap.account.index)) {
        const bin = getBinFromBinArray(
          activeId.toNumber(),
          binArrayAccountToSwap.account
        );
        const maxAmountOut = getBinMaxAmountOut(
          bin,
          swapForY,
          supportLimitOrder
        );
        if (!maxAmountOut.isZero()) {
          DLMM.updateVolatilityAccumulator(
            vParameterClone,
            sParameters3,
            activeId.toNumber()
          );
          const { amountIn, amountOut, fee, protocolFee } = swapExactInQuoteAtBin(
            bin,
            binStep,
            sParameters3,
            vParameterClone,
            inAmountLeft,
            swapForY,
            supportLimitOrder,
            feeOnInput
          );
          if (!amountIn.isZero()) {
            inAmountLeft = inAmountLeft.sub(amountIn);
            totalOutAmount = totalOutAmount.add(amountOut);
            feeAmount = feeAmount.add(fee);
            protocolFeeAmount = protocolFeeAmount.add(protocolFee);
            if (!startBin) {
              startBin = bin;
            }
            lastFilledActiveBinId = activeId;
          }
        }
      }
      if (!inAmountLeft.isZero()) {
        if (swapForY) {
          activeId = activeId.sub(new BN24(1));
        } else {
          activeId = activeId.add(new BN24(1));
        }
      }
    }
    if (!startBin) {
      throw new DlmmSdkError(
        "SWAP_QUOTE_INSUFFICIENT_LIQUIDITY",
        "Insufficient liquidity"
      );
    }
    const actualInAmount = transferFeeExcludedAmountIn.sub(inAmountLeft);
    let transferFeeIncludedInAmount = calculateTransferFeeIncludedAmount(
      actualInAmount,
      inMint,
      this.clock.epoch.toNumber()
    ).amount;
    transferFeeIncludedInAmount = transferFeeIncludedInAmount.gt(inAmount) ? inAmount : transferFeeIncludedInAmount;
    const outAmountWithoutSlippage = getAmountOut(
      startBin,
      actualInAmount.sub(
        computeFeeFromAmount(
          binStep,
          sParameters3,
          vParameterClone,
          actualInAmount
        )
      ),
      swapForY
    );
    const priceImpact = new Decimal11(totalOutAmount.toString()).sub(new Decimal11(outAmountWithoutSlippage.toString())).div(new Decimal11(outAmountWithoutSlippage.toString())).mul(new Decimal11(100)).abs();
    const endPrice = getPriceOfBinByBinId(
      lastFilledActiveBinId.toNumber(),
      this.lbPair.binStep
    );
    if (maxExtraBinArrays > 0 && maxExtraBinArrays <= MAX_EXTRA_BIN_ARRAYS) {
      const extraBinArrays = new Array();
      while (extraBinArrays.length < maxExtraBinArrays) {
        let binArrayAccountToSwap = findNextBinArrayWithLiquidity(
          swapForY,
          activeId,
          this.lbPair,
          this.binArrayBitmapExtension?.account ?? null,
          binArrays
        );
        if (binArrayAccountToSwap == null) {
          break;
        }
        const binArrayAccountToSwapExisted = binArraysForSwap.has(
          binArrayAccountToSwap.publicKey
        );
        if (binArrayAccountToSwapExisted) {
          if (swapForY) {
            activeId = activeId.sub(new BN24(1));
          } else {
            activeId = activeId.add(new BN24(1));
          }
        } else {
          extraBinArrays.push(binArrayAccountToSwap.publicKey);
          const [lowerBinId, upperBinId] = getBinArrayLowerUpperBinId(
            binArrayAccountToSwap.account.index
          );
          if (swapForY) {
            activeId = lowerBinId.sub(new BN24(1));
          } else {
            activeId = upperBinId.add(new BN24(1));
          }
        }
      }
      extraBinArrays.forEach((binArrayPubkey) => {
        binArraysForSwap.set(binArrayPubkey, true);
      });
    }
    const binArraysPubkey = Array.from(binArraysForSwap.keys());
    const transferFeeExcludedAmountOut = calculateTransferFeeExcludedAmount(
      totalOutAmount,
      outMint,
      this.clock.epoch.toNumber()
    ).amount;
    const minOutAmount = transferFeeExcludedAmountOut.mul(new BN24(BASIS_POINT_MAX).sub(allowedSlippage)).div(new BN24(BASIS_POINT_MAX));
    return {
      consumedInAmount: transferFeeIncludedInAmount,
      outAmount: transferFeeExcludedAmountOut,
      fee: feeAmount,
      protocolFee: protocolFeeAmount,
      minOutAmount,
      priceImpact,
      binArraysPubkey,
      endPrice,
      feeOnInput
    };
  }
  async swapExactOut({
    inToken,
    outToken,
    outAmount,
    maxInAmount,
    lbPair,
    user,
    binArraysPubkey
  }) {
    const preInstructions = [];
    const postInstructions = [];
    const [inTokenProgram, outTokenProgram] = inToken.equals(
      this.lbPair.tokenXMint
    ) ? [this.tokenX.owner, this.tokenY.owner] : [this.tokenY.owner, this.tokenX.owner];
    const [
      { ataPubKey: userTokenIn, ix: createInTokenAccountIx },
      { ataPubKey: userTokenOut, ix: createOutTokenAccountIx }
    ] = await Promise.all([
      getOrCreateATAInstruction(
        this.program.provider.connection,
        inToken,
        user,
        inTokenProgram
      ),
      getOrCreateATAInstruction(
        this.program.provider.connection,
        outToken,
        user,
        outTokenProgram
      )
    ]);
    createInTokenAccountIx && preInstructions.push(createInTokenAccountIx);
    createOutTokenAccountIx && preInstructions.push(createOutTokenAccountIx);
    if (inToken.equals(NATIVE_MINT2) && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        user,
        userTokenIn,
        BigInt(maxInAmount.toString())
      );
      preInstructions.push(...wrapSOLIx);
      const closeWrappedSOLIx = await unwrapSOLInstruction(user);
      closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
    }
    if (outToken.equals(NATIVE_MINT2) && !this.opt?.skipSolWrappingOperation) {
      const closeWrappedSOLIx = await unwrapSOLInstruction(user);
      closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
    }
    const { slices, accounts: transferHookAccounts } = this.getPotentialToken2022IxDataAndAccounts(0 /* Liquidity */);
    const binArrays = binArraysPubkey.map((pubkey) => {
      return {
        isSigner: false,
        isWritable: true,
        pubkey
      };
    });
    const swapIx = await this.program.methods.swapExactOut2(maxInAmount, outAmount, { slices }).accountsPartial({
      lbPair,
      reserveX: this.lbPair.reserveX,
      reserveY: this.lbPair.reserveY,
      tokenXMint: this.lbPair.tokenXMint,
      tokenYMint: this.lbPair.tokenYMint,
      tokenXProgram: this.tokenX.owner,
      tokenYProgram: this.tokenY.owner,
      user,
      userTokenIn,
      userTokenOut,
      binArrayBitmapExtension: this.binArrayBitmapExtension ? this.binArrayBitmapExtension.publicKey : null,
      oracle: this.lbPair.oracle,
      hostFeeIn: null,
      memoProgram: MEMO_PROGRAM_ID
    }).remainingAccounts(transferHookAccounts).remainingAccounts(binArrays).instruction();
    const instructions = [...preInstructions, swapIx, ...postInstructions];
    instructions.push(
      ComputeBudgetProgram3.setComputeUnitLimit({
        units: 14e5
      })
    );
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      blockhash,
      lastValidBlockHeight,
      feePayer: user
    }).add(...instructions);
  }
  /**
   * Returns a transaction to be signed and sent by user performing swap.
   * @param {SwapWithPriceImpactParams}
   *    - `inToken`: The public key of the token to be swapped in.
   *    - `outToken`: The public key of the token to be swapped out.
   *    - `inAmount`: The amount of token to be swapped in.
   *    - `priceImpact`: Accepted price impact bps.
   *    - `lbPair`: The public key of the liquidity pool.
   *    - `user`: The public key of the user account.
   *    - `binArraysPubkey`: Array of bin arrays involved in the swap
   * @returns {Promise<Transaction>}
   */
  async swapWithPriceImpact({
    inToken,
    outToken,
    inAmount,
    lbPair,
    user,
    priceImpact,
    binArraysPubkey
  }) {
    const preInstructions = [];
    const postInstructions = [];
    const [inTokenProgram, outTokenProgram] = inToken.equals(
      this.lbPair.tokenXMint
    ) ? [this.tokenX.owner, this.tokenY.owner] : [this.tokenY.owner, this.tokenX.owner];
    const [
      { ataPubKey: userTokenIn, ix: createInTokenAccountIx },
      { ataPubKey: userTokenOut, ix: createOutTokenAccountIx }
    ] = await Promise.all([
      getOrCreateATAInstruction(
        this.program.provider.connection,
        inToken,
        user,
        inTokenProgram
      ),
      getOrCreateATAInstruction(
        this.program.provider.connection,
        outToken,
        user,
        outTokenProgram
      )
    ]);
    createInTokenAccountIx && preInstructions.push(createInTokenAccountIx);
    createOutTokenAccountIx && preInstructions.push(createOutTokenAccountIx);
    if (inToken.equals(NATIVE_MINT2) && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        user,
        userTokenIn,
        BigInt(inAmount.toString())
      );
      preInstructions.push(...wrapSOLIx);
      const closeWrappedSOLIx = await unwrapSOLInstruction(user);
      closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
    }
    if (outToken.equals(NATIVE_MINT2) && !this.opt?.skipSolWrappingOperation) {
      const closeWrappedSOLIx = await unwrapSOLInstruction(user);
      closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
    }
    const binArrays = binArraysPubkey.map((pubkey) => {
      return {
        isSigner: false,
        isWritable: true,
        pubkey
      };
    });
    const { slices, accounts: transferHookAccounts } = this.getPotentialToken2022IxDataAndAccounts(0 /* Liquidity */);
    const swapIx = await this.program.methods.swapWithPriceImpact2(
      inAmount,
      this.lbPair.activeId,
      priceImpact.toNumber(),
      { slices }
    ).accountsPartial({
      lbPair,
      reserveX: this.lbPair.reserveX,
      reserveY: this.lbPair.reserveY,
      tokenXMint: this.lbPair.tokenXMint,
      tokenYMint: this.lbPair.tokenYMint,
      tokenXProgram: this.tokenX.owner,
      tokenYProgram: this.tokenY.owner,
      user,
      userTokenIn,
      userTokenOut,
      binArrayBitmapExtension: this.binArrayBitmapExtension ? this.binArrayBitmapExtension.publicKey : null,
      oracle: this.lbPair.oracle,
      hostFeeIn: null,
      memoProgram: MEMO_PROGRAM_ID
    }).remainingAccounts(transferHookAccounts).remainingAccounts(binArrays).instruction();
    const instructions = [...preInstructions, swapIx, ...postInstructions];
    const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
      this.program.provider.connection,
      instructions,
      user
    );
    instructions.unshift(setCUIx);
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      blockhash,
      lastValidBlockHeight,
      feePayer: user
    }).add(...instructions);
  }
  /**
   * Returns a transaction to be signed and sent by user performing swap.
   * @param {SwapParams}
   *    - `inToken`: The public key of the token to be swapped in.
   *    - `outToken`: The public key of the token to be swapped out.
   *    - `inAmount`: The amount of token to be swapped in.
   *    - `minOutAmount`: The minimum amount of token to be swapped out.
   *    - `lbPair`: The public key of the liquidity pool.
   *    - `user`: The public key of the user account.
   *    - `binArraysPubkey`: Array of bin arrays involved in the swap
   * @returns {Promise<Transaction>}
   */
  async swap({
    inToken,
    outToken,
    inAmount,
    minOutAmount,
    lbPair,
    user,
    binArraysPubkey
  }) {
    const preInstructions = [];
    const postInstructions = [];
    const [inTokenProgram, outTokenProgram] = inToken.equals(
      this.lbPair.tokenXMint
    ) ? [this.tokenX.owner, this.tokenY.owner] : [this.tokenY.owner, this.tokenX.owner];
    const [
      { ataPubKey: userTokenIn, ix: createInTokenAccountIx },
      { ataPubKey: userTokenOut, ix: createOutTokenAccountIx }
    ] = await Promise.all([
      getOrCreateATAInstruction(
        this.program.provider.connection,
        inToken,
        user,
        inTokenProgram
      ),
      getOrCreateATAInstruction(
        this.program.provider.connection,
        outToken,
        user,
        outTokenProgram
      )
    ]);
    createInTokenAccountIx && preInstructions.push(createInTokenAccountIx);
    createOutTokenAccountIx && preInstructions.push(createOutTokenAccountIx);
    if (inToken.equals(NATIVE_MINT2) && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        user,
        userTokenIn,
        BigInt(inAmount.toString())
      );
      preInstructions.push(...wrapSOLIx);
      const closeWrappedSOLIx = await unwrapSOLInstruction(user);
      closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
    }
    if (outToken.equals(NATIVE_MINT2) && !this.opt?.skipSolWrappingOperation) {
      const closeWrappedSOLIx = await unwrapSOLInstruction(user);
      closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
    }
    const binArrays = binArraysPubkey.map((pubkey) => {
      return {
        isSigner: false,
        isWritable: true,
        pubkey
      };
    });
    const { slices, accounts: transferHookAccounts } = this.getPotentialToken2022IxDataAndAccounts(0 /* Liquidity */);
    const swapIx = await this.program.methods.swap2(inAmount, minOutAmount, { slices }).accountsPartial({
      lbPair,
      reserveX: this.lbPair.reserveX,
      reserveY: this.lbPair.reserveY,
      tokenXMint: this.lbPair.tokenXMint,
      tokenYMint: this.lbPair.tokenYMint,
      tokenXProgram: this.tokenX.owner,
      tokenYProgram: this.tokenY.owner,
      user,
      userTokenIn,
      userTokenOut,
      binArrayBitmapExtension: this.binArrayBitmapExtension ? this.binArrayBitmapExtension.publicKey : null,
      oracle: this.lbPair.oracle,
      hostFeeIn: null,
      memoProgram: MEMO_PROGRAM_ID
    }).remainingAccounts(transferHookAccounts).remainingAccounts(binArrays).instruction();
    const instructions = [...preInstructions, swapIx, ...postInstructions];
    const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
      this.program.provider.connection,
      instructions,
      user
    );
    instructions.unshift(setCUIx);
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      blockhash,
      lastValidBlockHeight,
      feePayer: user
    }).add(...instructions);
  }
  /**
   * The claimLMReward function is used to claim rewards for a specific position owned by a specific owner.
   * @param
   *    - `owner`: The public key of the owner of the position.
   *    - `position`: The public key of the position account.
   * @returns {Promise<Transaction[]>} Claim LM reward transactions.
   */
  async claimLMReward({
    owner,
    position
  }) {
    if (isPositionNoReward(position.positionData)) {
      throw new Error("No LM reward to claim");
    }
    const claimTransactions = await this.createClaimBuildMethod({
      owner,
      position
    });
    if (!claimTransactions.length)
      return;
    const claimTransactionWithCUIx = await Promise.all(
      claimTransactions.map(async (tx) => {
        const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
          this.program.provider.connection,
          tx.instructions,
          owner
        );
        return [setCUIx, ...tx.instructions];
      })
    );
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return claimTransactionWithCUIx.map((ixs) => {
      return new Transaction({
        blockhash,
        lastValidBlockHeight,
        feePayer: owner
      }).add(...ixs);
    });
  }
  /**
   * The `claimAllLMRewards` function is used to claim all liquidity mining rewards for a given owner
   * and their positions.
   * @param
   *    - `owner`: The public key of the owner of the positions.
   *    - `positions`: An array of objects of type `PositionData` that represents the positions to claim rewards from.
   * @returns {Promise<Transaction[]>} Array of claim LM reward and fees transactions.
   */
  async claimAllLMRewards({
    owner,
    positions
  }) {
    if (positions.every((position) => isPositionNoReward(position.positionData))) {
      throw new Error("No LM reward to claim");
    }
    const claimAllTxs = (await Promise.all(
      positions.filter(
        ({ positionData: { rewardOne, rewardTwo } }) => !rewardOne.isZero() || !rewardTwo.isZero()
      ).map(async (position, idx) => {
        return await this.createClaimBuildMethod({
          owner,
          position
        });
      })
    )).flat();
    const chunkedClaimAllTx = chunks(claimAllTxs, MAX_CLAIM_ALL_ALLOWED);
    if (chunkedClaimAllTx.length === 0)
      return [];
    const chunkedClaimAllTxIx = await Promise.all(
      chunkedClaimAllTx.map(async (txs) => {
        const ixs = txs.map((t) => t.instructions).flat();
        const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
          this.program.provider.connection,
          ixs,
          owner
        );
        return [setCUIx, ...ixs];
      })
    );
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return Promise.all(
      chunkedClaimAllTxIx.map(async (claimAllTx) => {
        return new Transaction({
          feePayer: owner,
          blockhash,
          lastValidBlockHeight
        }).add(...claimAllTx);
      })
    );
  }
  async setActivationPoint(activationPoint) {
    const setActivationPointTx = await this.program.methods.setActivationPoint(activationPoint).accountsPartial({
      lbPair: this.pubkey,
      signer: this.lbPair.creator
    }).transaction();
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      feePayer: this.lbPair.creator,
      blockhash,
      lastValidBlockHeight
    }).add(setActivationPointTx);
  }
  async setPairStatus(enabled) {
    const pairStatus = enabled ? 0 : 1;
    const tx = await this.program.methods.setPairStatus(pairStatus).accountsPartial({
      lbPair: this.pubkey,
      signer: this.lbPair.creator
    }).transaction();
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      feePayer: this.lbPair.creator,
      blockhash,
      lastValidBlockHeight
    }).add(tx);
  }
  /**
   * The function `claimSwapFee` is used to claim swap fees for a specific position owned by a specific owner.
   * @param
   *    - `owner`: The public key of the owner of the position.
   *    - `position`: The public key of the position account.
   *    - `binRange`: The bin range to claim swap fees for. If not provided, the function claim swap fees for full range.
   * @returns {Promise<Transaction[]>} Claim swap fee transactions.
   */
  async claimSwapFee({
    owner,
    position
  }) {
    if (isPositionNoFee(position.positionData)) {
      throw new Error("No fee to claim");
    }
    const claimFeeTxs = await this.createClaimSwapFeeMethod({
      owner,
      position
    });
    const claimFeeTxsWithCUIx = await Promise.all(
      claimFeeTxs.map(async (tx) => {
        const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
          this.program.provider.connection,
          tx.instructions,
          owner
        );
        return [setCUIx, ...tx.instructions];
      })
    );
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return claimFeeTxsWithCUIx.map((ixs) => {
      return new Transaction({
        blockhash,
        lastValidBlockHeight,
        feePayer: owner
      }).add(...ixs);
    });
  }
  /**
   * The `claimAllSwapFee` function to claim swap fees for multiple positions owned by a specific owner.
   * @param
   *    - `owner`: The public key of the owner of the positions.
   *    - `positions`: An array of objects of type `PositionData` that represents the positions to claim swap fees from.
   * @returns {Promise<Transaction[]>} Array of claim swap fee transactions.
   */
  async claimAllSwapFee({
    owner,
    positions
  }) {
    if (positions.every((position) => isPositionNoFee(position.positionData))) {
      throw new Error("No fee to claim");
    }
    const claimAllTxs = (await Promise.all(
      positions.filter(
        ({ positionData: { feeX, feeY } }) => !feeX.isZero() || !feeY.isZero()
      ).map(async (position) => {
        return await this.createClaimSwapFeeMethod({
          owner,
          position
        });
      })
    )).flat();
    const chunkedClaimAllTx = chunks(claimAllTxs, MAX_CLAIM_ALL_ALLOWED);
    if (chunkedClaimAllTx.length === 0)
      return [];
    const chunkedClaimAllTxIxs = await Promise.all(
      chunkedClaimAllTx.map(async (tx) => {
        const ixs = tx.map((t) => t.instructions).flat();
        const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
          this.program.provider.connection,
          ixs,
          owner
        );
        return [setCUIx, ...ixs];
      })
    );
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return Promise.all(
      chunkedClaimAllTxIxs.map(async (claimAllTx) => {
        return new Transaction({
          feePayer: owner,
          blockhash,
          lastValidBlockHeight
        }).add(...claimAllTx);
      })
    );
  }
  /**
   * The function `claimAllRewardsByPosition` allows a user to claim all rewards for a specific
   * position.
   * @param
   *    - `owner`: The public key of the owner of the position.
   *    - `position`: The public key of the position account.
   * @returns {Promise<Transaction[]>} Array of claim reward transactions.
   */
  async claimAllRewardsByPosition({
    owner,
    position
  }) {
    if (isPositionNoFee(position.positionData) && isPositionNoReward(position.positionData)) {
      throw new Error("No fee/reward to claim");
    }
    const claimAllSwapFeeTxs = await this.createClaimSwapFeeMethod({
      owner,
      position
    });
    const claimAllLMTxs = await this.createClaimBuildMethod({
      owner,
      position
    });
    const claimAllTxs = chunks(
      [...claimAllSwapFeeTxs, ...claimAllLMTxs],
      MAX_CLAIM_ALL_ALLOWED
    );
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return Promise.all(
      claimAllTxs.map(async (txs) => {
        const instructions = txs.flatMap((tx) => tx.instructions);
        const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
          this.program.provider.connection,
          instructions,
          owner
        );
        const transaction = new Transaction({
          feePayer: owner,
          blockhash,
          lastValidBlockHeight
        }).add(setCUIx, ...instructions);
        return transaction;
      })
    );
  }
  /**
   * The `seedLiquidity` function create multiple grouped instructions. The grouped instructions will be [init ata + send lamport for token provde], [initialize bin array + initialize position instructions] and [deposit instruction]. Each grouped instructions can be executed parallelly.
   * @param
   *    - `owner`: The public key of the positions owner.
   *    - `seedAmount`: Lamport amount to be seeded to the pool.
   *    - `minPrice`: Start price in UI format
   *    - `maxPrice`: End price in UI format
   *    - `base`: Base key
   *    - `txPayer`: Account rental fee payer
   *    - `feeOwner`: Fee owner key. Default to position owner
   *    - `operator`: Operator key
   *    - `lockReleasePoint`: Timelock. Point (slot/timestamp) the position can withdraw the liquidity,
   *    - `shouldSeedPositionOwner` (optional): Whether to send 1 lamport amount of token X to the position owner to prove ownership.
   * @returns {Promise<SeedLiquidityResponse>}
   */
  async seedLiquidity(owner, seedAmount, curvature, minPrice, maxPrice, base, payer, feeOwner, operator, lockReleasePoint, shouldSeedPositionOwner = false) {
    let tokenOwnerProveAssociatedTokenAccountLamports = new BN24(0);
    let totalPositionCount = new BN24(0);
    let totalPositionLamports = new BN24(0);
    let totalBinArraysCount = new BN24(0);
    let totalBinArraysLamports = new BN24(0);
    let binArrayBitmapLamports = new BN24(0);
    const toLamportMultiplier = new Decimal11(
      10 ** (this.tokenY.mint.decimals - this.tokenX.mint.decimals)
    );
    const minPricePerLamport = new Decimal11(minPrice).mul(toLamportMultiplier);
    const maxPricePerLamport = new Decimal11(maxPrice).mul(toLamportMultiplier);
    const minBinId = new BN24(
      DLMM.getBinIdFromPrice(minPricePerLamport, this.lbPair.binStep, false)
    );
    const maxBinId = new BN24(
      DLMM.getBinIdFromPrice(maxPricePerLamport, this.lbPair.binStep, true)
    );
    if (minBinId.toNumber() < this.lbPair.activeId) {
      throw new Error("minPrice < current pair price");
    }
    if (minBinId.toNumber() >= maxBinId.toNumber()) {
      throw new Error("Price range too small");
    }
    const k = 1 / curvature;
    const binDepositAmount = generateAmountForBinRange(
      seedAmount,
      this.lbPair.binStep,
      this.tokenX.mint.decimals,
      this.tokenY.mint.decimals,
      minBinId,
      maxBinId,
      k
    );
    const decompressMultiplier = findOptimumDecompressMultiplier(
      binDepositAmount,
      new BN24(this.tokenX.mint.decimals)
    );
    let { compressedBinAmount, compressionLoss } = compressBinAmount(
      binDepositAmount,
      decompressMultiplier
    );
    let {
      newCompressedBinAmount: compressedBinDepositAmount,
      loss: finalLoss
    } = distributeAmountToCompressedBinsByRatio(
      compressedBinAmount,
      compressionLoss,
      decompressMultiplier,
      new BN24(2 ** 32 - 1)
      // u32
    );
    const positionCount = getPositionCount(minBinId, maxBinId.sub(new BN24(1)));
    const seederTokenX = getAssociatedTokenAddressSync2(
      this.lbPair.tokenXMint,
      operator,
      false,
      this.tokenX.owner
    );
    const seederTokenY = getAssociatedTokenAddressSync2(
      this.lbPair.tokenYMint,
      operator,
      false,
      this.tokenY.owner
    );
    const ownerTokenX = getAssociatedTokenAddressSync2(
      this.lbPair.tokenXMint,
      owner,
      false,
      this.tokenX.owner
    );
    const [binArrayBitmapExtension] = deriveBinArrayBitmapExtension(
      this.pubkey,
      this.program.programId
    );
    const sendPositionOwnerTokenProveIxs = [];
    const initializeBinArraysAndPositionIxs = [];
    const addLiquidityIxs = [];
    const appendedInitBinArrayIx = /* @__PURE__ */ new Set();
    let appendedInitBinArrayBitmap = false;
    if (shouldSeedPositionOwner) {
      const positionOwnerTokenX = await this.program.provider.connection.getAccountInfo(ownerTokenX);
      let requireTokenProve = false;
      if (positionOwnerTokenX) {
        const ownerTokenXState = unpackAccount(
          ownerTokenX,
          positionOwnerTokenX,
          this.tokenX.owner
        );
        requireTokenProve = ownerTokenXState.amount == 0n;
      } else {
        requireTokenProve = true;
      }
      if (requireTokenProve) {
        if (!positionOwnerTokenX) {
          tokenOwnerProveAssociatedTokenAccountLamports = tokenOwnerProveAssociatedTokenAccountLamports.add(
            TOKEN_ACCOUNT_FEE_BN
          );
        }
        const initPositionOwnerTokenX = createAssociatedTokenAccountIdempotentInstruction2(
          payer,
          ownerTokenX,
          owner,
          this.lbPair.tokenXMint,
          this.tokenX.owner
        );
        const proveAmount = calculateTransferFeeIncludedAmount(
          new BN24(1),
          this.tokenX.mint,
          this.clock.epoch.toNumber()
        ).amount;
        sendPositionOwnerTokenProveIxs.push(initPositionOwnerTokenX);
        const transferIx = createTransferCheckedInstruction2(
          seederTokenX,
          this.lbPair.tokenXMint,
          ownerTokenX,
          operator,
          BigInt(proveAmount.toString()),
          this.tokenX.mint.decimals,
          [],
          this.tokenX.owner
        );
        transferIx.keys.push(...this.tokenX.transferHookAccountMetas);
        sendPositionOwnerTokenProveIxs.push(transferIx);
      }
    }
    const slices = [
      {
        accountsType: {
          transferHookX: {}
        },
        length: this.tokenX.transferHookAccountMetas.length
      }
    ];
    const transferHookAccountMetas = this.tokenX.transferHookAccountMetas;
    for (let i = 0; i < positionCount.toNumber(); i++) {
      const lowerBinId = minBinId.add(DEFAULT_BIN_PER_POSITION.mul(new BN24(i)));
      const upperBinId = lowerBinId.add(DEFAULT_BIN_PER_POSITION).sub(new BN24(1));
      const binArrayAccountMetas = getBinArrayAccountMetasCoverage(
        lowerBinId,
        upperBinId,
        this.pubkey,
        this.program.programId
      );
      const binArrayIndexes = getBinArrayIndexesCoverage(
        lowerBinId,
        upperBinId
      );
      const [positionPda, _bump] = derivePosition(
        this.pubkey,
        base,
        lowerBinId,
        DEFAULT_BIN_PER_POSITION,
        this.program.programId
      );
      const accounts = await this.program.provider.connection.getMultipleAccountsInfo([
        ...binArrayAccountMetas.map((acc) => acc.pubkey),
        positionPda
      ]);
      let instructions = [];
      const binArrayAccounts = accounts.splice(0, binArrayAccountMetas.length);
      for (let i2 = 0; i2 < binArrayAccountMetas.length; i2++) {
        const account = binArrayAccounts[i2];
        const pubkey = binArrayAccountMetas[i2].pubkey.toBase58();
        const index = binArrayIndexes[i2];
        if (!account && !appendedInitBinArrayIx.has(pubkey)) {
          totalBinArraysCount = totalBinArraysCount.add(new BN24(1));
          totalBinArraysLamports = totalBinArraysLamports.add(BIN_ARRAY_FEE_BN);
          instructions.push(
            await this.program.methods.initializeBinArray(index).accountsPartial({
              lbPair: this.pubkey,
              binArray: pubkey,
              funder: payer
            }).instruction()
          );
        }
      }
      const positionAccount = accounts.pop();
      if (!positionAccount) {
        totalPositionCount = totalPositionCount.add(new BN24(1));
        totalPositionLamports = totalPositionLamports.add(POSITION_FEE_BN);
        instructions.push(
          await this.program.methods.initializePositionByOperator(
            lowerBinId.toNumber(),
            DEFAULT_BIN_PER_POSITION.toNumber(),
            feeOwner,
            lockReleasePoint
          ).accountsPartial({
            lbPair: this.pubkey,
            position: positionPda,
            base,
            owner,
            operator,
            operatorTokenX: seederTokenX,
            ownerTokenX,
            systemProgram: SystemProgram2.programId,
            payer
          }).instruction()
        );
      }
      if (instructions.length > 0) {
        initializeBinArraysAndPositionIxs.push(instructions);
        instructions = [];
      }
      const positionDeposited = positionAccount && decodeAccount(
        this.program,
        "positionV2",
        positionAccount.data
      ).liquidityShares.reduce((total, cur) => total.add(cur), new BN24(0)).gt(new BN24(0));
      if (!positionDeposited) {
        let overflowDefaultBinArrayBitmap = false;
        for (const binArrayIndex of binArrayIndexes) {
          if (isOverflowDefaultBinArrayBitmap(binArrayIndex)) {
            if (!this.binArrayBitmapExtension && !appendedInitBinArrayBitmap) {
              initializeBinArraysAndPositionIxs.push(
                await this.program.methods.initializeBinArrayBitmapExtension().accountsPartial({
                  binArrayBitmapExtension,
                  funder: payer,
                  lbPair: this.pubkey,
                  rent: SYSVAR_RENT_PUBKEY2
                }).instruction()
              );
              appendedInitBinArrayBitmap = true;
              binArrayBitmapLamports = binArrayBitmapLamports.add(
                BIN_ARRAY_BITMAP_FEE_BN
              );
            }
            overflowDefaultBinArrayBitmap = true;
          }
        }
        const cappedUpperBinId = Math.min(
          upperBinId.toNumber(),
          maxBinId.toNumber() - 1
        );
        const bins = [];
        for (let i2 = lowerBinId.toNumber(); i2 <= cappedUpperBinId; i2++) {
          bins.push({
            binId: i2,
            amount: compressedBinDepositAmount.get(i2).toNumber()
          });
        }
        instructions.push(
          await this.program.methods.addLiquidityOneSidePrecise2(
            {
              bins,
              decompressMultiplier,
              maxAmount: U64_MAX
            },
            {
              slices
            }
          ).accountsPartial({
            position: positionPda,
            lbPair: this.pubkey,
            binArrayBitmapExtension: overflowDefaultBinArrayBitmap ? binArrayBitmapExtension : this.program.programId,
            userToken: seederTokenX,
            reserve: this.lbPair.reserveX,
            tokenMint: this.lbPair.tokenXMint,
            sender: operator,
            tokenProgram: this.tokenX.owner
          }).remainingAccounts([
            ...transferHookAccountMetas,
            ...binArrayAccountMetas
          ]).instruction()
        );
        if (i + 1 >= positionCount.toNumber() && !finalLoss.isZero()) {
          const finalLossIncludesTransferFee = calculateTransferFeeIncludedAmount(
            finalLoss,
            this.tokenX.mint,
            this.clock.epoch.toNumber()
          ).amount;
          instructions.push(
            await this.program.methods.addLiquidity2(
              {
                amountX: finalLossIncludesTransferFee,
                amountY: new BN24(0),
                binLiquidityDist: [
                  {
                    binId: cappedUpperBinId,
                    distributionX: BASIS_POINT_MAX,
                    distributionY: BASIS_POINT_MAX
                  }
                ]
              },
              {
                slices
              }
            ).accountsPartial({
              position: positionPda,
              lbPair: this.pubkey,
              binArrayBitmapExtension: overflowDefaultBinArrayBitmap ? binArrayBitmapExtension : this.program.programId,
              userTokenX: seederTokenX,
              userTokenY: seederTokenY,
              reserveX: this.lbPair.reserveX,
              reserveY: this.lbPair.reserveY,
              tokenXMint: this.lbPair.tokenXMint,
              tokenYMint: this.lbPair.tokenYMint,
              tokenXProgram: this.tokenX.owner,
              tokenYProgram: this.tokenY.owner,
              sender: operator
            }).remainingAccounts([
              ...transferHookAccountMetas,
              ...getBinArrayAccountMetasCoverage(
                new BN24(cappedUpperBinId),
                new BN24(cappedUpperBinId),
                this.pubkey,
                this.program.programId
              )
            ]).instruction()
          );
        }
        addLiquidityIxs.push([
          ComputeBudgetProgram3.setComputeUnitLimit({
            units: DEFAULT_ADD_LIQUIDITY_CU
          }),
          ...instructions
        ]);
      }
    }
    return {
      sendPositionOwnerTokenProveIxs,
      initializeBinArraysAndPositionIxs,
      addLiquidityIxs,
      costBreakdown: {
        tokenOwnerProveAssociatedTokenAccountLamports,
        totalBinArraysCount,
        totalBinArraysLamports,
        totalPositionCount,
        totalPositionLamports,
        binArrayBitmapLamports
      }
    };
  }
  /**
   * The `seedLiquiditySingleBin` function seed liquidity into a single bin.
   * @param
   *    - `payer`: The public key of the tx payer.
   *    - `base`: Base key
   *    - `seedAmount`: Token X lamport amount to be seeded to the pool.
   *    - `price`: TokenX/TokenY Price in UI format
   *    - `roundingUp`: Whether to round up the price
   *    - `positionOwner`: The owner of the position
   *    - `feeOwner`: Position fee owner
   *    - `operator`: Operator of the position. Operator able to manage the position on behalf of the position owner. However, liquidity withdrawal issue by the operator can only send to the position owner.
   *    - `lockReleasePoint`: The lock release point of the position.
   *    - `shouldSeedPositionOwner` (optional): Whether to send 1 lamport amount of token X to the position owner to prove ownership.
   *
   * The returned instructions need to be executed sequentially if it was separated into multiple transactions.
   * @returns {Promise<SeedLiquiditySingleBinResponse>}
   */
  async seedLiquiditySingleBin(payer, base, seedAmount, price, roundingUp, positionOwner, feeOwner, operator, lockReleasePoint, shouldSeedPositionOwner = false) {
    let tokenOwnerProveAssociatedTokenAccountLamports = new BN24(0);
    let totalPositionCount = new BN24(0);
    let totalPositionLamports = new BN24(0);
    let totalBinArraysCount = new BN24(0);
    let totalBinArraysLamports = new BN24(0);
    let binArrayBitmapLamports = new BN24(0);
    const pricePerLamport = DLMM.getPricePerLamport(
      this.tokenX.mint.decimals,
      this.tokenY.mint.decimals,
      price
    );
    const binIdNumber = DLMM.getBinIdFromPrice(
      pricePerLamport,
      this.lbPair.binStep,
      !roundingUp
    );
    const binId = new BN24(binIdNumber);
    const [positionPda] = derivePosition(
      this.pubkey,
      base,
      binId,
      new BN24(1),
      this.program.programId
    );
    const binArrayIndex = binIdToBinArrayIndex(binId);
    const [binArrayKey] = deriveBinArray(
      this.pubkey,
      binArrayIndex,
      this.program.programId
    );
    const preInstructions = [];
    const [
      { ataPubKey: userTokenX, ix: createPayerTokenXIx },
      { ataPubKey: userTokenY, ix: createPayerTokenYIx }
    ] = await Promise.all([
      getOrCreateATAInstruction(
        this.program.provider.connection,
        this.tokenX.publicKey,
        operator,
        this.tokenX.owner,
        payer
      ),
      getOrCreateATAInstruction(
        this.program.provider.connection,
        this.tokenY.publicKey,
        operator,
        this.tokenY.owner,
        payer
      )
    ]);
    createPayerTokenXIx && preInstructions.push(createPayerTokenXIx);
    createPayerTokenYIx && preInstructions.push(createPayerTokenYIx);
    let [binArrayBitmapExtension] = deriveBinArrayBitmapExtension(
      this.pubkey,
      this.program.programId
    );
    const [binArrayAccount, positionAccount, bitmapExtensionAccount] = await this.program.provider.connection.getMultipleAccountsInfo([
      binArrayKey,
      positionPda,
      binArrayBitmapExtension
    ]);
    if (isOverflowDefaultBinArrayBitmap(binArrayIndex)) {
      if (!bitmapExtensionAccount) {
        preInstructions.push(
          await this.program.methods.initializeBinArrayBitmapExtension().accountsPartial({
            binArrayBitmapExtension,
            funder: payer,
            lbPair: this.pubkey,
            rent: SYSVAR_RENT_PUBKEY2
          }).instruction()
        );
        binArrayBitmapLamports = binArrayBitmapLamports.add(
          BIN_ARRAY_BITMAP_FEE_BN
        );
      }
    } else {
      binArrayBitmapExtension = this.program.programId;
    }
    const operatorTokenX = getAssociatedTokenAddressSync2(
      this.lbPair.tokenXMint,
      operator,
      true,
      this.tokenX.owner
    );
    const positionOwnerTokenX = getAssociatedTokenAddressSync2(
      this.lbPair.tokenXMint,
      positionOwner,
      true,
      this.tokenX.owner
    );
    if (shouldSeedPositionOwner) {
      const positionOwnerTokenXAccount = await this.program.provider.connection.getAccountInfo(
        positionOwnerTokenX
      );
      const proveAmount = calculateTransferFeeIncludedAmount(
        new BN24(1),
        this.tokenX.mint,
        this.clock.epoch.toNumber()
      ).amount;
      if (positionOwnerTokenXAccount) {
        const account = unpackAccount(
          positionOwnerTokenX,
          positionOwnerTokenXAccount,
          this.tokenX.owner
        );
        if (account.amount == BigInt(0)) {
          const transferIx = createTransferCheckedInstruction2(
            operatorTokenX,
            this.lbPair.tokenXMint,
            positionOwnerTokenX,
            operator,
            BigInt(proveAmount.toString()),
            this.tokenX.mint.decimals,
            [],
            this.tokenX.owner
          );
          transferIx.keys.push(...this.tokenX.transferHookAccountMetas);
          preInstructions.push(transferIx);
        }
      } else {
        const createPositionOwnerTokenXIx = createAssociatedTokenAccountIdempotentInstruction2(
          payer,
          positionOwnerTokenX,
          positionOwner,
          this.lbPair.tokenXMint,
          this.tokenX.owner
        );
        preInstructions.push(createPositionOwnerTokenXIx);
        const transferIx = createTransferCheckedInstruction2(
          operatorTokenX,
          this.lbPair.tokenXMint,
          positionOwnerTokenX,
          operator,
          BigInt(proveAmount.toString()),
          this.tokenX.mint.decimals,
          [],
          this.tokenX.owner
        );
        transferIx.keys.push(...this.tokenX.transferHookAccountMetas);
        preInstructions.push(transferIx);
        tokenOwnerProveAssociatedTokenAccountLamports = tokenOwnerProveAssociatedTokenAccountLamports.add(
          TOKEN_ACCOUNT_FEE_BN
        );
      }
    }
    if (!binArrayAccount) {
      preInstructions.push(
        await this.program.methods.initializeBinArray(binArrayIndex).accountsPartial({
          binArray: binArrayKey,
          funder: payer,
          lbPair: this.pubkey
        }).instruction()
      );
      totalBinArraysCount = totalBinArraysCount.add(new BN24(1));
      totalBinArraysLamports = totalBinArraysLamports.add(BIN_ARRAY_FEE_BN);
    }
    if (!positionAccount) {
      preInstructions.push(
        await this.program.methods.initializePositionByOperator(
          binId.toNumber(),
          1,
          feeOwner,
          lockReleasePoint
        ).accountsPartial({
          payer,
          base,
          position: positionPda,
          lbPair: this.pubkey,
          owner: positionOwner,
          operator,
          operatorTokenX,
          ownerTokenX: positionOwnerTokenX
        }).instruction()
      );
      totalPositionCount = totalPositionCount.add(new BN24(1));
      totalPositionLamports = totalPositionLamports.add(POSITION_FEE_BN);
    }
    const slices = [
      {
        accountsType: {
          transferHookX: {}
        },
        length: this.tokenX.transferHookAccountMetas.length
      }
    ];
    const transferHookAccountMetas = this.tokenX.transferHookAccountMetas;
    const binLiquidityDist = {
      binId: binIdNumber,
      distributionX: BASIS_POINT_MAX,
      distributionY: BASIS_POINT_MAX
    };
    const seedAmountIncludeTransferFee = calculateTransferFeeIncludedAmount(
      seedAmount,
      this.tokenX.mint,
      this.clock.epoch.toNumber()
    ).amount;
    const addLiquidityParams = {
      amountX: seedAmountIncludeTransferFee,
      amountY: new BN24(0),
      binLiquidityDist: [binLiquidityDist]
    };
    const depositLiquidityIx = await this.program.methods.addLiquidity2(addLiquidityParams, {
      slices
    }).accountsPartial({
      position: positionPda,
      lbPair: this.pubkey,
      binArrayBitmapExtension,
      userTokenX,
      userTokenY,
      reserveX: this.lbPair.reserveX,
      reserveY: this.lbPair.reserveY,
      tokenXMint: this.lbPair.tokenXMint,
      tokenYMint: this.lbPair.tokenYMint,
      sender: operator,
      tokenXProgram: this.tokenX.owner,
      tokenYProgram: this.tokenY.owner
    }).remainingAccounts([
      ...transferHookAccountMetas,
      {
        pubkey: binArrayKey,
        isSigner: false,
        isWritable: true
      }
    ]).instruction();
    const instructions = [...preInstructions, depositLiquidityIx];
    return {
      instructions,
      costBreakdown: {
        tokenOwnerProveAssociatedTokenAccountLamports,
        totalBinArraysCount,
        totalBinArraysLamports,
        totalPositionCount,
        totalPositionLamports,
        binArrayBitmapLamports
      }
    };
  }
  /**
   * Initializes bin arrays for the given bin array indexes if it wasn't initialized.
   *
   * @param {BN[]} binArrayIndexes - An array of bin array indexes to initialize.
   * @param {PublicKey} funder - The public key of the funder.
   * @return {Promise<TransactionInstruction[]>} An array of transaction instructions to initialize the bin arrays.
   */
  async initializeBinArrays(binArrayIndexes, funder) {
    const ixs = [];
    for (const idx of binArrayIndexes) {
      const [binArray] = deriveBinArray(
        this.pubkey,
        idx,
        this.program.programId
      );
      const binArrayAccount = await this.program.provider.connection.getAccountInfo(binArray);
      if (binArrayAccount === null) {
        const initBinArrayIx = await this.program.methods.initializeBinArray(idx).accountsPartial({
          binArray,
          funder,
          lbPair: this.pubkey
        }).instruction();
        ixs.push(initBinArrayIx);
      }
    }
    if (ixs.length > 0) {
      const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
        this.program.provider.connection,
        ixs,
        funder
      );
      ixs.unshift(setCUIx);
    }
    return ixs;
  }
  /**
   *
   * @param
   *    - `lowerBinId`: Lower bin ID of the position. This represent the lowest price of the position
   *    - `positionWidth`: Width of the position. This will decide the upper bin id of the position, which represents the highest price of the position. UpperBinId = lowerBinId + positionWidth
   *    - `owner`: Owner of the position.
   *    - `operator`: Operator of the position. Operator able to manage the position on behalf of the position owner. However, liquidity withdrawal issue by the operator can only send to the position owner.
   *    - `base`: Base key
   *    - `feeOwner`: Owner of the fees earned by the position.
   *    - `payer`: Payer for the position account rental.
   *    - `lockReleasePoint`: The lock release point of the position.
   * @returns
   */
  async initializePositionByOperator({
    lowerBinId,
    positionWidth,
    owner,
    feeOwner,
    base,
    operator,
    payer,
    lockReleasePoint
  }) {
    const [positionPda, _bump] = derivePosition(
      this.pubkey,
      base,
      lowerBinId,
      positionWidth,
      this.program.programId
    );
    const operatorTokenX = getAssociatedTokenAddressSync2(
      this.lbPair.tokenXMint,
      operator,
      true,
      this.tokenX.owner
    );
    const ownerTokenX = getAssociatedTokenAddressSync2(
      this.lbPair.tokenXMint,
      owner,
      true,
      this.tokenY.owner
    );
    const initializePositionByOperatorTx = await this.program.methods.initializePositionByOperator(
      lowerBinId.toNumber(),
      DEFAULT_BIN_PER_POSITION.toNumber(),
      feeOwner,
      lockReleasePoint
    ).accountsPartial({
      lbPair: this.pubkey,
      position: positionPda,
      base,
      operator,
      owner,
      ownerTokenX,
      operatorTokenX,
      payer
    }).transaction();
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      feePayer: operator,
      blockhash,
      lastValidBlockHeight
    }).add(initializePositionByOperatorTx);
  }
  /**
   * The `claimAllRewards` function to claim swap fees and LM rewards for multiple positions owned by a specific owner.
   * @param
   *    - `owner`: The public key of the owner of the positions.
   *    - `positions`: An array of objects of type `PositionData` that represents the positions to claim swap fees and LM rewards from.
   * @returns {Promise<Transaction[]>} Array of claim swap fee and LM reward transactions.
   */
  async claimAllRewards({
    owner,
    positions
  }) {
    positions = positions.filter(
      ({ positionData: { feeX, feeY, rewardOne, rewardTwo } }) => !feeX.isZero() || !feeY.isZero() || !rewardOne.isZero() || !rewardTwo.isZero()
    );
    const claimAllSwapFeeTxs = (await Promise.all(
      positions.map(async (position) => {
        return await this.createClaimSwapFeeMethod({
          owner,
          position
        });
      })
    )).flat();
    const claimAllLMTxs = (await Promise.all(
      positions.map(async (position) => {
        return await this.createClaimBuildMethod({
          owner,
          position
        });
      })
    )).flat();
    const transactions = chunks(
      [...claimAllSwapFeeTxs, ...claimAllLMTxs],
      MAX_CLAIM_ALL_ALLOWED
    );
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return Promise.all(
      transactions.map(async (txs) => {
        const instructions = txs.flatMap((i) => i.instructions);
        const setCUIx = await getEstimatedComputeUnitIxWithBuffer(
          this.program.provider.connection,
          instructions,
          owner
        );
        const transaction = new Transaction({
          feePayer: owner,
          blockhash,
          lastValidBlockHeight
        }).add(setCUIx, ...instructions);
        return transaction;
      })
    );
  }
  canSyncWithMarketPrice(marketPrice, activeBinId) {
    const marketPriceBinId = this.getBinIdFromPrice(
      Number(
        DLMM.getPricePerLamport(
          this.tokenX.mint.decimals,
          this.tokenY.mint.decimals,
          marketPrice
        )
      ),
      false
    );
    const marketPriceBinArrayIndex = binIdToBinArrayIndex(
      new BN24(marketPriceBinId)
    );
    const swapForY = marketPriceBinId < activeBinId;
    const toBinArrayIndex = findNextBinArrayIndexWithLiquidity(
      swapForY,
      new BN24(activeBinId),
      this.lbPair,
      this.binArrayBitmapExtension?.account ?? null
    );
    if (toBinArrayIndex === null)
      return true;
    return swapForY ? marketPriceBinArrayIndex.gt(toBinArrayIndex) : marketPriceBinArrayIndex.lt(toBinArrayIndex);
  }
  /**
   * The `syncWithMarketPrice` function is used to sync the liquidity pool with the market price.
   * @param
   *    - `marketPrice`: The market price to sync with.
   *    - `owner`: The public key of the owner of the liquidity pool.
   * @returns {Promise<Transaction>}
   */
  async syncWithMarketPrice(marketPrice, owner) {
    const marketPriceBinId = this.getBinIdFromPrice(
      Number(
        DLMM.getPricePerLamport(
          this.tokenX.mint.decimals,
          this.tokenY.mint.decimals,
          marketPrice
        )
      ),
      false
    );
    const activeBin = await this.getActiveBin();
    const activeBinId = activeBin.binId;
    if (!this.canSyncWithMarketPrice(marketPrice, activeBinId)) {
      throw new Error(
        "Unable to sync with market price due to bin with liquidity between current and market price bin"
      );
    }
    const fromBinArrayIndex = binIdToBinArrayIndex(new BN24(activeBinId));
    const swapForY = marketPriceBinId < activeBinId;
    const toBinArrayIndex = findNextBinArrayIndexWithLiquidity(
      swapForY,
      new BN24(activeBinId),
      this.lbPair,
      this.binArrayBitmapExtension?.account ?? null
    );
    const marketPriceBinArrayIndex = binIdToBinArrayIndex(
      new BN24(marketPriceBinId)
    );
    const accountsToFetch = [];
    const binArrayBitMapExtensionPubkey = isOverflowDefaultBinArrayBitmap(
      new BN24(marketPriceBinArrayIndex)
    ) ? deriveBinArrayBitmapExtension(this.pubkey, this.program.programId)[0] : null;
    binArrayBitMapExtensionPubkey && accountsToFetch.push(binArrayBitMapExtensionPubkey);
    const [fromBinArrayPubkey] = deriveBinArray(
      this.pubkey,
      fromBinArrayIndex,
      this.program.programId
    );
    accountsToFetch.push(fromBinArrayPubkey);
    const toBinArrayPubkey = (() => {
      if (!toBinArrayIndex)
        return null;
      const [toBinArrayPubkey2] = deriveBinArray(
        this.pubkey,
        toBinArrayIndex,
        this.program.programId
      );
      accountsToFetch.push(toBinArrayPubkey2);
      return toBinArrayPubkey2;
    })();
    const binArrayAccounts = await this.program.provider.connection.getMultipleAccountsInfo(
      accountsToFetch
    );
    const preInstructions = [];
    let fromBinArray = null;
    let toBinArray = null;
    let binArrayBitmapExtension = null;
    if (binArrayBitMapExtensionPubkey) {
      binArrayBitmapExtension = binArrayBitMapExtensionPubkey;
      if (!binArrayAccounts?.[0]) {
        const initializeBitmapExtensionIx = await this.program.methods.initializeBinArrayBitmapExtension().accountsPartial({
          binArrayBitmapExtension: binArrayBitMapExtensionPubkey,
          funder: owner,
          lbPair: this.pubkey,
          rent: SYSVAR_RENT_PUBKEY2
        }).instruction();
        preInstructions.push(initializeBitmapExtensionIx);
      }
    }
    if (!!binArrayAccounts?.[1]) {
      fromBinArray = fromBinArrayPubkey;
    }
    if (!!binArrayAccounts?.[2] && !!toBinArrayIndex) {
      toBinArray = toBinArrayPubkey;
    }
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    const syncWithMarketPriceTx = await this.program.methods.goToABin(marketPriceBinId).accountsPartial({
      lbPair: this.pubkey,
      binArrayBitmapExtension,
      fromBinArray,
      toBinArray
    }).preInstructions(preInstructions).transaction();
    return new Transaction({
      feePayer: owner,
      blockhash,
      lastValidBlockHeight
    }).add(syncWithMarketPriceTx);
  }
  async getMaxPriceInBinArrays(binArrayAccounts) {
    const sortedBinArrays = [...binArrayAccounts].sort(
      ({ account: { index: indexA } }, { account: { index: indexB } }) => indexA.toNumber() - indexB.toNumber()
    );
    let count = sortedBinArrays.length - 1;
    let binPriceWithLastLiquidity;
    while (count >= 0) {
      const binArray = sortedBinArrays[count];
      if (binArray) {
        const bins = binArray.account.bins;
        if (bins.every(({ amountX }) => amountX.isZero())) {
          count--;
        } else {
          const lastBinWithLiquidityIndex = bins.findLastIndex(
            ({ amountX }) => !amountX.isZero()
          );
          binPriceWithLastLiquidity = bins[lastBinWithLiquidityIndex].price.toString();
          count = -1;
        }
      }
    }
    return this.fromPricePerLamport(
      Number(binPriceWithLastLiquidity) / (2 ** 64 - 1)
    );
  }
  /**
   *
   * @param swapInitiator Address of the swap initiator
   * @returns
   */
  isSwapDisabled(swapInitiator) {
    if (this.lbPair.status == 1 /* Disabled */) {
      return true;
    }
    if (this.lbPair.pairType == 1 /* Permissioned */ || this.lbPair.pairType == 2 /* CustomizablePermissionless */) {
      const currentPoint = this.lbPair.activationType == 0 /* Slot */ ? this.clock.slot : this.clock.unixTimestamp;
      const preActivationSwapPoint = this.lbPair.activationPoint.sub(
        this.lbPair.preActivationDuration
      );
      const activationPoint = !this.lbPair.preActivationSwapAddress.equals(PublicKey10.default) && this.lbPair.preActivationSwapAddress.equals(swapInitiator) ? preActivationSwapPoint : this.lbPair.activationPoint;
      if (currentPoint < activationPoint) {
        return true;
      }
    }
    return false;
  }
  /**
   * Decrease the length of a position. The segment of the position to be decreased must be empty.
   *
   * @param position The public key of the position to decrease.
   * @param side The side of the position to decrease.
   * @param length The amount of length to decrease.
   * @param allowParallelExecution If true, the instructions will be grouped to allow parallel execution. Otherwise, the instructions will be executed sequentially.
   * @returns An array of transactions if allowParallelExecution is true. Otherwise, an empty array.
   */
  async decreasePositionLength(position, side, length, allowParallelExecution = true) {
    const positionAccount = await this.program.provider.connection.getAccountInfo(position);
    const positionState = wrapPosition(this.program, position, positionAccount);
    const newWidth = positionState.width().sub(length);
    if (newWidth.lte(new BN24(0))) {
      length = length.sub(newWidth.abs()).subn(1);
    }
    const groupedIxs = [];
    const promises = [];
    for (let i = length.toNumber(); i > 0; i -= MAX_RESIZE_LENGTH.toNumber()) {
      const lengthToReduce = Math.min(i, MAX_RESIZE_LENGTH.toNumber());
      const setCuIx = ComputeBudgetProgram3.setComputeUnitLimit({
        units: getDefaultExtendPositionCU(side)
      });
      const ixPromise = this.program.methods.decreasePositionLength(lengthToReduce, Number(side)).accountsPartial({
        position,
        owner: positionState.owner(),
        rentReceiver: positionState.owner()
      }).instruction().then((decreasePositionLengthIx) => {
        if (allowParallelExecution) {
          decreasePositionLengthIx.keys.push({
            isSigner: false,
            isWritable: false,
            pubkey: PublicKey10.unique()
          });
        }
        const ixs = [setCuIx, decreasePositionLengthIx];
        groupedIxs.push(ixs);
      });
      promises.push(ixPromise);
    }
    await Promise.all(promises);
    if (groupedIxs.length > 0) {
      const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
      return groupedIxs.map((ixs) => {
        return new Transaction({
          feePayer: positionState.owner(),
          blockhash,
          lastValidBlockHeight
        }).add(...ixs);
      });
    }
  }
  /**
   * Expand the position bin range to the left or right (lower or upper).
   *
   * @param position The address of the position to increase the length of.
   * @param side The side of the position to increase the length of. Must be either
   *             ResizeSide.Lower or ResizeSide.Upper.
   * @param length The number of bins to increase the length of. Position length after increase must be <= 1400.
   * @param funder The address to account rental and transaction fee.
   * @param allowParallelExecution Whether to allow parallel execution of the transaction.
   * @returns The transaction to execute this instruction.
   */
  async increasePositionLength(position, side, length, funder, allowParallelExecution = true) {
    const positionAccount = await this.program.provider.connection.getAccountInfo(position);
    const positionState = wrapPosition(this.program, position, positionAccount);
    const newWidth = positionState.width().add(length);
    if (newWidth.gt(POSITION_MAX_LENGTH)) {
      length = newWidth.sub(POSITION_MAX_LENGTH);
    }
    const groupedIxs = await this.increasePositionLengthIxs(
      position,
      side,
      length,
      funder,
      positionState.owner(),
      true,
      allowParallelExecution
    );
    if (groupedIxs.length > 0) {
      const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
      return groupedIxs.map((ixs) => {
        return new Transaction({
          feePayer: funder,
          blockhash,
          lastValidBlockHeight
        }).add(...ixs);
      });
    }
  }
  async simulateRebalancePositionWithBalancedStrategy(positionAddress, positionData, strategy, topUpAmountX, topUpAmountY, xWithdrawBps, yWithdrawBps) {
    const rebalancePosition = await RebalancePosition.create({
      program: this.program,
      positionAddress,
      positionData,
      shouldClaimFee: true,
      shouldClaimReward: true,
      pairAddress: this.pubkey
    });
    const rebalanceStrategyBuilder = new BalancedStrategyBuilder(
      new BN24(rebalancePosition.lbPair.activeId),
      new BN24(rebalancePosition.lbPair.binStep),
      positionData,
      topUpAmountX,
      topUpAmountY,
      xWithdrawBps,
      yWithdrawBps,
      strategy
    );
    return this.simulateRebalancePositionWithStrategy(
      rebalancePosition,
      rebalanceStrategyBuilder
    );
  }
  async simulateRebalancePositionWithStrategy(rebalancePosition, rebalanceStrategy) {
    const { deposits, withdraws } = rebalanceStrategy.buildRebalanceStrategyParameters();
    const simulationResult = await rebalancePosition.simulateRebalance(
      this.program.provider.connection,
      new BN24(this.lbPair.binStep),
      new BN24(this.tokenX.mint.decimals),
      new BN24(this.tokenY.mint.decimals),
      withdraws,
      deposits
    );
    const binArrayQuoteResult = await this.quoteBinArrayAccountsRentalCost(
      simulationResult.depositParams,
      simulationResult.withdrawParams,
      new BN24(rebalancePosition.lbPair.activeId)
    );
    return {
      rebalancePosition,
      simulationResult,
      ...binArrayQuoteResult
    };
  }
  async quoteBinArrayAccountsRentalCost(deposits, withdraws, activeId) {
    const { binArrayBitmap, binArrayIndexes } = getRebalanceBinArrayIndexesAndBitmapCoverage(
      deposits,
      withdraws,
      activeId.toNumber(),
      this.pubkey,
      this.program.programId
    );
    const binArrayPublicKeys = binArrayIndexes.map((index) => {
      const [binArrayPubkey] = deriveBinArray(
        this.pubkey,
        index,
        this.program.programId
      );
      return binArrayPubkey;
    });
    const accountPublicKeys = [...binArrayPublicKeys];
    if (!binArrayBitmap.equals(PublicKey10.default)) {
      accountPublicKeys.push(binArrayBitmap);
    }
    const accounts = await chunkedGetMultipleAccountInfos(
      this.program.provider.connection,
      binArrayPublicKeys
    );
    const binArrayAccounts = accounts.splice(0, binArrayPublicKeys.length);
    let binArrayCount = 0;
    let bitmapExtensionCost = 0;
    const binArraySet = /* @__PURE__ */ new Set();
    for (let i = 0; i < binArrayAccounts.length; i++) {
      const binArrayAccount = binArrayAccounts[i];
      const binArrayPubkey = binArrayPublicKeys[i];
      if (!binArrayAccount) {
        binArrayCount++;
      } else {
        binArraySet.add(binArrayPubkey.toBase58());
      }
    }
    if (!binArrayBitmap.equals(PublicKey10.default)) {
      const bitmapAccount = accounts.pop();
      if (!bitmapAccount) {
        bitmapExtensionCost = BIN_ARRAY_BITMAP_FEE;
      }
    }
    return {
      binArrayCost: binArrayCount * BIN_ARRAY_FEE,
      binArrayCount,
      binArrayExistence: binArraySet,
      bitmapExtensionCost
    };
  }
  /**
   * Simulates a rebalance operation on a position without actually executing it. It's recommended to use simulateRebalancePositionWithXStrategy instead unless you know what you're doing.
   *
   * @param positionAddress The address of the position to simulate rebalancing.
   * @param positionData The PositionData object associated with the position.
   * @param shouldClaimFee True if the fee should be claimed during rebalancing.
   * @param shouldClaimReward True if the reward should be claimed during rebalancing.
   * @param deposits An array of RebalanceWithDeposit objects representing the deposits to simulate.
   * @param withdraws An array of RebalanceWithWithdraw objects representing the withdraws to simulate.
   */
  async simulateRebalancePosition(positionAddress, positionData, shouldClaimFee, shouldClaimReward, deposits, withdraws) {
    const rebalancePosition = await RebalancePosition.create({
      program: this.program,
      positionAddress,
      positionData,
      shouldClaimFee,
      shouldClaimReward,
      pairAddress: this.pubkey
    });
    const simulationResult = await rebalancePosition.simulateRebalance(
      this.program.provider.connection,
      new BN24(this.lbPair.binStep),
      new BN24(this.tokenX.mint.decimals),
      new BN24(this.tokenY.mint.decimals),
      withdraws,
      deposits
    );
    const binArrayQuoteResult = await this.quoteBinArrayAccountsRentalCost(
      simulationResult.depositParams,
      simulationResult.withdrawParams,
      new BN24(rebalancePosition.lbPair.activeId)
    );
    return {
      rebalancePosition,
      simulationResult,
      ...binArrayQuoteResult
    };
  }
  /**
   * Rebalances a position and claim rewards if specified.
   *
   * @param rebalancePositionResponse The result of `simulateRebalancePosition`.
   * @param maxActiveBinSlippage The maximum slippage allowed for active bin selection.
   * @param slippage The slippage tolerance percentage for rebalncing.
   *
   * @returns An object containing the instructions to initialize new bin arrays and the instruction to rebalance the position.
   */
  async rebalancePosition(rebalancePositionResponse, maxActiveBinSlippage, rentPayer, slippage = 100) {
    const { rebalancePosition, simulationResult } = rebalancePositionResponse;
    const { lbPair, shouldClaimFee, shouldClaimReward, owner, address } = rebalancePosition;
    const { depositParams, withdrawParams } = simulationResult;
    const activeId = new BN24(lbPair.activeId);
    const { slices, accounts: transferHookAccounts } = this.getPotentialToken2022IxDataAndAccounts(0 /* Liquidity */);
    const preInstructions = [];
    const harvestRewardRemainingAccountMetas = [];
    if (shouldClaimReward) {
      for (const [idx, reward] of this.lbPair.rewardInfos.entries()) {
        if (!reward.mint.equals(PublicKey10.default)) {
          const rewardTokenInfo = this.rewards[idx];
          slices.push({
            accountsType: {
              transferHookMultiReward: {
                0: idx
              }
            },
            length: rewardTokenInfo.transferHookAccountMetas.length
          });
          transferHookAccounts.push(
            ...rewardTokenInfo.transferHookAccountMetas
          );
          const userTokenRewardAddress = getAssociatedTokenAddressSync2(
            reward.mint,
            owner,
            true,
            rewardTokenInfo.owner
          );
          preInstructions.push(
            createAssociatedTokenAccountIdempotentInstruction2(
              owner,
              userTokenRewardAddress,
              owner,
              reward.mint,
              rewardTokenInfo.owner
            )
          );
          const rewardVault = {
            pubkey: reward.vault,
            isSigner: false,
            isWritable: true
          };
          const userTokenReward = {
            pubkey: userTokenRewardAddress,
            isSigner: false,
            isWritable: true
          };
          const rewardMint = {
            pubkey: reward.mint,
            isSigner: false,
            isWritable: false
          };
          const rewardTokenProgram = {
            pubkey: rewardTokenInfo.owner,
            isSigner: false,
            isWritable: false
          };
          harvestRewardRemainingAccountMetas.push(
            rewardVault,
            userTokenReward,
            rewardMint,
            rewardTokenProgram
          );
        }
      }
    }
    const initBinArrayInstructions = [];
    const { binArrayBitmap, binArrayIndexes } = getRebalanceBinArrayIndexesAndBitmapCoverage(
      depositParams,
      withdrawParams,
      activeId.toNumber(),
      this.pubkey,
      this.program.programId
    );
    const binArrayPublicKeys = binArrayIndexes.map((index) => {
      const [binArrayPubkey] = deriveBinArray(
        this.pubkey,
        index,
        this.program.programId
      );
      return binArrayPubkey;
    });
    const binArrayAccounts = await chunkedGetMultipleAccountInfos(
      this.program.provider.connection,
      binArrayPublicKeys
    );
    for (let i = 0; i < binArrayAccounts.length; i++) {
      const binArrayAccount = binArrayAccounts[i];
      if (!binArrayAccount) {
        const binArrayPubkey = binArrayPublicKeys[i];
        const binArrayIndex = binArrayIndexes[i];
        const initBinArrayIx = await this.program.methods.initializeBinArray(binArrayIndex).accountsPartial({
          binArray: binArrayPubkey,
          funder: owner,
          lbPair: this.pubkey
        }).instruction();
        initBinArrayInstructions.push(initBinArrayIx);
      }
    }
    if (!binArrayBitmap.equals(PublicKey10.default)) {
      const bitmapAccount = await this.program.provider.connection.getAccountInfo(binArrayBitmap);
      if (!bitmapAccount) {
        const initBitmapExtensionIx = await this.program.methods.initializeBinArrayBitmapExtension().accountsPartial({
          binArrayBitmapExtension: binArrayBitmap,
          funder: owner,
          lbPair: this.pubkey,
          rent: SYSVAR_RENT_PUBKEY2
        }).preInstructions([
          ComputeBudgetProgram3.setComputeUnitLimit({
            units: DEFAULT_INIT_BIN_ARRAY_CU
          })
        ]).instruction();
        preInstructions.push(initBitmapExtensionIx);
      }
    }
    const [
      { ataPubKey: userTokenX, ix: createUserTokenXIx },
      { ataPubKey: userTokenY, ix: createUserTokenYIx }
    ] = await Promise.all([
      getOrCreateATAInstruction(
        this.program.provider.connection,
        this.tokenX.publicKey,
        owner,
        this.tokenX.owner
      ),
      getOrCreateATAInstruction(
        this.program.provider.connection,
        this.tokenY.publicKey,
        owner,
        this.tokenY.owner
      )
    ]);
    createUserTokenXIx && preInstructions.push(createUserTokenXIx);
    createUserTokenYIx && preInstructions.push(createUserTokenYIx);
    slippage = capSlippagePercentage(slippage);
    const maxDepositXAmount = getSlippageMaxAmount(
      simulationResult.actualAmountXDeposited,
      slippage
    );
    const maxDepositYAmount = getSlippageMaxAmount(
      simulationResult.actualAmountYDeposited,
      slippage
    );
    const minWithdrawXAmount = getSlippageMinAmount(
      simulationResult.actualAmountXWithdrawn,
      slippage
    );
    const minWithdrawYAmount = getSlippageMinAmount(
      simulationResult.actualAmountYWithdrawn,
      slippage
    );
    const postInstructions = [];
    if (this.tokenX.publicKey.equals(NATIVE_MINT2) && simulationResult.actualAmountXDeposited.gtn(0) && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        owner,
        userTokenX,
        BigInt(simulationResult.actualAmountXDeposited.toString())
      );
      preInstructions.push(...wrapSOLIx);
    }
    if (this.tokenY.publicKey.equals(NATIVE_MINT2) && simulationResult.actualAmountYDeposited.gtn(0) && !this.opt?.skipSolWrappingOperation) {
      const wrapSOLIx = wrapSOLInstruction(
        owner,
        userTokenY,
        BigInt(simulationResult.actualAmountYDeposited.toString())
      );
      preInstructions.push(...wrapSOLIx);
    }
    if ((this.tokenX.publicKey.equals(NATIVE_MINT2) || this.tokenY.publicKey.equals(NATIVE_MINT2)) && !this.opt?.skipSolWrappingOperation) {
      const closeWrappedSOLIx = await unwrapSOLInstruction(owner);
      closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
    }
    const instruction = await this.program.methods.rebalanceLiquidity(
      {
        adds: depositParams,
        removes: withdrawParams,
        activeId: activeId.toNumber(),
        shouldClaimFee,
        shouldClaimReward,
        maxActiveBinSlippage: maxActiveBinSlippage.toNumber(),
        maxDepositXAmount,
        maxDepositYAmount,
        minWithdrawXAmount,
        minWithdrawYAmount,
        shrinkMode: 0 /* ShrinkBoth */,
        padding: REBALANCE_POSITION_PADDING
      },
      {
        slices
      }
    ).accountsPartial({
      lbPair: this.pubkey,
      binArrayBitmapExtension: binArrayBitmap,
      position: address,
      owner,
      userTokenX,
      userTokenY,
      reserveX: this.lbPair.reserveX,
      reserveY: this.lbPair.reserveY,
      tokenXMint: this.tokenX.publicKey,
      tokenYMint: this.tokenY.publicKey,
      tokenXProgram: this.tokenX.owner,
      tokenYProgram: this.tokenY.owner,
      memoProgram: MEMO_PROGRAM_ID,
      rentPayer: rentPayer ?? owner
    }).remainingAccounts(transferHookAccounts).remainingAccounts(
      binArrayPublicKeys.map((pubkey) => {
        return {
          pubkey,
          isSigner: false,
          isWritable: true
        };
      })
    ).instruction();
    const setCUIX = await getEstimatedComputeUnitIxWithBuffer(
      this.program.provider.connection,
      [instruction],
      owner
    );
    const rebalancePositionInstruction = [
      setCUIX,
      ...preInstructions,
      instruction,
      ...postInstructions
    ];
    return {
      initBinArrayInstructions,
      rebalancePositionInstruction
    };
  }
  /**
   * Create an extended empty position.
   *
   * @param lowerBinid The lowest bin of the position.
   * @param upperBinId The highest bin of the position.
   * @param position The public key of the position.
   * @param owner The owner of the position.
   * @returns The instructions to create the extended empty position.
   */
  async createExtendedEmptyPosition(lowerBinid, upperBinId, position, owner) {
    const positionWidth = upperBinId - lowerBinid + 1;
    const basePositionWidth = Math.min(
      positionWidth,
      DEFAULT_BIN_PER_POSITION.toNumber()
    );
    const ixs = await this.createInitAndExtendPositionIx(
      lowerBinid,
      upperBinId,
      basePositionWidth,
      owner,
      position
    );
    const latestBlockhashInfo = await this.program.provider.connection.getLatestBlockhash();
    const tx = new Transaction({
      ...latestBlockhashInfo,
      feePayer: owner
    }).add(...ixs);
    return tx;
  }
  /**
   * Enables permissionless fee claiming for a position.
   * @param
   *    - `position`: The public key of the position account.
   *    - `owner`: The public key of the position owner.
   * @returns {Promise<Transaction>} A transaction that sets the position permission bit for fee claiming.
   */
  async enablePositionPermissionlessClaimFee({
    position,
    owner
  }) {
    const enablePositionPermissionlessClaimFeeIx = await this.program.methods.setPermissionlessOperationBits(
      encodePositionPermissions([0 /* ClaimFee */])
    ).accountsPartial({
      position,
      owner
    }).instruction();
    const latestBlockhashInfo = await this.program.provider.connection.getLatestBlockhash();
    const tx = new Transaction({
      ...latestBlockhashInfo,
      feePayer: owner
    }).add(enablePositionPermissionlessClaimFeeIx);
    return tx;
  }
  /**
   * Creates a limit-order transaction for this LB pair.
   * When `relativeBin` is provided, the `bin.id` in `params.bins` will be treated as relative to the current active bin, which mean bin.id = bin.id + activeId. Otherwise, it will be absolute bin id.
   *
   *
   * @param params Input parameters for placing a limit order.
   * @param params.owner Owner of the token account used by the order.
   * @param params.payer Account paying rent for any newly created accounts.
   * @param params.sender Transaction signer that submits the order.
   * @param params.limitOrder PDA/public key of the limit-order account.
   * @param params.params Limit-order configuration. `padding` is injected by the SDK.
   * @returns A transaction that places the limit order.
   */
  async placeLimitOrder({
    owner,
    payer,
    sender,
    limitOrder,
    params
  }) {
    const isAskSide = Boolean(params.isAskSide);
    const resolvedBinIds = params.bins.map(
      (bin) => params.relativeBin == null ? bin.id : bin.id + this.lbPair.activeId
    );
    const { binArrayIndexes, binArrayAccountMetas, binArrayBitmapExtension } = getBinArrayInfoForNonContiguousBinIds(
      resolvedBinIds,
      this.program.programId,
      this.pubkey
    );
    const createBinArrayIxs = await this.createBinArraysIfNeeded(
      binArrayIndexes,
      payer
    );
    const preInstructions = [...createBinArrayIxs];
    const postInstructions = [];
    if (!binArrayBitmapExtension.equals(this.program.programId) && !this.binArrayBitmapExtension) {
      const initializeBitmapExtensionIx = await this.program.methods.initializeBinArrayBitmapExtension().accountsPartial({
        binArrayBitmapExtension,
        funder: owner,
        lbPair: this.pubkey,
        rent: SYSVAR_RENT_PUBKEY2
      }).instruction();
      preInstructions.push(initializeBitmapExtensionIx);
    }
    const [reserve, tokenMint, tokenProgram, slices, transferHookAccounts] = isAskSide ? [
      this.lbPair.reserveX,
      this.tokenX.mint.address,
      this.tokenX.owner,
      [
        {
          accountsType: {
            transferHookX: {}
          },
          length: this.tokenX.transferHookAccountMetas.length
        }
      ],
      this.tokenX.transferHookAccountMetas
    ] : [
      this.lbPair.reserveY,
      this.tokenY.mint.address,
      this.tokenY.owner,
      [
        {
          accountsType: {
            transferHookY: {}
          },
          length: this.tokenY.transferHookAccountMetas.length
        }
      ],
      this.tokenY.transferHookAccountMetas
    ];
    const userTokenAddress = getAssociatedTokenAddressSync2(
      tokenMint,
      owner,
      true,
      tokenProgram
    );
    if (tokenMint.equals(NATIVE_MINT2) && !this.opt?.skipSolWrappingOperation) {
      const totalAmount = params.bins.reduce(
        (acc, { amount }) => acc.add(amount),
        new BN24(0)
      );
      preInstructions.push(
        createAssociatedTokenAccountIdempotentInstruction2(
          owner,
          userTokenAddress,
          owner,
          NATIVE_MINT2
        )
      );
      const wrapSOLIxX = wrapSOLInstruction(
        sender,
        userTokenAddress,
        BigInt(totalAmount.toString())
      );
      preInstructions.push(...wrapSOLIxX);
      const unwrapSOLIX = unwrapSOLInstruction(sender, true);
      postInstructions.push(unwrapSOLIX);
    }
    const placeLimitOrderIx = await this.program.methods.placeLimitOrder(
      {
        ...params,
        padding: new Array(16).fill(0)
      },
      {
        slices
      }
    ).accountsPartial({
      lbPair: this.pubkey,
      binArrayBitmapExtension,
      reserve,
      tokenMint,
      tokenProgram,
      limitOrder,
      userToken: userTokenAddress,
      sender,
      payer,
      owner
    }).remainingAccounts([...transferHookAccounts, ...binArrayAccountMetas]).preInstructions(preInstructions).postInstructions(postInstructions).instruction();
    const latestBlockhashInfo = await this.program.provider.connection.getLatestBlockhash();
    const tx = new Transaction({
      ...latestBlockhashInfo,
      feePayer: sender
    }).add(...preInstructions, placeLimitOrderIx, ...postInstructions);
    return tx;
  }
  /**
   * Cancels a limit order
   * @param
   *    - `limitOrderPubkey`: The public key of the limit-order account to cancel.
   *    - `owner`: The owner of the limit-order account and transaction fee payer.
   *    - `binIds`: Bin IDs to cancel from the limit order.
   * @returns {Promise<Transaction>} A transaction that cancels the limit order, ensures owner ATAs for both pool
   *    mints (including idempotent creates for non-SOL legs), and unwraps SOL when applicable.
   */
  async cancelLimitOrder({
    limitOrderPubkey,
    owner,
    rentReceiver,
    binIds
  }) {
    const { slices, accounts: transferHookAccounts } = this.getPotentialToken2022IxDataAndAccounts(0 /* Liquidity */);
    const { binArrayAccountMetas, binArrayBitmapExtension } = getBinArrayInfoForNonContiguousBinIds(
      binIds,
      this.program.programId,
      this.pubkey
    );
    const preInstructions = [];
    const postInstructions = [];
    const userTokenX = getAssociatedTokenAddressSync2(
      this.tokenX.mint.address,
      owner,
      true,
      this.tokenX.owner
    );
    const userTokenY = getAssociatedTokenAddressSync2(
      this.tokenY.mint.address,
      owner,
      true,
      this.tokenY.owner
    );
    if (this.tokenX.mint.address.equals(NATIVE_MINT2)) {
      if (!this.opt?.skipSolWrappingOperation) {
        preInstructions.push(
          createAssociatedTokenAccountIdempotentInstruction2(
            owner,
            userTokenX,
            owner,
            this.tokenX.mint.address,
            this.tokenX.owner
          )
        );
        postInstructions.push(unwrapSOLInstruction(owner));
      }
    } else {
      preInstructions.push(
        createAssociatedTokenAccountIdempotentInstruction2(
          owner,
          userTokenX,
          owner,
          this.tokenX.mint.address,
          this.tokenX.owner
        )
      );
    }
    if (this.tokenY.mint.address.equals(NATIVE_MINT2)) {
      if (!this.opt?.skipSolWrappingOperation) {
        preInstructions.push(
          createAssociatedTokenAccountIdempotentInstruction2(
            owner,
            userTokenY,
            owner,
            this.tokenY.mint.address,
            this.tokenY.owner
          )
        );
        postInstructions.push(unwrapSOLInstruction(owner));
      }
    } else {
      preInstructions.push(
        createAssociatedTokenAccountIdempotentInstruction2(
          owner,
          userTokenY,
          owner,
          this.tokenY.mint.address,
          this.tokenY.owner
        )
      );
    }
    const closeLimitOrderIx = await this.program.methods.closeLimitOrderIfEmpty().accountsPartial({
      limitOrder: limitOrderPubkey,
      owner,
      rentReceiver
    }).instruction();
    postInstructions.push(closeLimitOrderIx);
    const cancelLimitOrderIx = await this.program.methods.cancelLimitOrder(binIds, {
      slices
    }).accountsPartial({
      lbPair: this.pubkey,
      reserveX: this.lbPair.reserveX,
      reserveY: this.lbPair.reserveY,
      binArrayBitmapExtension,
      tokenXMint: this.tokenX.mint.address,
      tokenYMint: this.tokenY.mint.address,
      limitOrder: limitOrderPubkey,
      ownerTokenX: userTokenX,
      ownerTokenY: userTokenY,
      owner,
      tokenXProgram: this.tokenX.owner,
      tokenYProgram: this.tokenY.owner,
      memoProgram: MEMO_PROGRAM_ID
    }).remainingAccounts([...transferHookAccounts, ...binArrayAccountMetas]).instruction();
    const latestBlockhashInfo = await this.program.provider.connection.getLatestBlockhash();
    const tx = new Transaction({
      ...latestBlockhashInfo,
      feePayer: owner
    }).add(...preInstructions, cancelLimitOrderIx, ...postInstructions);
    return tx;
  }
  /**
   * Closes a limit-order account if it has no remaining open bins.
   * @param
   *    - `limitOrder`: The public key of the limit-order account to close.
   *    - `owner`: The owner of the limit-order account and transaction fee payer.
   *    - `rentReceiver`: The account that receives reclaimed rent from the closed limit-order account.
   * @returns {Promise<Transaction>} A transaction that closes the limit-order account when it is empty.
   */
  async closeLimitOrderIfEmpty({
    limitOrder,
    owner,
    rentReceiver
  }) {
    const closeLimitOrderIx = await this.program.methods.closeLimitOrderIfEmpty().accountsPartial({
      limitOrder,
      owner,
      rentReceiver
    }).instruction();
    const latestBlockhashInfo = await this.program.provider.connection.getLatestBlockhash();
    const tx = new Transaction({
      ...latestBlockhashInfo,
      feePayer: owner
    }).add(closeLimitOrderIx);
    return tx;
  }
  async createInitAndExtendPositionIx(lowerBinId, upperBinId, basePositionWidth, user, position) {
    const createPositionIx = await this.program.methods.initializePosition(lowerBinId, basePositionWidth).accountsPartial({
      payer: user,
      position,
      lbPair: this.pubkey,
      owner: user,
      rent: SYSVAR_RENT_PUBKEY2
    }).instruction();
    const extendedBinCount = getExtendedPositionBinCount(
      new BN24(lowerBinId),
      new BN24(upperBinId)
    );
    if (extendedBinCount.gt(new BN24(0))) {
      const extendPositionIxs = await this.increasePositionLengthIxs(
        position,
        1 /* Upper */,
        extendedBinCount,
        user,
        user,
        false,
        false
      );
      const extendPositionDefaultCU = getDefaultExtendPositionCU(1 /* Upper */) * extendedBinCount.toNumber();
      return [
        ComputeBudgetProgram3.setComputeUnitLimit({
          units: Math.min(
            DEFAULT_INIT_POSITION_CU + extendPositionDefaultCU,
            14e5
          )
        }),
        createPositionIx,
        ...extendPositionIxs.flat()
      ];
    } else {
      return [
        ComputeBudgetProgram3.setComputeUnitLimit({
          units: DEFAULT_INIT_POSITION_CU
        }),
        createPositionIx
      ];
    }
  }
  async increasePositionLengthIxs(position, side, length, funder, positionOwner, includeSetCuIx = true, allowParallelExecution = true) {
    const groupedIxs = [];
    const promises = [];
    for (let i = 0; i < length.toNumber(); i += MAX_RESIZE_LENGTH.toNumber()) {
      const lengthToAdd = Math.min(
        length.toNumber() - i,
        MAX_RESIZE_LENGTH.toNumber()
      );
      const setCuIx = ComputeBudgetProgram3.setComputeUnitLimit({
        units: getDefaultExtendPositionCU(side)
      });
      const ixPromise = this.program.methods.increasePositionLength(lengthToAdd, Number(side)).accountsPartial({
        lbPair: this.pubkey,
        position,
        owner: positionOwner,
        funder
      }).instruction().then((increasePositionLengthIx) => {
        if (allowParallelExecution) {
          increasePositionLengthIx.keys.push({
            isSigner: false,
            isWritable: false,
            pubkey: PublicKey10.unique()
          });
        }
        const ixs = [increasePositionLengthIx];
        if (includeSetCuIx) {
          ixs.unshift(setCuIx);
        }
        groupedIxs.push(ixs);
      });
      promises.push(ixPromise);
    }
    await Promise.all(promises);
    return groupedIxs;
  }
  /** Private static method */
  static async getBinArrays(program, lbPairPubkey) {
    return program.account.binArray.all([binArrayLbPairFilter(lbPairPubkey)]);
  }
  static async processPosition(program, lbPair, clock, position, baseMint, quoteMint, rewardMint0, rewardMint1, binArrayMap) {
    const lbPairKey = position.lbPair();
    const lowerBinId = position.lowerBinId();
    const upperBinId = position.upperBinId();
    const posShares = position.liquidityShares();
    const lastUpdatedAt = position.lastUpdatedAt();
    const feeInfos = position.feeInfos();
    const totalClaimedFeeXAmount = position.totalClaimedFeeXAmount();
    const totalClaimedFeeYAmount = position.totalClaimedFeeYAmount();
    const positionRewardInfos = position.rewardInfos();
    const feeOwner = position.feeOwner();
    const bins = this.getBinsBetweenLowerAndUpperBound(
      lbPairKey,
      lbPair,
      lowerBinId.toNumber(),
      upperBinId.toNumber(),
      baseMint.decimals,
      quoteMint.decimals,
      binArrayMap,
      program.programId
    );
    if (!bins.length)
      return null;
    const positionData = [];
    let totalXAmount = new Decimal11(0);
    let totalYAmount = new Decimal11(0);
    const ZERO = new BN24(0);
    let feeX = ZERO;
    let feeY = ZERO;
    let rewards = [ZERO, ZERO];
    bins.forEach((bin, idx) => {
      const binSupply = bin.supply;
      const posShare = posShares[idx];
      const posBinRewardInfo = positionRewardInfos[idx];
      const positionXAmount = binSupply.eq(ZERO) ? ZERO : posShare.mul(bin.xAmount).div(binSupply);
      const positionYAmount = binSupply.eq(ZERO) ? ZERO : posShare.mul(bin.yAmount).div(binSupply);
      totalXAmount = totalXAmount.add(new Decimal11(positionXAmount.toString()));
      totalYAmount = totalYAmount.add(new Decimal11(positionYAmount.toString()));
      const feeInfo = feeInfos[idx];
      const newFeeX = posShare.isZero() ? new BN24(0) : mulShr(
        posShares[idx].shrn(SCALE_OFFSET),
        bin.feeAmountXPerTokenStored.sub(feeInfo.feeXPerTokenComplete),
        SCALE_OFFSET,
        1 /* Down */
      );
      const newFeeY = posShare.isZero() ? new BN24(0) : mulShr(
        posShares[idx].shrn(SCALE_OFFSET),
        bin.feeAmountYPerTokenStored.sub(feeInfo.feeYPerTokenComplete),
        SCALE_OFFSET,
        1 /* Down */
      );
      const claimableFeeX = newFeeX.add(feeInfo.feeXPending);
      const claimableFeeY = newFeeY.add(feeInfo.feeYPending);
      feeX = feeX.add(claimableFeeX);
      feeY = feeY.add(claimableFeeY);
      const claimableRewardsInBin = [new BN24(0), new BN24(0)];
      if (!isSupportLimitOrder(lbPair)) {
        for (let j = 0; j < claimableRewardsInBin.length; j++) {
          const pairRewardInfo = lbPair.rewardInfos[j];
          if (!pairRewardInfo.mint.equals(PublicKey10.default)) {
            let rewardPerTokenStored = bin.rewardPerTokenStored[j];
            if (bin.binId == lbPair.activeId && !bin.supply.isZero()) {
              const currentTime = new BN24(
                Math.min(
                  clock.unixTimestamp.toNumber(),
                  pairRewardInfo.rewardDurationEnd.toNumber()
                )
              );
              const delta2 = currentTime.sub(pairRewardInfo.lastUpdateTime);
              const liquiditySupply = bin.supply.shrn(SCALE_OFFSET);
              const rewardPerTokenStoredDelta = pairRewardInfo.rewardRate.mul(delta2).div(new BN24(15)).div(liquiditySupply);
              rewardPerTokenStored = rewardPerTokenStored.add(
                rewardPerTokenStoredDelta
              );
            }
            const delta = rewardPerTokenStored.sub(
              posBinRewardInfo.rewardPerTokenCompletes[j]
            );
            const newReward = posShares[idx].isZero() ? new BN24(0) : mulShr(
              delta,
              posShares[idx].shrn(SCALE_OFFSET),
              SCALE_OFFSET,
              1 /* Down */
            );
            const claimableReward = newReward.add(
              posBinRewardInfo.rewardPendings[j]
            );
            claimableRewardsInBin[j] = claimableRewardsInBin[j].add(claimableReward);
            rewards[j] = rewards[j].add(claimableReward);
          }
        }
      }
      positionData.push({
        binId: bin.binId,
        price: bin.price,
        pricePerToken: bin.pricePerToken,
        binXAmount: bin.xAmount.toString(),
        binYAmount: bin.yAmount.toString(),
        binLiquidity: binSupply.toString(),
        positionLiquidity: posShare.toString(),
        positionXAmount: positionXAmount.toString(),
        positionYAmount: positionYAmount.toString(),
        positionFeeXAmount: claimableFeeX.toString(),
        positionFeeYAmount: claimableFeeY.toString(),
        positionRewardAmount: claimableRewardsInBin.map(
          (amount) => amount.toString()
        )
      });
    });
    const currentEpoch = clock.epoch.toNumber();
    const feeXExcludeTransferFee = calculateTransferFeeExcludedAmount(
      feeX,
      baseMint,
      currentEpoch
    ).amount;
    const feeYExcludeTransferFee = calculateTransferFeeExcludedAmount(
      feeY,
      quoteMint,
      currentEpoch
    ).amount;
    const rewardOne = rewards[0];
    const rewardTwo = rewards[1];
    let rewardOneExcludeTransferFee = new BN24(0);
    let rewardTwoExcludeTransferFee = new BN24(0);
    if (rewardMint0) {
      rewardOneExcludeTransferFee = calculateTransferFeeExcludedAmount(
        rewardOne,
        rewardMint0,
        currentEpoch
      ).amount;
    }
    if (rewardMint1) {
      rewardTwoExcludeTransferFee = calculateTransferFeeExcludedAmount(
        rewardTwo,
        rewardMint1,
        currentEpoch
      ).amount;
    }
    const totalXAmountExcludeTransferFee = calculateTransferFeeExcludedAmount(
      new BN24(totalXAmount.floor().toString()),
      baseMint,
      currentEpoch
    ).amount;
    const totalYAmountExcludeTransferFee = calculateTransferFeeExcludedAmount(
      new BN24(totalYAmount.floor().toString()),
      quoteMint,
      currentEpoch
    ).amount;
    return {
      totalXAmount: totalXAmount.toString(),
      totalYAmount: totalYAmount.toString(),
      positionBinData: positionData,
      lastUpdatedAt,
      lowerBinId: lowerBinId.toNumber(),
      upperBinId: upperBinId.toNumber(),
      feeX,
      feeY,
      rewardOne,
      rewardTwo,
      feeOwner,
      totalClaimedFeeXAmount,
      totalClaimedFeeYAmount,
      totalXAmountExcludeTransferFee,
      totalYAmountExcludeTransferFee,
      rewardOneExcludeTransferFee,
      rewardTwoExcludeTransferFee,
      feeXExcludeTransferFee,
      feeYExcludeTransferFee,
      owner: position.owner()
    };
  }
  static getBinsBetweenLowerAndUpperBound(lbPairKey, lbPair, lowerBinId, upperBinId, baseTokenDecimal, quoteTokenDecimal, binArrayMap, programId) {
    const lowerBinArrayIndex = binIdToBinArrayIndex(new BN24(lowerBinId));
    const upperBinArrayIndex = binIdToBinArrayIndex(new BN24(upperBinId));
    let bins = [];
    for (let binArrayIndex = lowerBinArrayIndex.toNumber(); binArrayIndex <= upperBinArrayIndex.toNumber(); binArrayIndex++) {
      const binArrayIndexBN = new BN24(binArrayIndex);
      const binArrayKey = deriveBinArray(
        lbPairKey,
        binArrayIndexBN,
        programId
      )[0];
      const [lowerBinIdForBinArray] = getBinArrayLowerUpperBinId(binArrayIndexBN);
      const binArray = binArrayMap.get(binArrayKey.toBase58());
      for (let i = 0; i < MAX_BIN_ARRAY_SIZE.toNumber(); i++) {
        const binId = lowerBinIdForBinArray.toNumber() + i;
        if (binId >= lowerBinId && binId <= upperBinId) {
          if (!binArray) {
            bins.push(
              BinLiquidity.empty(
                binId,
                lbPair.binStep,
                baseTokenDecimal,
                quoteTokenDecimal,
                BIN_ARRAY_DEFAULT_VERSION
              )
            );
          } else {
            const bin = binArray.bins[i];
            bins.push(
              BinLiquidity.fromBin(
                bin,
                binId,
                lbPair.binStep,
                baseTokenDecimal,
                quoteTokenDecimal,
                binArray.version,
                lbPair
              )
            );
          }
        }
      }
    }
    return bins;
  }
  /** Private method */
  processXYAmountDistribution(xYAmountDistribution) {
    let currentBinId = null;
    const xAmountDistribution = [];
    const yAmountDistribution = [];
    const binIds = [];
    xYAmountDistribution.forEach((binAndAmount) => {
      xAmountDistribution.push(binAndAmount.xAmountBpsOfTotal);
      yAmountDistribution.push(binAndAmount.yAmountBpsOfTotal);
      binIds.push(binAndAmount.binId);
      if (currentBinId && binAndAmount.binId !== currentBinId + 1) {
        throw new Error("Discontinuous Bin ID");
      } else {
        currentBinId = binAndAmount.binId;
      }
    });
    return {
      lowerBinId: xYAmountDistribution[0].binId,
      upperBinId: xYAmountDistribution[xYAmountDistribution.length - 1].binId,
      xAmountDistribution,
      yAmountDistribution,
      binIds
    };
  }
  async getBins(lbPairPubKey, lowerBinId, upperBinId, baseTokenDecimal, quoteTokenDecimal, lowerBinArray, upperBinArray) {
    const lowerBinArrayIndex = binIdToBinArrayIndex(new BN24(lowerBinId));
    const upperBinArrayIndex = binIdToBinArrayIndex(new BN24(upperBinId));
    const hasCachedLowerBinArray = lowerBinArray != null;
    const hasCachedUpperBinArray = upperBinArray != null;
    const isSingleBinArray = lowerBinArrayIndex.eq(upperBinArrayIndex);
    const lowerBinArrayIndexOffset = hasCachedLowerBinArray ? 1 : 0;
    const upperBinArrayIndexOffset = hasCachedUpperBinArray ? -1 : 0;
    const binArrayPubkeys = range(
      lowerBinArrayIndex.toNumber() + lowerBinArrayIndexOffset,
      upperBinArrayIndex.toNumber() + upperBinArrayIndexOffset,
      (i) => deriveBinArray(lbPairPubKey, new BN24(i), this.program.programId)[0]
    );
    const fetchedBinArrays = binArrayPubkeys.length !== 0 ? await this.program.account.binArray.fetchMultiple(binArrayPubkeys) : [];
    const binArrays = [
      ...hasCachedLowerBinArray ? [lowerBinArray] : [],
      ...fetchedBinArrays,
      ...hasCachedUpperBinArray && !isSingleBinArray ? [upperBinArray] : []
    ];
    const binsById = new Map(
      binArrays.filter((x) => x != null).flatMap(({ bins, index }) => {
        const [lowerBinId2] = getBinArrayLowerUpperBinId(index);
        return bins.map(
          (b, i) => [lowerBinId2.toNumber() + i, b]
        );
      })
    );
    const version = binArrays.find((binArray) => binArray != null)?.version ?? 1;
    return Array.from(
      enumerateBins(
        binsById,
        lowerBinId,
        upperBinId,
        this.lbPair.binStep,
        baseTokenDecimal,
        quoteTokenDecimal,
        version,
        this.lbPair
      )
    );
  }
  async binArraysToBeCreate(lowerBinArrayIndex, upperBinArrayIndex) {
    const binArrayIndexes = Array.from(
      { length: upperBinArrayIndex.sub(lowerBinArrayIndex).toNumber() + 1 },
      (_, index) => index + lowerBinArrayIndex.toNumber()
    ).map((idx) => new BN24(idx));
    const binArrays = [];
    for (const idx of binArrayIndexes) {
      const [binArrayPubKey] = deriveBinArray(
        this.pubkey,
        idx,
        this.program.programId
      );
      binArrays.push(binArrayPubKey);
    }
    const binArrayAccounts = await this.program.provider.connection.getMultipleAccountsInfo(binArrays);
    return binArrayAccounts.filter((binArray) => binArray === null).map((_, index) => binArrays[index]);
  }
  async createBinArraysIfNeeded(binArrayIndexes, funder) {
    const ixs = [];
    for (const idx of binArrayIndexes) {
      const [binArrayKey] = deriveBinArray(
        this.pubkey,
        idx,
        this.program.programId
      );
      const binArrayAccount = await this.program.provider.connection.getAccountInfo(binArrayKey);
      if (binArrayAccount === null) {
        ixs.push(
          await this.program.methods.initializeBinArray(idx).accountsPartial({
            binArray: binArrayKey,
            funder,
            lbPair: this.pubkey
          }).instruction()
        );
      }
    }
    return ixs;
  }
  static updateVolatilityAccumulator(vParameter, sParameter, activeId) {
    const deltaId = Math.abs(vParameter.indexReference - activeId);
    const newVolatilityAccumulator = vParameter.volatilityReference + deltaId * BASIS_POINT_MAX;
    vParameter.volatilityAccumulator = Math.min(
      newVolatilityAccumulator,
      sParameter.maxVolatilityAccumulator
    );
  }
  static updateReference(activeId, vParameter, sParameter, currentTimestamp) {
    const elapsed = currentTimestamp - vParameter.lastUpdateTimestamp.toNumber();
    if (elapsed >= sParameter.filterPeriod) {
      vParameter.indexReference = activeId;
      if (elapsed < sParameter.decayPeriod) {
        const decayedVolatilityReference = Math.floor(
          vParameter.volatilityAccumulator * sParameter.reductionFactor / BASIS_POINT_MAX
        );
        vParameter.volatilityReference = decayedVolatilityReference;
      } else {
        vParameter.volatilityReference = 0;
      }
    }
  }
  async createClaimBuildMethod({
    owner,
    position
  }) {
    const maybeClaimableBinRange = getPositionLowerUpperBinIdWithLiquidity(
      position.positionData
    );
    if (!maybeClaimableBinRange)
      return [];
    const { lowerBinId, upperBinId } = maybeClaimableBinRange;
    const chunkedBinRange = chunkBinRange(
      lowerBinId.toNumber(),
      upperBinId.toNumber()
    );
    const claimTransactions = [];
    for (const {
      lowerBinId: chunkedLowerBinId,
      upperBinId: chunkedUpperBinId
    } of chunkedBinRange) {
      const binArrayAccountsMeta = getBinArrayAccountMetasCoverage(
        new BN24(chunkedLowerBinId),
        new BN24(chunkedUpperBinId),
        this.pubkey,
        this.program.programId
      );
      for (let i = 0; i < 2; i++) {
        const rewardInfo = this.lbPair.rewardInfos[i];
        if (!rewardInfo || rewardInfo.mint.equals(PublicKey10.default))
          continue;
        const preInstructions = [];
        const userRewardToken = getAssociatedTokenAddressSync2(
          rewardInfo.mint,
          owner,
          true,
          this.rewards[i].owner
        );
        const createUserTokenIx = createAssociatedTokenAccountIdempotentInstruction2(
          owner,
          userRewardToken,
          owner,
          rewardInfo.mint,
          this.rewards[i].owner
        );
        preInstructions.push(createUserTokenIx);
        const { slices, accounts: transferHookAccounts } = this.getPotentialToken2022IxDataAndAccounts(1 /* Reward */, i);
        const claimTransaction = await this.program.methods.claimReward2(new BN24(i), chunkedLowerBinId, chunkedUpperBinId, {
          slices
        }).accountsPartial({
          lbPair: this.pubkey,
          sender: owner,
          position: position.publicKey,
          rewardVault: rewardInfo.vault,
          rewardMint: rewardInfo.mint,
          tokenProgram: this.rewards[i].owner,
          userTokenAccount: userRewardToken,
          memoProgram: MEMO_PROGRAM_ID
        }).remainingAccounts(transferHookAccounts).remainingAccounts(binArrayAccountsMeta).preInstructions(preInstructions).transaction();
        claimTransactions.push(claimTransaction);
      }
    }
    return claimTransactions;
  }
  async createClaimSwapFeeMethod({
    owner,
    position
  }) {
    const maybeClaimableBinRange = getPositionLowerUpperBinIdWithLiquidity(
      position.positionData
    );
    if (!maybeClaimableBinRange)
      return [];
    const { lowerBinId, upperBinId } = maybeClaimableBinRange;
    const chunkedBinRange = chunkBinRange(
      lowerBinId.toNumber(),
      upperBinId.toNumber()
    );
    const claimFeeTxs = [];
    for (const {
      lowerBinId: chunkedLowerBinId,
      upperBinId: chunkedUpperBinId
    } of chunkedBinRange) {
      const binArrayAccountsMeta = getBinArrayAccountMetasCoverage(
        new BN24(chunkedLowerBinId),
        new BN24(chunkedUpperBinId),
        this.pubkey,
        this.program.programId
      );
      const { feeOwner } = position.positionData;
      const walletToReceiveFee = feeOwner.equals(PublicKey10.default) ? owner : feeOwner;
      const preInstructions = [];
      const userTokenX = getAssociatedTokenAddressSync2(
        this.lbPair.tokenXMint,
        walletToReceiveFee,
        true,
        this.tokenX.owner
      );
      const userTokenY = getAssociatedTokenAddressSync2(
        this.lbPair.tokenYMint,
        walletToReceiveFee,
        true,
        this.tokenY.owner
      );
      const createUserTokenXIx = createAssociatedTokenAccountIdempotentInstruction2(
        owner,
        userTokenX,
        walletToReceiveFee,
        this.lbPair.tokenXMint,
        this.tokenX.owner
      );
      const createUserTokenYIx = createAssociatedTokenAccountIdempotentInstruction2(
        owner,
        userTokenY,
        walletToReceiveFee,
        this.lbPair.tokenYMint,
        this.tokenY.owner
      );
      preInstructions.push(createUserTokenXIx);
      preInstructions.push(createUserTokenYIx);
      const postInstructions = [];
      if ([
        this.tokenX.publicKey.toBase58(),
        this.tokenY.publicKey.toBase58()
      ].includes(NATIVE_MINT2.toBase58()) && !this.opt?.skipSolWrappingOperation) {
        const closeWrappedSOLIx = await unwrapSOLInstruction(owner);
        closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
      }
      const { slices, accounts: transferHookAccounts } = this.getPotentialToken2022IxDataAndAccounts(0 /* Liquidity */);
      const claimFeeTx = await this.program.methods.claimFee2(chunkedLowerBinId, chunkedUpperBinId, {
        slices
      }).accountsPartial({
        lbPair: this.pubkey,
        sender: owner,
        position: position.publicKey,
        reserveX: this.lbPair.reserveX,
        reserveY: this.lbPair.reserveY,
        tokenProgramX: this.tokenX.owner,
        tokenProgramY: this.tokenY.owner,
        tokenXMint: this.tokenX.publicKey,
        tokenYMint: this.tokenY.publicKey,
        userTokenX,
        userTokenY,
        memoProgram: MEMO_PROGRAM_ID
      }).remainingAccounts(transferHookAccounts).remainingAccounts(binArrayAccountsMeta).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
      claimFeeTxs.push(claimFeeTx);
    }
    return claimFeeTxs;
  }
  getPotentialToken2022IxDataAndAccounts(actionType, rewardIndex) {
    if (actionType == 0 /* Liquidity */) {
      return {
        slices: [
          {
            accountsType: {
              transferHookX: {}
            },
            length: this.tokenX.transferHookAccountMetas.length
          },
          {
            accountsType: {
              transferHookY: {}
            },
            length: this.tokenY.transferHookAccountMetas.length
          }
        ],
        accounts: this.tokenX.transferHookAccountMetas.concat(
          this.tokenY.transferHookAccountMetas
        )
      };
    }
    return {
      slices: [
        {
          accountsType: {
            transferHookReward: {}
          },
          length: this.rewards[rewardIndex].transferHookAccountMetas.length
        }
      ],
      accounts: this.rewards[rewardIndex].transferHookAccountMetas
    };
  }
  /**
   * Fetches the oracle account and returns an IDynamicOracle instance that can be
   * used to query TWAP (Time-Weighted Average Price) data.
   *
   * @returns An IDynamicOracle instance with methods like getActiveIdByTime,
   * getPriceByTime, getUiPriceByTime, etc.
   */
  async getOracle() {
    const oracleAddress = this.lbPair.oracle;
    const [oracleAccountInfo, lbPairAccountInfo] = await this.program.provider.connection.getMultipleAccountsInfo([
      oracleAddress,
      this.pubkey
    ]);
    const lbPairState = decodeAccount(
      this.program,
      "lbPair",
      lbPairAccountInfo.data
    );
    return wrapOracle(
      oracleAddress,
      oracleAccountInfo.data,
      this.lbPair.binStep,
      new BN24(lbPairState.activeId),
      this.tokenX.mint.decimals,
      this.tokenY.mint.decimals,
      this.program
    );
  }
  /**
   * Returns a transaction to increase the oracle observation storage length.
   * A longer oracle stores more historical data, enabling TWAP queries over
   * longer time ranges.
   *
   * @param lengthToAdd - Number of observation slots to add.
   * @param funder - The public key of the account funding the reallocation.
   * @returns A Transaction that can be signed and sent.
   */
  async increaseOracleLength(lengthToAdd, funder) {
    const oracleAddress = this.lbPair.oracle;
    const increaseOracleLengthIx = await this.program.methods.increaseOracleLength(lengthToAdd).accountsPartial({
      oracle: oracleAddress,
      funder
    }).instruction();
    const { blockhash, lastValidBlockHeight } = await this.program.provider.connection.getLatestBlockhash("confirmed");
    return new Transaction({
      blockhash,
      lastValidBlockHeight,
      feePayer: funder
    }).add(increaseOracleLengthIx);
  }
};

// src/index.ts
var src_default = DLMM;
export {
  ADMIN,
  ALT_ADDRESS,
  ActionType,
  ActivationType,
  BASIS_POINT_MAX,
  BIN_ARRAY_BITMAP_FEE,
  BIN_ARRAY_BITMAP_FEE_BN,
  BIN_ARRAY_BITMAP_SIZE,
  BIN_ARRAY_DEFAULT_VERSION,
  BIN_ARRAY_FEE,
  BIN_ARRAY_FEE_BN,
  BinLiquidity,
  BitmapType,
  ClockLayout,
  CollectFeeMode,
  ConcreteFunctionType,
  DEFAULT_BIN_PER_POSITION,
  DLMMError,
  DlmmSdkError,
  DynamicOracle,
  EXTENSION_BINARRAY_BITMAP_SIZE,
  FEE_PRECISION,
  FunctionType,
  idl_default as IDL,
  ILM_BASE,
  LBCLMM_PROGRAM_IDS,
  LIMIT_ORDER_BIN_DATA_SIZE,
  LIMIT_ORDER_FEE_SHARE,
  LIMIT_ORDER_MIN_SIZE,
  LimitOrderStatus,
  MAX_ACTIVE_BIN_SLIPPAGE,
  MAX_BINS_PER_POSITION,
  MAX_BIN_ARRAY_SIZE,
  MAX_BIN_ID_PER_BIN_STEP,
  MAX_BIN_LENGTH_ALLOWED_IN_ONE_TX,
  MAX_BIN_PER_LIMIT_ORDER,
  MAX_CLAIM_ALL_ALLOWED,
  MAX_EXTRA_BIN_ARRAYS,
  MAX_FEE_RATE,
  MAX_RESIZE_LENGTH,
  MEMO_PROGRAM_ID,
  Network,
  Observation,
  POOL_FEE,
  POOL_FEE_BN,
  POSITION_BIN_DATA_SIZE,
  POSITION_FEE,
  POSITION_FEE_BN,
  POSITION_MAX_LENGTH,
  POSITION_MIN_SIZE,
  PRECISION,
  PairStatus,
  PairType,
  PositionPermission,
  PositionV2Wrapper,
  PositionVersion,
  REBALANCE_POSITION_PADDING,
  RebalancePosition,
  ResizeSide,
  Rounding,
  SCALE,
  SCALE_OFFSET,
  SIMULATION_USER,
  ShrinkMode,
  Strategy,
  StrategyType,
  TOKEN_ACCOUNT_FEE,
  TOKEN_ACCOUNT_FEE_BN,
  U64_MAX,
  autoFillXByStrategy,
  autoFillXByWeight,
  autoFillYByStrategy,
  autoFillYByWeight,
  binArrayLbPairFilter,
  binDeltaToMinMaxBinId,
  binIdToBinArrayIndex,
  buildBitFlagAndNegateStrategyParameters,
  buildLiquidityStrategyParameters,
  calculateBidAskDistribution,
  calculateNormalDistribution,
  calculatePositionSize,
  calculateSpotDistribution,
  calculateTransferFeeExcludedAmount,
  calculateTransferFeeIncludedAmount,
  capSlippagePercentage,
  chunkBinRange,
  chunkBinRangeIntoExtendedPositions,
  chunkDepositWithRebalanceEndpoint,
  chunkPositionBinRange,
  chunkedFetchMultipleBinArrayBitmapExtensionAccount,
  chunkedFetchMultiplePoolAccount,
  chunkedGetMultipleAccountInfos,
  chunkedGetProgramAccounts,
  chunks,
  compressBinAmount,
  computeBaseFactorFromFeeBps,
  computeFee,
  computeFeeFromAmount,
  computeProtocolFee,
  createProgram,
  decodeAccount,
  decodeExtendedPosition,
  decodeRewardPerTokenStored,
  src_default as default,
  deriveBinArray,
  deriveBinArrayBitmapExtension,
  deriveCustomizablePermissionlessLbPair,
  deriveEventAuthority,
  deriveLbPair,
  deriveLbPair2,
  deriveLbPairWithPresetParamWithIndexKey,
  deriveOperator,
  deriveOracle,
  derivePermissionLbPair,
  derivePlaceHolderAccountMeta,
  derivePosition,
  derivePresetParameter,
  derivePresetParameter2,
  derivePresetParameterWithIndex,
  deriveReserve,
  deriveRewardVault,
  deriveTokenBadge,
  distributeAmountToCompressedBinsByRatio,
  encodePositionPermissions,
  enumerateBins,
  findNextBinArrayIndexWithLiquidity,
  findNextBinArrayWithLiquidity,
  findOptimumDecompressMultiplier,
  fromWeightDistributionToAmount,
  fromWeightDistributionToAmountOneSide,
  generateAmountForBinRange,
  generateBinAmount,
  getAccountDiscriminator,
  getAmountIn,
  getAmountInBinsAskSide,
  getAmountInBinsBidSide,
  getAmountOut,
  getAndCapMaxActiveBinSlippage,
  getAutoFillAmountByRebalancedPosition,
  getBaseFee,
  getBinArrayAccountMetasCoverage,
  getBinArrayIndexesCoverage,
  getBinArrayInfoForNonContiguousBinIds,
  getBinArrayKeysCoverage,
  getBinArrayLowerUpperBinId,
  getBinArraysRequiredByPositionRange,
  getBinArraysRequiredByPositionRange2,
  getBinCount,
  getBinFromBinArray,
  getBinIdIndexInBinArray,
  getBinMaxAmountOut,
  getC,
  getEstimatedComputeUnitIxWithBuffer,
  getEstimatedComputeUnitUsageWithBuffer,
  getExcludedFeeAmount,
  getExtendedPositionBinCount,
  getExtraAccountMetasForTransferHook,
  getFeeMode,
  getIncludedFeeAmount,
  getLimitOrderLiquidity,
  getLiquidityStrategyParameterBuilder,
  getMultipleMintsExtraAccountMetasForTransferHook,
  getOrCreateATAInstruction,
  getPositionCount,
  getPositionCountByBinCount,
  getPositionExpandRentExemption,
  getPositionLowerUpperBinIdWithLiquidity,
  getPositionRentExemption,
  getPriceOfBinByBinId,
  getQPriceBaseFactor,
  getQPriceFromId,
  getRebalanceBinArrayIndexesAndBitmapCoverage,
  getSlippageMaxAmount,
  getSlippageMinAmount,
  getTokenBalance,
  getTokenDecimals,
  getTokenProgramId,
  getTokensMintFromPoolAddress,
  getTotalFee,
  getVariableFee,
  isBinIdWithinBinArray,
  isOverflowDefaultBinArrayBitmap,
  isPositionNoFee,
  isPositionNoReward,
  isSupportLimitOrder,
  limitOrderFilter,
  limitOrderLbPairFilter,
  limitOrderOwnerFilter,
  mulDiv,
  mulShr,
  parseLogs,
  positionLbPairFilter,
  positionOwnerFilter,
  positionV2Filter,
  presetParameter2BaseFactorFilter,
  presetParameter2BaseFeePowerFactor,
  presetParameter2BinStepFilter,
  range,
  resetUninvolvedLiquidityParams,
  shlDiv,
  splitFee,
  suggestBalancedXParametersFromY,
  suggestBalancedYParametersFromX,
  swapExactInQuoteAtBin,
  swapExactOutQuoteAtBin,
  toAmountAskSide,
  toAmountBidSide,
  toAmountBothSide,
  toAmountIntoBins,
  toAmountsBothSideByStrategy,
  toStrategyParameters,
  toWeightDistribution,
  unwrapSOLInstruction,
  wrapOracle,
  wrapPosition,
  wrapSOLInstruction
};
//# sourceMappingURL=index.mjs.map