@nekoproject/swap
Version:
Cross-chain Swap Token
134 lines (125 loc) • 4.15 kB
text/typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
import axios from 'axios';
import { ethers } from 'ethers';
import { Transaction } from '@solana/web3.js';
import { SPLWallet } from '@nekoproject/wallets';
import { SPLNetwork } from '@nekoproject/networks';
import { Swap } from '../Swap';
import { CreateOrder, SPLSwapOrderRequest, SetApiParams } from '../types';
export class SPLSwap extends Swap {
private _createOrderApi: string;
private _buildTransApi: string;
constructor(network: SPLNetwork, endpoint: string) {
let fmt_endpoint: string;
if (endpoint.endsWith('/')) {
fmt_endpoint = endpoint.slice(0, endpoint.length - 1);
} else {
fmt_endpoint = endpoint;
}
super(network, fmt_endpoint);
this._createOrderApi = this._endpoint + '/v2/swaps/create-order';
this._buildTransApi = this._endpoint + '/v2/swaps/build-transaction';
}
set endpoint(endpoint: string) {
this._endpoint = endpoint;
}
get endpoint() {
return this._endpoint;
}
set api(params: SetApiParams) {
this._createOrderApi = this._endpoint + params.createOrder;
this._buildTransApi = this._endpoint + params.buildTransaction;
}
/**
*
* @param swapRequest
* @returns
*/
async createSwapOrder(
swapRequest: CreateOrder
): Promise<SPLSwapOrderRequest> {
const destDecimals = swapRequest.destToken.tokenInfo.decimals
? swapRequest.destToken.tokenInfo.decimals
: (await swapRequest.destToken.getInfo()).decimals;
const srcDecimals = swapRequest.srcToken.tokenInfo.decimals
? swapRequest.srcToken.tokenInfo.decimals
: (await swapRequest.srcToken.getInfo()).decimals;
const unitAmount = ethers.utils.parseUnits(
swapRequest.srcAmount,
srcDecimals
);
const data = {
wallet_address: swapRequest.wallet_address,
slippage: swapRequest.slippage,
network: 'SOL',
destDecimals: destDecimals,
srcDecimals: srcDecimals,
srcAmount: unitAmount.toString(),
destToken: swapRequest.destToken.tokenInfo.mintAddress,
srcToken: swapRequest.srcToken.tokenInfo.mintAddress,
};
const orderResquest = await axios.post(this._createOrderApi, data);
if (orderResquest.data.swap_order) {
return orderResquest.data.swap_order;
} else {
throw new Error(
`Error create order: ${orderResquest.data?.error?.message}`
);
}
}
/**
*
* @param swapRequest
* @param wallet
* @returns
*/
async swapToken(
swapRequest: SPLSwapOrderRequest,
wallet: SPLWallet
): Promise<string> {
const buildTransactionOrder = {
slippage: swapRequest.slippage,
wallet_address: wallet.address,
network: 'SOL',
swap_order_id: swapRequest.id.toString(),
};
const buildResponse = await axios.post(
this._buildTransApi,
buildTransactionOrder
);
const transactions = buildResponse.data.transaction;
// setup transaction if must have
if (transactions.setupTransaction) {
const instructions = Transaction.from(
Buffer.from(transactions.setupTransaction, 'base64')
).instructions;
const txSetUp = new Transaction().add(...instructions);
await this.network.provider.sendTransaction(txSetUp, [wallet.signer], {
skipPreflight: false,
});
}
// execute swap
const swapInstructions = Transaction.from(
Buffer.from(transactions.swapTransaction, 'base64')
).instructions;
const transactionSwap = new Transaction().add(...swapInstructions);
const signature = await this.network.provider.sendTransaction(
transactionSwap,
[wallet.signer],
{
skipPreflight: false,
}
);
// clear cache if possible
if (transactions.cleanupTransaction) {
const cleanInstruction = Transaction.from(
Buffer.from(transactions.swapTransaction, 'base64')
).instructions;
const txClean = new Transaction().add(...cleanInstruction);
await this.network.provider.sendTransaction(txClean, [wallet.signer], {
skipPreflight: false,
});
}
return signature;
}
}