Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c822a5a
chore: keystore transaction signing
towanTG Oct 10, 2025
caaa9c2
chore: correct quoteresponserouteitem
towanTG Oct 10, 2025
ac9823f
chore: clean up
towanTG Oct 10, 2025
831a14e
Merge branch 'develop' into chore/keystore-signing-api-provided-tx
towanTG Oct 16, 2025
8ba9336
Merge branch 'develop' into chore/keystore-signing-api-provided-tx
towanTG Oct 21, 2025
767cc24
Merge branch 'develop' into chore/keystore-signing-api-provided-tx
towanTG Oct 21, 2025
f32cf05
chore: move nightly changes into branch
towanTG Oct 21, 2025
1f1e59e
chore: uses approve endpoint for plugins
towanTG Oct 22, 2025
62923a7
Merge branch 'develop' into chore/keystore-signing-api-provided-tx
towanTG Nov 21, 2025
9cdee0b
Merge branch 'develop' into chore/keystore-signing-api-provided-tx
towanTG Nov 21, 2025
8d30bfd
chore: fix branch
towanTG Nov 21, 2025
e702fb6
Merge branch 'develop' into chore/keystore-signing-api-provided-tx
towanTG Nov 24, 2025
d232666
Merge branch 'develop' into chore/keystore-signing-api-provided-tx
towanTG Nov 25, 2025
b7689ed
fix: approval endpoint changes
towanTG Nov 25, 2025
3cefbb4
chore: cleans up ts errors
towanTG Nov 25, 2025
777dd5b
chore: update signing decision logic + adds btc to phantom
towanTG Nov 26, 2025
1de8bb3
Merge branch 'develop' into chore/keystore-signing-api-provided-tx
towanTG Nov 26, 2025
f783b25
Merge branch 'develop' into chore/keystore-signing-api-provided-tx
towanTG Nov 30, 2025
fc155f9
chore: adds sui sign and broadcast and support in trading plugin
towanTG Dec 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ jobs:
- run: bun lint
- run: bun type-check:ci

- name: Test
if: github.ref_name == 'nightly'
run: bun test:ci

