@robertprp/intents-sdk
Version:
Shogun Network Intent-based cross-chain swaps SDK
125 lines (103 loc) • 5.45 kB
text/typescript
import { AUCTIONEER_URL } from '../constants.js';
import { NetworkError } from '../errors/index.js';
import type { ApiResponse } from '../types/api.js';
import type {
CrossChainOrderPrepared,
CrossChainUserIntentRequest,
DcaSingleChainOrderPrepared,
DcaSingleChainUserIntentRequest,
SingleChainOrderPrepared,
SingleChainUserIntentRequest,
} from '../types/intent.js';
import { Parsers } from '../utils/parsers.js';
import { CrossChainOrder, type CreateCrossChainOrderParams } from './orders/cross-chain.js';
import { DcaSingleChainOrder, type CreateDcaSingleChainOrderParams } from './orders/dca-single-chain.js';
import { SingleChainOrder, type CreateSingleChainOrderParams } from './orders/single-chain.js';
/**
* Base SDK providing common functionality for all blockchain implementations
*/
export abstract class BaseSDK {
public abstract getUserAddress(): Promise<string>;
protected abstract prepareCrossChainOrder(order: CrossChainOrder): Promise<CrossChainOrderPrepared>;
protected prepareSingleChainOrder?(order: SingleChainOrder): Promise<SingleChainOrderPrepared>;
protected prepareDcaSingleChainOrder?(order: DcaSingleChainOrder): Promise<DcaSingleChainOrderPrepared>;
// Generic HTTP request handler
private static async makeRequest(url: string, body: string): Promise<ApiResponse> {
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body,
});
if (!response.ok) {
const errorJson: ApiResponse = await response.json();
const mainError = errorJson.error;
const extraErrorData = errorJson.extra_error_data;
const errorMessage = mainError
? `${mainError}. Extra error data: ${extraErrorData}`
: `Server error ${extraErrorData}`;
throw new NetworkError(errorMessage);
}
return response.json();
}
private static async validateOrder<T>(intentRequest: T, endpoint: string): Promise<void> {
const body = JSON.stringify(intentRequest, Parsers.bigIntReplacer);
const url = `${AUCTIONEER_URL}${endpoint}`;
await BaseSDK.makeRequest(url, body);
}
private static async sendOrder<T extends { toIntentRequest(preparedData: any): any }>(
preparedOrder: { order: T; preparedData: any },
endpoint: string,
): Promise<ApiResponse> {
const intentRequest = preparedOrder.order.toIntentRequest(preparedOrder.preparedData);
const body = JSON.stringify(intentRequest, Parsers.bigIntReplacer);
const url = `${AUCTIONEER_URL}${endpoint}`;
return BaseSDK.makeRequest(url, body);
}
public async createCrossChainOrder(params: CreateCrossChainOrderParams): Promise<CrossChainOrderPrepared> {
const userAddress = await this.getUserAddress();
const order = await CrossChainOrder.create({ ...params, user: userAddress });
return this.prepareCrossChainOrder!(order);
}
public async createAndSendCrossChainOrder(params: CreateCrossChainOrderParams): Promise<ApiResponse> {
const preparedOrder = await this.createCrossChainOrder(params);
return BaseSDK.sendCrossChainOrder(preparedOrder);
}
public static async sendCrossChainOrder(preparedOrder: CrossChainOrderPrepared): Promise<ApiResponse> {
return BaseSDK.sendOrder(preparedOrder, '/user_intent/cross_chain/limit_order');
}
public static async validateCrossChainOrder(intentRequest: CrossChainUserIntentRequest): Promise<void> {
return BaseSDK.validateOrder(intentRequest, '/validate_intent/cross_chain/limit_order');
}
public async createSingleChainOrder(params: CreateSingleChainOrderParams): Promise<SingleChainOrderPrepared> {
const userAddress = await this.getUserAddress();
const order = await SingleChainOrder.create({ ...params, user: userAddress });
return this.prepareSingleChainOrder!(order);
}
public async createAndSendSingleChainOrder(params: CreateSingleChainOrderParams): Promise<ApiResponse> {
const preparedOrder = await this.createSingleChainOrder(params);
return BaseSDK.sendSingleChainOrder(preparedOrder);
}
public static async sendSingleChainOrder(preparedOrder: SingleChainOrderPrepared): Promise<ApiResponse> {
return BaseSDK.sendOrder(preparedOrder, '/user_intent/single_chain/limit_order');
}
public static async validateSingleChainOrder(intentRequest: SingleChainUserIntentRequest): Promise<void> {
return BaseSDK.validateOrder(intentRequest, '/validate_intent/single_chain/limit_order');
}
public async createDcaSingleChainOrder(
params: CreateDcaSingleChainOrderParams,
): Promise<DcaSingleChainOrderPrepared> {
const userAddress = await this.getUserAddress();
const order = await DcaSingleChainOrder.create({ ...params, user: userAddress });
return this.prepareDcaSingleChainOrder!(order);
}
public async createAndSendDcaSingleChainOrder(params: CreateDcaSingleChainOrderParams): Promise<ApiResponse> {
const preparedOrder = await this.createDcaSingleChainOrder(params);
return BaseSDK.sendDcaSingleChainOrder(preparedOrder);
}
public static async sendDcaSingleChainOrder(preparedOrder: DcaSingleChainOrderPrepared): Promise<ApiResponse> {
return BaseSDK.sendOrder(preparedOrder, '/user_intent/single_chain/dca_order');
}
public static async validateDcaSingleChainOrder(intentRequest: DcaSingleChainUserIntentRequest): Promise<void> {
return BaseSDK.validateOrder(intentRequest, '/validate_intent/single_chain/dca_order');
}
}