npm package: @luckyswaps/sdk
Description: LuckySwaps integrates tightly with Jupiter and thus uses mostly similar interfaces. If you ever integrated with Jupiter, it should be easy for you to also integrate with Luckyswaps.
Latest version: 1.4.1

# Luckyswaps SDK

LuckySwaps integrates tightly with Jupiter and thus uses mostly similar
interfaces. If you ever integrated with Jupiter, it should be easy for you to
also integrate with Luckyswaps.

## Howto

### Integrate with LuckySwaps using the SDK

#### 1. Install required libraries

Running this example requires a minimum of [NodeJS 16](https://nodejs.org/en/). In your command line terminal, install the libraries.

```shell
npm i @luckyswaps/sdk
```

#### 2. Get a program instance

```typescript
import { PublicKey, Keypair } from "@solana/web3.js";
import assert from "assert";
import {
  getProgram,
  swap,
  LuckySwapParams,
  MAX_THRESHOLD,
} from "@luckyswaps/sdk";

const keyPair = Keypair.generate();
const program = getProgram("https://api.mainnet-beta.solana.com", keyPair);
```

#### 4. Get the route for a swap

Here, we are getting a quote to swap from SOL to USDC.

```js
// Swapping SOL to USDC with input 0.1 SOL and 0.5% slippage
const params: LuckySwapParams = {

  // Payer that signs the transactions
  payerAccount: new PublicKey(
    "G2FJbtHdaBP5qaFTKyBuTGYHqenTFFpmpz2DSD5A5BH7",
  ),

  // input and output mint (will be used for Jupiter swap)
  inputMint: new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), // USDC
  outputMint: new PublicKey("So11111111111111111111111111111111111111112"), // WSOL

  // associated token accounts for both mint owned by the user
  userSourceAccount: new PublicKey(
    "CqMKa8z4WHpcW4pR7vWEAB96nerRPwBYi1ZJJhsP4bNw",
  ),
  userTargetAccount: new PublicKey(
    "FBAoSPT2L5qJJPmMJ1w9uo9ExuTXC4SHK4322ESuBpg7",
  ),

  // a reference to our program (e.g. API connection)
  program: program,

  // The amount to swap (ExactIn)
  amount: amount,

  // The threshold defines the winning probability and the multiplier
  // if you want a 50% win chance (including house-edge, you chose multiplier: 2)
  threshold: Math.round(MAX_THRESHOLD / multiplier),

  // optional parameters when calling /quote on jupiter
  // https://station.jup.ag/api-v6/get-quote
  jupiterQuoteParams: {},

  // optional parameters when calling /swap-instruction on jupiter
  // https://station.jup.ag/api-v6/post-swap-instructions
  jupiterSwapParams: {},
};
```

#### 5. Get the serialized transactions to perform the swap

Once we have the quote, we need to serialize the quote into a swap transaction that can be submitted on chain.

```js
// get serialized transactions for the swap
const instructions = await swap(params);
```

The returned `instructions` are identical to what you would expect when calling
`https://quote-api.jup.ag/v6/swap-instructions`.

#### 6. Deserialize and sign the transaction

The following is standard Jupiter

```typescript
const {
  tokenLedgerInstruction: tokenLedgerPayload, // If you are using `useTokenLedger = true`.
  swapInstruction: swapInstructionPayload, // The actual swap instruction.
  addressLookupTableAddresses, // The lookup table addresses that you can use if you are using versioned transaction.
} = instructions;

// A withdraw instruction that will increase the user input token account amount.
const withdrawInstruction = ...;

// Coupled with the tokenLedgerInstruction, the swap instruction will use the
// user increased amount of the input token account after the withdrawal as input amount.
const tokenLedgerInstruction = new TransactionInstruction({
  programId: new PublicKey(tokenLedgerPayload.programId),
  keys: tokenLedgerPayload.accounts.map((key) => ({
    pubkey: new PublicKey(key.pubkey),
      isSigner: key.isSigner,
      isWritable: key.isWritable,
    })),
  data: Buffer.from(tokenLedgerPayload.data, "base64"),
});

const swapInstruction = new TransactionInstruction({
  programId: new PublicKey(swapInstructionPayload.programId),
  keys: swapInstructionPayload.accounts.map((key) => ({
    pubkey: new PublicKey(key.pubkey),
      isSigner: key.isSigner,
      isWritable: key.isWritable,
    })),
  data: Buffer.from(swapInstructionPayload.data, "base64"),
});

const getAdressLookupTableAccounts = async (
  keys: string[]
): Promise<AddressLookupTableAccount[]> => {
  const addressLookupTableAccountInfos =
    await connection.getMultipleAccountsInfo(
      keys.map((key) => new PublicKey(key))
    );

  return addressLookupTableAccountInfos.reduce((acc, accountInfo, index) => {
    const addressLookupTableAddress = keys[index];
    if (accountInfo) {
      const addressLookupTableAccount = new AddressLookupTableAccount({
        key: new PublicKey(addressLookupTableAddress),
        state: AddressLookupTableAccount.deserialize(accountInfo.data),
      });
      acc.push(addressLookupTableAccount);
    }

    return acc;
  }, new Array<AddressLookupTableAccount>());
};

const addressLookupTableAccounts: AddressLookupTableAccount[] = [];

addressLookupTableAccounts.push(
  ...(await getAdressLookupTableAccounts(addressLookupTableAddresses))
);

const messageV0 = new TransactionMessage({
  payerKey: payerPublicKey,
  recentBlockhash: blockhash,
  instructions: [tokenLedgerInstruction, withdrawInstruction, swapInstruction],
}).compileToV0Message(addressLookupTableAccounts);
const transaction = new VersionedTransaction(messageV0);
```