publish:
needs: [build-lint-test]
runs-on: ubuntu-latest
Expand Down
12 changes: 9 additions & 3 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,11 @@
"@swapkit/plugins": "workspace:*",
"@swapkit/toolboxes": "workspace:*",
"@swapkit/wallets": "workspace:*",
"cosmjs-types": "0.10.1",
"ts-pattern": "^5.9.0",
},
"devDependencies": {
"cosmjs-types": "0.10.1",
"ts-pattern": "5.9.0",
},
},
Expand Down Expand Up @@ -105,6 +107,8 @@
"name": "@swapkit/plugins",
"version": "4.2.9",
"dependencies": {
"@mysten/sui": "1.44.0",
"@near-js/transactions": "2.5.0",
"@near-js/utils": "~2.5.0",
"@polkadot/keyring": "~13.5.7",
"@polkadot/util": "~13.5.7",
Expand All @@ -131,6 +135,7 @@
"@swapkit/server": "workspace:*",
"@swapkit/toolboxes": "workspace:*",
"@swapkit/wallets": "workspace:*",
"cosmjs-types": "0.10.1",
},
},
"packages/server": {
Expand Down Expand Up @@ -293,6 +298,7 @@
"@swapkit/wallets": "workspace:*",
"class-variance-authority": "0.7.1",
"clsx": "2.1.1",
"cosmjs-types": "0.10.1",
"lucide-react": "0.552.0",
"react": "19.1.1",
"react-hook-form": "7.65.0",
Expand Down Expand Up @@ -324,6 +330,7 @@
"@swapkit/helpers": "workspace:*",
"@swapkit/toolboxes": "workspace:*",
"@swapkit/wallet-core": "workspace:*",
"cosmjs-types": "0.10.1",
"ethers": "^6.14.0",
"sats-connect": "~1.0.0",
"ts-pattern": "~5.9.0",
Expand All @@ -334,6 +341,7 @@
"@near-js/crypto": "2.5.0",
"@near-js/transactions": "2.5.0",
"@solana/web3.js": "1.98.4",
"cosmjs-types": "0.10.1",
"ethers": "6.15.0",
"sats-connect": "1.0.0",
"ts-pattern": "5.9.0",
Expand Down Expand Up @@ -3741,7 +3749,7 @@

"oniguruma-parser": ["[email protected]", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="],

"oniguruma-to-es": ["[email protected].3", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg=="],
"oniguruma-to-es": ["[email protected].4", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA=="],

"open": ["[email protected]", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="],

Expand Down Expand Up @@ -5337,8 +5345,6 @@

"abi-wan-kanabi/fs-extra": ["[email protected]", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="],

"ajv-formats/ajv": ["[email protected]", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg=="],

"anymatch/picomatch": ["[email protected]", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],

"aria-hidden/tslib": ["[email protected]", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"xrpl": "4.4.2"
},
"name": "swapkit-monorepo",
"packageManager": "bun@^1.3.1",
"packageManager": "bun@^1.3.2",
"private": true,
"scripts": {
"bootstrap": "bun clean --force; bun build:ci",
Expand Down
3 changes: 2 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
"@swapkit/plugins": "workspace:*",
"@swapkit/toolboxes": "workspace:*",
"@swapkit/wallets": "workspace:*",
"cosmjs-types": "0.10.1",
"ts-pattern": "^5.9.0"
},
"description": "SwapKit - Core",
"devDependencies": { "ts-pattern": "5.9.0" },
"devDependencies": { "cosmjs-types": "0.10.1", "ts-pattern": "5.9.0" },
"exports": {
".": {
"bun": "./src/index.ts",
Expand Down
19 changes: 19 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import {
type SKConfigState,
SwapKitError,
type SwapParams,
supportsV3SwapFlow,
UTXOChains,
type WalletOption,
} from "@swapkit/helpers";
import type { EVMTransaction, QuoteResponseRoute } from "@swapkit/helpers/api";
import type { createPlugin } from "@swapkit/plugins";
Expand Down Expand Up @@ -202,6 +204,23 @@ export function SwapKit<
}

function swap<T extends PluginName>({ route, pluginName, ...rest }: SwapParams<T, QuoteResponseRoute>) {
const fromChain = AssetValue.from({ asset: route.sellAsset }).chain;
const wallet = getWallet(fromChain);

if (!wallet) {
throw new SwapKitError("core_wallet_connection_not_found");
}

const useV3Flow = supportsV3SwapFlow(wallet.walletType as WalletOption, fromChain) && route.tx;

if (useV3Flow) {
const plugin = getSwapKitPlugin("trading");
if ("swap" in plugin) {
// @ts-expect-error TODO: fix this
return plugin.swap({ ...rest, route });
}
}

const plugin = getSwapKitPlugin(pluginName || route.providers[0]);

if ("swap" in plugin) {
Expand Down
22 changes: 22 additions & 0 deletions packages/helpers/src/api/swapkitApi/endpoints.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AssetValue,
type Chain,
type EVMChain,
EVMChains,
Expand All @@ -10,6 +11,7 @@ import {
} from "@swapkit/helpers";
import { match, P } from "ts-pattern";
import {
type ApproveResponse,
type BalanceResponse,
type BrokerDepositChannelParams,
type DepositChannelResponse,
Expand Down Expand Up @@ -122,6 +124,26 @@ export async function getChainBalance<T extends Chain>({
return scamFilter ? filterAssets(balances) : balances;
}

export function getTokenApproval(
params: { spender: string; userWallet: string; assetValue: AssetValue } | { routeId: string; spender: string },
) {
return match(params)
.with({ routeId: P.string, spender: P.string }, ({ routeId, spender }) => {
const url = getApiUrl(`/approve?routeId=${routeId}&sourceAddress=${spender}`);
return SKRequestClient.get<ApproveResponse>(url);
})
.with(
{ assetValue: P.instanceOf(AssetValue), spender: P.string, userWallet: P.string },
({ spender, userWallet, assetValue }) => {
const url = getApiUrl(
`/approve?tokenIdentifier=${assetValue.toString()}&userWalletAddress=${userWallet}&spender=${spender}&amount=${assetValue.getValue("string")}`,
);
return SKRequestClient.get<ApproveResponse>(url);
},
)
.exhaustive();
}

export function getTokenListProviders() {
const url = getApiUrl("/providers");
return SKRequestClient.get<TokenListProvidersResponse>(url);
Expand Down
79 changes: 77 additions & 2 deletions packages/helpers/src/api/swapkitApi/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,21 @@ export const EVMTransactionSchema = object({

export type EVMTransaction = z.infer<typeof EVMTransactionSchema>;

export const TronTransactionSchema = z.object({
raw_data: z.object({
contract: z.any(),
expiration: z.number(),
ref_block_bytes: z.string(),
ref_block_hash: z.string(),
timestamp: z.number(),
}),
raw_data_hex: z.string(),
txID: z.string(),
visible: z.boolean(),
});

export type TronTransaction = z.infer<typeof TronTransactionSchema>;

export const EVMTransactionDetailsParamsSchema = array(
union([
string(),
Expand All @@ -468,7 +483,36 @@ export const EVMTransactionDetailsSchema = object({

export type EVMTransactionDetails = z.infer<typeof EVMTransactionDetailsSchema>;

const EncodeObjectSchema = object({ typeUrl: string(), value: unknown() });
const ThorchainDepositMsgSchema = object({
typeUrl: string("/types.MsgDeposit"),
value: object({
coins: array(
object({
amount: string(),
asset: object({ chain: string(), symbol: string(), synth: boolean(), ticker: string() }),
}),
),
memo: string(),
signer: string(),
}),
});

export type ThorchainDepositMsg = z.infer<typeof ThorchainDepositMsgSchema>;

const CosmosSendMsgSchema = object({
typeUrl: string("/types.MsgSend"),
value: object({
amount: array(object({ amount: string(), denom: string() })),
fromAddress: string(),
toAddress: string(),
}),
});

export type CosmosSendMsg = z.infer<typeof CosmosSendMsgSchema>;

const EncodeObjectSchema = object({ typeUrl: string(), value: CosmosSendMsgSchema.or(ThorchainDepositMsgSchema) });

export type APICosmosEncodedObject = z.infer<typeof EncodeObjectSchema>;

const FeeSchema = object({ amount: array(object({ amount: string(), denom: string() })), gas: string() });

Expand Down Expand Up @@ -572,7 +616,7 @@ export const QuoteResponseRouteItem = object({
sourceAddress: string().describe("Source address"),
targetAddress: optional(string().describe("Target address")),
totalSlippageBps: number().describe("Total slippage in bps"),
tx: optional(union([EVMTransactionSchema, CosmosTransactionSchema, string()])),
tx: optional(union([EVMTransactionSchema, CosmosTransactionSchema, TronTransactionSchema, string()])),
txType: optional(z.enum(RouteQuoteTxType)),
warnings: RouteQuoteWarningSchema,
});
Expand Down Expand Up @@ -622,3 +666,34 @@ const BalanceResponseSchema = array(
);

export type BalanceResponse = z.infer<typeof BalanceResponseSchema>;

export const ApproveRequestParams = z.union([
z.object({ amount: z.string(), spender: z.string(), tokenIdentifier: z.string(), userWalletAddress: z.string() }),
z.object({
amount: z.string(),
chainId: z.enum(ChainId),
spender: z.string(),
tokenContractAddress: z.string(),
userWalletAddress: z.string(),
}),
z.object({ routeId: z.string() }),
]);

export type ApproveRequest = z.infer<typeof ApproveRequestParams>;

export const ApproveResponseSchema = z.object({
approvalTransaction: z.optional(
z.object({
data: z.string(),
from: z.string(),
gasLimit: z.optional(z.string()),
gasPrice: z.optional(z.string()),
to: z.string(),
value: z.string(),
}),
),
approvedAmount: z.string(),
isApproved: z.boolean(),
});

export type ApproveResponse = z.infer<typeof ApproveResponseSchema>;
15 changes: 14 additions & 1 deletion packages/helpers/src/modules/swapKitConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ import type { BalanceResponse, QuoteRequest, QuoteResponse, QuoteResponseRoute }
import { WalletOption } from "../types";
import type { FeeMultiplierConfig } from "./feeMultiplier";

export type V3SwapFlowConfig = {
/**
* Global flag to enable/disable V3 swap flow (raw tx signing from API).
* When disabled, always falls back to named plugins.
* @default true
*/
enabled: boolean;
};

export type SKConfigIntegrations = {
chainflip?: { useSDKBroker?: boolean; brokerUrl: string };
coinbase?: {
Expand Down Expand Up @@ -80,6 +89,7 @@ const initialState = {

requestOptions: { retry: { backoffMultiplier: 2, baseDelay: 300, maxDelay: 5000, maxRetries: 3 }, timeoutMs: 30000 },
rpcUrls,
v3SwapFlow: { enabled: true } as V3SwapFlowConfig,
wallets: Object.values(WalletOption),
};
type SKState = typeof initialState;
Expand All @@ -89,10 +99,11 @@ export type SKConfigState = {
chains?: SKState["chains"];
endpoints?: Partial<CustomApiEndpoints>;
envs?: Partial<SKState["envs"]>;
feeMultipliers?: FeeMultiplierConfig;
integrations?: Partial<SKConfigIntegrations>;
rpcUrls?: Partial<SKState["rpcUrls"]>;
v3SwapFlow?: Partial<V3SwapFlowConfig>;
wallets?: SKState["wallets"];
feeMultipliers?: FeeMultiplierConfig;
};

type SwapKitConfigStore = SKState & {
Expand Down Expand Up @@ -122,6 +133,7 @@ export const useSwapKitStore = create<SwapKitConfigStore>((set) => ({
feeMultipliers: config?.feeMultipliers || s.feeMultipliers,
integrations: { ...s.integrations, ...config?.integrations },
rpcUrls: { ...s.rpcUrls, ...config?.rpcUrls },
v3SwapFlow: { ...s.v3SwapFlow, ...config?.v3SwapFlow },
wallets: s.wallets.concat(config?.wallets || []),
})),
setEndpoint: (key, endpoint) => set((s) => ({ endpoints: { ...s.endpoints, [key]: endpoint } })),
Expand Down Expand Up @@ -149,6 +161,7 @@ export const useSwapKitConfig = () =>
feeMultipliers: state?.feeMultipliers,
integrations: state?.integrations,
rpcUrls: state?.rpcUrls,
v3SwapFlow: state?.v3SwapFlow,
wallets: state?.wallets,
})),
);
Expand Down
4 changes: 4 additions & 0 deletions packages/helpers/src/modules/swapKitError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,10 @@ const errorCodes = {
* Garden Plugin
*/
plugin_garden_missing_data: 42001,
/**
* Swap Plugin
*/
plugin_generic_swap_invalid_data: 43001,
/**
* SwapKit API
*/
Expand Down
5 changes: 4 additions & 1 deletion packages/helpers/src/types/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ export type GenericSwapParams<T = unknown> = {
route: T;
};

export type SwapParams<PluginNames = string, R = unknown> = GenericSwapParams<R> & { pluginName?: PluginNames };
export type SwapParams<PluginNames = string, R = unknown> = GenericSwapParams<R> & {
pluginName?: PluginNames;
useApiTx?: boolean;
};

export enum FeeOption {
Average = "average",
Expand Down
Loading
Loading