Creating a SwapKit Plugin
Creating a Custom SwapKit Plugin
Section titled “Creating a Custom SwapKit Plugin”SwapKit plugins extend the functionality of the core library to support various DeFi protocols and services. This guide explains how to create a custom plugin for SwapKit.
Plugin Structure
Section titled “Plugin Structure”A SwapKit plugin consists of the following components:
- A plugin factory created with
createPlugin
- Plugin methods that interact with external services or smart contracts
- Integration with the SwapKit client
Basic Plugin Example
Section titled “Basic Plugin Example”Here’s a simple example of creating a plugin:
import {
class AssetValue
AssetValue,
enum Chain
Chain,
class SwapKitError
SwapKitError,
function createPlugin<const Name extends string, T extends (params: SwapKitPluginParams) => Record<string, unknown>, K extends {
supportedSwapkitProviders?: (ProviderName | string)[];
}>({ name, properties, methods }: {
name: Name;
properties?: K;
methods: T;
}): { [key in Name]: (pluginParams: SwapKitPluginParams) => K & ReturnType<T>; }
createPlugin,
type type EVMChain = Chain.Arbitrum | Chain.Avalanche | Chain.Base | Chain.BinanceSmartChain | Chain.Ethereum | Chain.Optimism | Chain.Polygon
EVMChain,
} from "@swapkit/helpers";
type type SwapParams = {
route: {
sellAsset: string;
buyAsset: string;
sellAmount: string;
};
}
SwapParams = {
route: {
sellAsset: string;
buyAsset: string;
sellAmount: string;
}
route: {
sellAsset: string
sellAsset: string;
buyAsset: string
buyAsset: string;
sellAmount: string
sellAmount: string;
};
};
type type QuoteParams = {
sellAsset: string;
buyAsset: string;
sellAmount: string;
}
QuoteParams = {
sellAsset: string
sellAsset: string;
buyAsset: string
buyAsset: string;
sellAmount: string
sellAmount: string;
};
// Create a simple example plugin
export const const ExamplePlugin: {
example: (pluginParams: SwapKitPluginParams) => {
supportedSwapkitProviders: string[];
} & {
swap: ({ route }: SwapParams) => Promise<string>;
getQuote: (params: QuoteParams) => Promise<...>;
};
}
ExamplePlugin = createPlugin<"example", ({ getWallet }: SwapKitPluginParams) => {
swap: ({ route }: SwapParams) => Promise<string>;
getQuote: (params: QuoteParams) => Promise<{
success: boolean;
data: {};
}>;
}, {
...;
}>({ name, properties, methods }: {
...;
}): {
...;
}
createPlugin({
name: "example"
name: "example",
properties?: {
supportedSwapkitProviders: string[];
} | undefined
properties: {
// Plugin properties/metadata
supportedSwapkitProviders: string[]
supportedSwapkitProviders: ["your-provider-name"],
},
methods: ({ getWallet }: SwapKitPluginParams) => {
swap: ({ route }: SwapParams) => Promise<string>;
getQuote: (params: QuoteParams) => Promise<{
success: boolean;
data: {};
}>;
}
methods: ({ getWallet: <T extends CryptoChain>(chain: T) => FullWallet[T]
getWallet }) => ({
// Define plugin methods here
swap: ({ route }: SwapParams) => Promise<string>
swap: async function function (local function) exampleSwap({ route }: SwapParams): Promise<string>
exampleSwap({ route: {
sellAsset: string;
buyAsset: string;
sellAmount: string;
}
route }: type SwapParams = {
route: {
sellAsset: string;
buyAsset: string;
sellAmount: string;
};
}
SwapParams) {
// Extract necessary data from the route
const { const sellAsset: string
sellAsset, const buyAsset: string
buyAsset, const sellAmount: string
sellAmount } = route: {
sellAsset: string;
buyAsset: string;
sellAmount: string;
}
route;
if (!(const sellAsset: string
sellAsset && const buyAsset: string
buyAsset)) {
throw new new SwapKitError(errorOrErrorKey: ErrorKeys | {
errorKey: ErrorKeys;
info?: Record<string, any>;
}, sourceErrorOrInfo?: any): SwapKitError
SwapKitError("core_swap_asset_not_recognized");
}
// Create an asset value from the sell asset
const const assetValue: AssetValue
assetValue = await class AssetValue
AssetValue.AssetValue.from<{
asyncTokenLookup: true;
asset: string;
value: string;
}>({ value, fromBaseDecimal, asyncTokenLookup, ...fromAssetOrChain }: {
asyncTokenLookup: true;
asset: string;
value: string;
} & AssetValueFromParams): Promise<AssetValue>
from({
asyncTokenLookup: true
asyncTokenLookup: true,
asset: string
asset: const sellAsset: string
sellAsset,
value: string
value: const sellAmount: string
sellAmount,
});
// Get the wallet for the source chain
const const wallet: (ChainWallet<Chain.Arbitrum> & {
estimateTransactionFee: ({ feeOption, chain, ...txObject }: EIP1559TxParams & {
feeOption: FeeOption;
chain: EVMChain;
}) => Promise<...>;
... 20 more ...;
validateAddress: (address: string) => boolean;
}) | ... 5 more ... | (ChainWallet<...> & {
...;
})
wallet = getWallet: <EVMChain>(chain: EVMChain) => (ChainWallet<Chain.Arbitrum> & {
estimateTransactionFee: ({ feeOption, chain, ...txObject }: EIP1559TxParams & {
feeOption: FeeOption;
chain: EVMChain;
}) => Promise<...>;
... 20 more ...;
validateAddress: (address: string) => boolean;
}) | ... 5 more ... | (ChainWallet<...> & {
...;
})
getWallet(const assetValue: AssetValue
assetValue.AssetValue.chain: Chain
chain as type EVMChain = Chain.Arbitrum | Chain.Avalanche | Chain.Base | Chain.BinanceSmartChain | Chain.Ethereum | Chain.Optimism | Chain.Polygon
EVMChain);
if (!const wallet: (ChainWallet<Chain.Arbitrum> & {
estimateTransactionFee: ({ feeOption, chain, ...txObject }: EIP1559TxParams & {
feeOption: FeeOption;
chain: EVMChain;
}) => Promise<...>;
... 20 more ...;
validateAddress: (address: string) => boolean;
}) | ... 5 more ... | (ChainWallet<...> & {
...;
})
wallet) {
throw new new SwapKitError(errorOrErrorKey: ErrorKeys | {
errorKey: ErrorKeys;
info?: Record<string, any>;
}, sourceErrorOrInfo?: any): SwapKitError
SwapKitError("core_wallet_connection_not_found");
}
// Custom swap logic goes here - this is where you would
// connect to your DeFi protocol or service
// For this example, we'll just transfer the funds to simulate a swap
if ('transfer' in const wallet: (ChainWallet<Chain.Arbitrum> & {
estimateTransactionFee: ({ feeOption, chain, ...txObject }: EIP1559TxParams & {
feeOption: FeeOption;
chain: EVMChain;
}) => Promise<...>;
... 20 more ...;
validateAddress: (address: string) => boolean;
}) | ... 5 more ... | (ChainWallet<...> & {
...;
})
wallet) {
const const txHash: string
txHash = await const wallet: (ChainWallet<Chain.Arbitrum> & {
estimateTransactionFee: ({ feeOption, chain, ...txObject }: EIP1559TxParams & {
feeOption: FeeOption;
chain: EVMChain;
}) => Promise<...>;
... 20 more ...;
validateAddress: (address: string) => boolean;
}) | ... 5 more ... | (ChainWallet<...> & {
...;
})
wallet.transfer: ({ assetValue, memo, recipient, feeOptionKey, sender, ...tx }: EVMTransferParams) => Promise<string>
transfer({
assetValue: AssetValue
assetValue,
from: const wallet: (ChainWallet<Chain.Arbitrum> & {
estimateTransactionFee: ({ feeOption, chain, ...txObject }: EIP1559TxParams & {
feeOption: FeeOption;
chain: EVMChain;
}) => Promise<...>;
... 20 more ...;
validateAddress: (address: string) => boolean;
}) | ... 5 more ... | (ChainWallet<...> & {
...;
})
wallet.address: string
address, recipient: string
recipient: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", // Example recipient
});
return const txHash: string
txHash;
}
throw new var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+2 overloads)
Error("Wallet does not support transfer");
},
// Add additional methods as needed
getQuote: (params: QuoteParams) => Promise<{
success: boolean;
data: {};
}>
getQuote: async function function (local function) getExampleQuote(params: QuoteParams): Promise<{
success: boolean;
data: {};
}>
getExampleQuote(params: QuoteParams
params: type QuoteParams = {
sellAsset: string;
buyAsset: string;
sellAmount: string;
}
QuoteParams) {
// Custom quote logic here
return {
// Return quote data
success: boolean
success: true,
data: {}
data: {
// Quote details
}
};
},
}),
});
Creating an EVM-based Swap Plugin
Section titled “Creating an EVM-based Swap Plugin”Here’s a more realistic example of an EVM-based plugin that integrates with an exchange:
import {
enum ApproveMode
ApproveMode,
class AssetValue
AssetValue,
enum Chain
Chain,
type EVMChain = Chain.Arbitrum | Chain.Avalanche | Chain.Base | Chain.BinanceSmartChain | Chain.Ethereum | Chain.Optimism | Chain.Polygon
EVMChain,
enum ProviderName
ProviderName,
class SwapKitError
SwapKitError,
function createPlugin<const Name extends string, T extends (params: SwapKitPluginParams) => Record<string, unknown>, K extends {
supportedSwapkitProviders?: (ProviderName | string)[];
}>({ name, properties, methods }: {
name: Name;
properties?: K;
methods: T;
}): { [key in Name]: (pluginParams: SwapKitPluginParams) => K & ReturnType<T>; }
createPlugin
} from "@swapkit/helpers";
import { const SwapKitApi: {
mayachainMidgard: {
getLiquidityPositionRaw: (address: string) => Promise<MemberDetailsMayachain>;
getBorrowerDetailRaw: (address: string) => Promise<...>;
... 6 more ...;
getLiquidityPosition: (address: string) => Promise<...>;
};
... 14 more ...;
getChainflipDepositChannel(body: BrokerDepositChannelParams): Promise<...>;
}
SwapKitApi, type type QuoteResponseRoute = {
sellAsset: string;
buyAsset: string;
destinationAddress: string;
providers: ProviderName[];
sellAmount: string;
expectedBuyAmount: string;
expectedBuyAmountMaxSlippage: string;
... 12 more ...;
estimatedTime?: {
...;
} | undefined;
}
QuoteResponseRoute } from "@swapkit/helpers/api";
// Helper function for approval handling
const const approve: ({ approveMode, getWallet }: {
approveMode: any;
getWallet: any;
}) => ({ assetValue }: {
assetValue: any;
}) => Promise<any>
approve = ({ approveMode: any
approveMode, getWallet: any
getWallet }) =>
async function({ assetValue: any
assetValue }) {
const const evmChain: EVMChain
evmChain = assetValue: any
assetValue.chain as type EVMChain = Chain.Arbitrum | Chain.Avalanche | Chain.Base | Chain.BinanceSmartChain | Chain.Ethereum | Chain.Optimism | Chain.Polygon
EVMChain;
const const wallet: any
wallet = getWallet: any
getWallet(const evmChain: EVMChain
evmChain);
if (!const wallet: any
wallet) {
throw new new SwapKitError(errorOrErrorKey: ErrorKeys | {
errorKey: ErrorKeys;
info?: Record<string, any>;
}, sourceErrorOrInfo?: any): SwapKitError
SwapKitError("core_wallet_connection_not_found");
}
// Get the router contract address from your protocol
const const routerAddress: "0x1234567890123456789012345678901234567890"
routerAddress = "0x1234567890123456789012345678901234567890";
// Handle the approval based on the mode
if (approveMode: any
approveMode === enum ApproveMode
ApproveMode.function (enum member) ApproveMode.CheckOnly = "checkOnly"
CheckOnly) {
return const wallet: any
wallet.isApproved({
amount: any
amount: assetValue: any
assetValue.getBaseValue("bigint"),
assetAddress: any
assetAddress: assetValue: any
assetValue.address,
from: any
from: const wallet: any
wallet.address,
spenderAddress: string
spenderAddress: const routerAddress: "0x1234567890123456789012345678901234567890"
routerAddress,
});
}
return const wallet: any
wallet.approve({
amount: any
amount: assetValue: any
assetValue.getBaseValue("bigint"),
assetAddress: any
assetAddress: assetValue: any
assetValue.address,
from: any
from: const wallet: any
wallet.address,
spenderAddress: string
spenderAddress: const routerAddress: "0x1234567890123456789012345678901234567890"
routerAddress,
});
};
// Create the exchange plugin
export const const ExchangePlugin: {
exchange: (pluginParams: SwapKitPluginParams) => {
supportedSwapkitProviders: any[];
} & {
approveAssetValue: ({ assetValue }: {
assetValue: any;
}) => Promise<...>;
isAssetValueApproved: ({ assetValue }: {
assetValue: any;
}) => Promise<...>;
swap: ({ route }: {
...;
}) => Promise<...>;
getQuote: ({ sellAsset, buyAsset, sellAmount, slippage, }: {
...;
}) => Promise<...>;
};
}
ExchangePlugin = createPlugin<"exchange", ({ getWallet }: SwapKitPluginParams) => {
approveAssetValue: ({ assetValue }: {
assetValue: any;
}) => Promise<any>;
isAssetValueApproved: ({ assetValue }: {
assetValue: any;
}) => Promise<any>;
swap: ({ route }: {
...;
}) => Promise<...>;
getQuote: ({ sellAsset, buyAsset, sellAmount, slippage, }: {
...;
}) => Promise<...>;
}, {
...;
}>({ name, properties, methods }: {
...;
}): {
...;
}
createPlugin({
name: "exchange"
name: "exchange",
properties?: {
supportedSwapkitProviders: any[];
} | undefined
properties: {
supportedSwapkitProviders: any[]
supportedSwapkitProviders: [enum ProviderName
ProviderName.CUSTOM_EXCHANGE],
},
methods: ({ getWallet }: SwapKitPluginParams) => {
approveAssetValue: ({ assetValue }: {
assetValue: any;
}) => Promise<any>;
isAssetValueApproved: ({ assetValue }: {
assetValue: any;
}) => Promise<any>;
swap: ({ route }: {
...;
}) => Promise<...>;
getQuote: ({ sellAsset, buyAsset, sellAmount, slippage, }: {
...;
}) => Promise<...>;
}
methods: ({ getWallet: <T extends CryptoChain>(chain: T) => FullWallet[T]
getWallet }) => ({
// Approval methods
approveAssetValue: ({ assetValue }: {
assetValue: any;
}) => Promise<any>
approveAssetValue: const approve: ({ approveMode, getWallet }: {
approveMode: any;
getWallet: any;
}) => ({ assetValue }: {
assetValue: any;
}) => Promise<any>
approve({ approveMode: any
approveMode: enum ApproveMode
ApproveMode.function (enum member) ApproveMode.Approve = "approve"
Approve, getWallet: any
getWallet }),
isAssetValueApproved: ({ assetValue }: {
assetValue: any;
}) => Promise<any>
isAssetValueApproved: const approve: ({ approveMode, getWallet }: {
approveMode: any;
getWallet: any;
}) => ({ assetValue }: {
assetValue: any;
}) => Promise<any>
approve({ approveMode: any
approveMode: enum ApproveMode
ApproveMode.function (enum member) ApproveMode.CheckOnly = "checkOnly"
CheckOnly, getWallet: any
getWallet }),
// Swap method
swap: ({ route }: {
route: any;
}) => Promise<string>
swap: async function function (local function) exchangeSwap({ route }: {
route: any;
}): Promise<string>
exchangeSwap({ route: any
route }) {
const { const tx: any
tx, const sellAsset: any
sellAsset } = route: any
route;
if (!const tx: any
tx) {
throw new new SwapKitError(errorOrErrorKey: ErrorKeys | {
errorKey: ErrorKeys;
info?: Record<string, any>;
}, sourceErrorOrInfo?: any): SwapKitError
SwapKitError("core_swap_invalid_params");
}
const const assetValue: AssetValue
assetValue = await class AssetValue
AssetValue.AssetValue.from<{
asset: any;
asyncTokenLookup: true;
}>({ value, fromBaseDecimal, asyncTokenLookup, ...fromAssetOrChain }: {
asset: any;
asyncTokenLookup: true;
} & AssetValueFromParams): Promise<AssetValue>
from({
asset: any
asset: const sellAsset: any
sellAsset,
asyncTokenLookup: true
asyncTokenLookup: true
});
const const evmChain: EVMChain
evmChain = const assetValue: AssetValue
assetValue.AssetValue.chain: Chain
chain as type EVMChain = Chain.Arbitrum | Chain.Avalanche | Chain.Base | Chain.BinanceSmartChain | Chain.Ethereum | Chain.Optimism | Chain.Polygon
EVMChain;
const const wallet: (ChainWallet<Chain.Arbitrum> & {
estimateTransactionFee: ({ feeOption, chain, ...txObject }: EIP1559TxParams & {
feeOption: FeeOption;
chain: EVMChain;
}) => Promise<...>;
... 20 more ...;
validateAddress: (address: string) => boolean;
}) | ... 5 more ... | (ChainWallet<...> & {
...;
})
wallet = getWallet: <EVMChain>(chain: EVMChain) => (ChainWallet<Chain.Arbitrum> & {
estimateTransactionFee: ({ feeOption, chain, ...txObject }: EIP1559TxParams & {
feeOption: FeeOption;
chain: EVMChain;
}) => Promise<...>;
... 20 more ...;
validateAddress: (address: string) => boolean;
}) | ... 5 more ... | (ChainWallet<...> & {
...;
})
getWallet(const evmChain: EVMChain
evmChain);
if (!const wallet: (ChainWallet<Chain.Arbitrum> & {
estimateTransactionFee: ({ feeOption, chain, ...txObject }: EIP1559TxParams & {
feeOption: FeeOption;
chain: EVMChain;
}) => Promise<...>;
... 20 more ...;
validateAddress: (address: string) => boolean;
}) | ... 5 more ... | (ChainWallet<...> & {
...;
})
wallet) {
throw new new SwapKitError(errorOrErrorKey: ErrorKeys | {
errorKey: ErrorKeys;
info?: Record<string, any>;
}, sourceErrorOrInfo?: any): SwapKitError
SwapKitError("core_wallet_connection_not_found");
}
// Send the transaction
const { const from: any
from, const to: any
to, const data: any
data, const value: any
value } = const tx: any
tx;
return const wallet: (ChainWallet<Chain.Arbitrum> & {
estimateTransactionFee: ({ feeOption, chain, ...txObject }: EIP1559TxParams & {
feeOption: FeeOption;
chain: EVMChain;
}) => Promise<...>;
... 20 more ...;
validateAddress: (address: string) => boolean;
}) | ... 5 more ... | (ChainWallet<...> & {
...;
})
wallet.sendTransaction: ({ feeOptionKey, ...tx }: EVMTxParams & {
feeOptionKey?: FeeOption;
}) => Promise<string>
sendTransaction({
from?: string | undefined
from,
to?: string | undefined
to,
data?: string | undefined
data,
value?: bigint | undefined
value: var BigInt: BigIntConstructor
(value: bigint | boolean | number | string) => bigint
BigInt(const value: any
value || 0)
});
},
// Get a quote from the exchange
getQuote: ({ sellAsset, buyAsset, sellAmount, slippage, }: {
sellAsset: any;
buyAsset: any;
sellAmount: any;
slippage?: number | undefined;
}) => Promise<{
success: boolean;
data: {
routes: {
sellAsset: string;
buyAsset: string;
destinationAddress: string;
... 16 more ...;
estimatedTime?: {
...;
} | undefined;
}[];
};
error?: undefined;
} | {
...;
}>
getQuote: async function function (local function) getExchangeQuote({ sellAsset, buyAsset, sellAmount, slippage, }: {
sellAsset: any;
buyAsset: any;
sellAmount: any;
slippage?: number | undefined;
}): Promise<{
success: boolean;
data: {
routes: {
sellAsset: string;
buyAsset: string;
destinationAddress: string;
... 16 more ...;
estimatedTime?: {
...;
} | undefined;
}[];
};
error?: undefined;
} | {
...;
}>
getExchangeQuote({
sellAsset: any
sellAsset,
buyAsset: any
buyAsset,
sellAmount: any
sellAmount,
slippage: number
slippage = 1, // 1% default slippage
}) {
try {
// Call your exchange API to get a quote
const const response: Response
response = await function fetch(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response> (+3 overloads)
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/fetch)fetch("https://api.your-exchange.com/quote", {
RequestInit.method?: string | undefined
A string to set request's method.method: "POST",
RequestInit.headers?: HeadersInit | undefined
A Headers object, an object literal, or an array of two-item arrays to set request's headers.headers: { "Content-Type": "application/json" },
RequestInit.body?: BodyInit | null | undefined
A BodyInit object or null to set request's body.body: var JSON: JSON
An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.JSON.JSON.stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string (+1 overload)
Converts a JavaScript value to a JavaScript Object Notation (JSON) string.stringify({
sellAsset: any
sellAsset,
buyAsset: any
buyAsset,
sellAmount: any
sellAmount,
slippage: number
slippage,
}),
});
if (!const response: Response
response.Response.ok: boolean
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Response/ok)ok) {
throw new var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+2 overloads)
Error(`API error: ${const response: Response
response.Response.status: number
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Response/status)status}`);
}
const const quoteData: any
quoteData = await const response: Response
response.Body.json(): Promise<any> (+1 overload)
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/json)json();
// Format the response to match SwapKit's expected format
return {
success: boolean
success: true,
data: {
routes: {
sellAsset: string;
buyAsset: string;
destinationAddress: string;
providers: ProviderName[];
sellAmount: string;
expectedBuyAmount: string;
expectedBuyAmountMaxSlippage: string;
... 12 more ...;
estimatedTime?: {
...;
} | undefined;
}[];
}
data: {
routes: {
sellAsset: string;
buyAsset: string;
destinationAddress: string;
providers: ProviderName[];
sellAmount: string;
expectedBuyAmount: string;
expectedBuyAmountMaxSlippage: string;
... 12 more ...;
estimatedTime?: {
...;
} | undefined;
}[]
routes: [
{
sellAsset: string
sellAsset,
buyAsset: string
buyAsset,
sellAmount: string
sellAmount,
buyAmount: any
buyAmount: const quoteData: any
quoteData.buyAmount,
// Include the transaction data needed for the swap
tx?: string | {
value: string;
to: string;
from: string;
data: string;
} | {
memo: string;
accountNumber: number;
sequence: number;
chainId: ChainId;
msgs: {
typeUrl: string;
value?: unknown;
}[];
fee: {
amount: {
...;
}[];
gas: string;
};
} | undefined
tx: {
from: string
from: const quoteData: any
quoteData.from,
to: string
to: const quoteData: any
quoteData.to,
data: string
data: const quoteData: any
quoteData.data,
value: string
value: const quoteData: any
quoteData.value,
},
providers: ProviderName[]
providers: [enum ProviderName
ProviderName.CUSTOM_EXCHANGE],
} as type QuoteResponseRoute = {
sellAsset: string;
buyAsset: string;
destinationAddress: string;
providers: ProviderName[];
sellAmount: string;
expectedBuyAmount: string;
expectedBuyAmountMaxSlippage: string;
... 12 more ...;
estimatedTime?: {
...;
} | undefined;
}
QuoteResponseRoute,
],
},
};
} catch (function (local var) error: unknown
error) {
return {
success: boolean
success: false,
error: string
error: var String: StringConstructor
(value?: any) => string
Allows manipulation and formatting of text strings and determination and location of substrings within strings.String(function (local var) error: unknown
error),
};
}
},
}),
});
Using Your Plugin with SwapKit
Section titled “Using Your Plugin with SwapKit”Once you’ve created your plugin, you can use it with the SwapKit client:
import { function SwapKit<Plugins extends ReturnType<typeof createPlugin>, Wallets extends ReturnType<typeof createWallet>>({ config, plugins, wallets, }?: {
config?: SKConfigState;
plugins?: Plugins;
wallets?: Wallets;
}): { [key in keyof Plugins]: ReturnType<...>; } & ... 1 more ... & {
...;
}
SwapKit, enum Chain
Chain } from "@swapkit/core";
import { const keystoreWallet: {
connectKeystore: {
connectWallet: (connectParams: {
addChain: AddChainType;
}) => (chains: Chain[], phrase: string, derivationPathMapOrIndex?: number | {
ARB?: DerivationPathArray | undefined;
... 21 more ...;
SOL?: DerivationPathArray | undefined;
} | undefined) => Promise<boolean>;
supportedChains: (Chain.Arbitrum | ... 18 more ... | Chain.Solana)[];
};
}
keystoreWallet } from "@swapkit/wallets/keystore";
// @ts-ignore
import { import ExamplePlugin
ExamplePlugin } from "./example-plugin";
// Initialize SwapKit with your plugin
const const swapKit: {
examplePlugin: any;
} & {
connectKeystore: (chains: Chain[], phrase: string, derivationPathMapOrIndex?: number | {
ARB?: DerivationPathArray | undefined;
AVAX?: DerivationPathArray | undefined;
... 20 more ...;
SOL?: DerivationPathArray | undefined;
} | undefined) => Promise<boolean>;
} & {
...;
}
swapKit = SwapKit<{
examplePlugin: any;
}, {
connectKeystore: {
connectWallet: (connectParams: {
addChain: AddChainType;
}) => (chains: Chain[], phrase: string, derivationPathMapOrIndex?: number | {
...;
} | undefined) => Promise<boolean>;
supportedChains: (Chain.Arbitrum | ... 18 more ... | Chain.Solana)[];
};
}>({ config, plugins, wallets, }?: {
...;
}): {
...;
} & ... 1 more ... & {
...;
}
SwapKit({
plugins?: {
examplePlugin: any;
} | undefined
plugins: { examplePlugin: any
examplePlugin: import ExamplePlugin
ExamplePlugin },
wallets?: {
connectKeystore: {
connectWallet: (connectParams: {
addChain: AddChainType;
}) => (chains: Chain[], phrase: string, derivationPathMapOrIndex?: number | {
ARB?: DerivationPathArray | undefined;
... 21 more ...;
SOL?: DerivationPathArray | undefined;
} | undefined) => Promise<boolean>;
supportedChains: (Chain.Arbitrum | ... 18 more ... | Chain.Solana)[];
};
} | undefined
wallets: { ...const keystoreWallet: {
connectKeystore: {
connectWallet: (connectParams: {
addChain: AddChainType;
}) => (chains: Chain[], phrase: string, derivationPathMapOrIndex?: number | {
ARB?: DerivationPathArray | undefined;
... 21 more ...;
SOL?: DerivationPathArray | undefined;
} | undefined) => Promise<boolean>;
supportedChains: (Chain.Arbitrum | ... 18 more ... | Chain.Solana)[];
};
}
keystoreWallet },
});
// Connect a wallet
async function function connectAndUsePlugin(): Promise<void>
connectAndUsePlugin() {
// Connect a wallet first
await const swapKit: {
examplePlugin: any;
} & {
connectKeystore: (chains: Chain[], phrase: string, derivationPathMapOrIndex?: number | {
ARB?: DerivationPathArray | undefined;
AVAX?: DerivationPathArray | undefined;
... 20 more ...;
SOL?: DerivationPathArray | undefined;
} | undefined) => Promise<boolean>;
} & {
...;
}
swapKit.connectKeystore: (chains: Chain[], phrase: string, derivationPathMapOrIndex?: number | {
ARB?: DerivationPathArray | undefined;
AVAX?: DerivationPathArray | undefined;
... 20 more ...;
SOL?: DerivationPathArray | undefined;
} | undefined) => Promise<boolean>
connectKeystore(
[enum Chain
Chain.function (enum member) Chain.Bitcoin = "BTC"
Bitcoin, enum Chain
Chain.function (enum member) Chain.Ethereum = "ETH"
Ethereum], // Chains to connect
"your secret phrase here"
);
// Get a quote from your plugin
const const quoteResponse: any
quoteResponse = await const swapKit: {
examplePlugin: any;
} & {
connectKeystore: (chains: Chain[], phrase: string, derivationPathMapOrIndex?: number | {
ARB?: DerivationPathArray | undefined;
AVAX?: DerivationPathArray | undefined;
... 20 more ...;
SOL?: DerivationPathArray | undefined;
} | undefined) => Promise<boolean>;
} & {
...;
}
swapKit.examplePlugin: any
examplePlugin.getQuote({
sellAsset: string
sellAsset: "ETH.ETH",
buyAsset: string
buyAsset: "ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
sellAmount: string
sellAmount: "0.1",
});
if (const quoteResponse: any
quoteResponse.success) {
// Execute the swap using the first route from the quote
const const txHash: any
txHash = await const swapKit: {
examplePlugin: any;
} & {
connectKeystore: (chains: Chain[], phrase: string, derivationPathMapOrIndex?: number | {
ARB?: DerivationPathArray | undefined;
AVAX?: DerivationPathArray | undefined;
... 20 more ...;
SOL?: DerivationPathArray | undefined;
} | undefined) => Promise<boolean>;
} & {
...;
}
swapKit.swap: <"examplePlugin">({ route, pluginName, ...rest }: SwapParams<"examplePlugin", {
providers: ProviderName[];
sellAsset: string;
sellAmount: string;
buyAsset: string;
expectedBuyAmount: string;
expectedBuyAmountMaxSlippage: string;
... 13 more ...;
estimatedTime?: {
...;
} | undefined;
}>) => any
swap({ route: {
providers: ProviderName[];
sellAsset: string;
sellAmount: string;
buyAsset: string;
expectedBuyAmount: string;
expectedBuyAmountMaxSlippage: string;
sourceAddress: string;
... 12 more ...;
estimatedTime?: {
...;
} | undefined;
}
route: const quoteResponse: any
quoteResponse.data.routes[0] });
}
}
Best Practices
Section titled “Best Practices”When creating a SwapKit plugin, follow these best practices:
- Error Handling: Use SwapKitError for consistent error reporting
- Type Safety: Leverage TypeScript to provide proper type definitions
- Documentation: Document your plugin methods and parameters
- Testing: Create comprehensive tests for all functionality
- Validation: Validate inputs to prevent runtime errors
- Security: Be careful with sensitive data and external API calls
By following this guide, you should be able to create, test, and integrate custom plugins with SwapKit.