@swapkit/plugins 0.0.0-nightly-20250304130539

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/chainflip/index.cjs +3 -0
  2. package/dist/chainflip/index.cjs.map +11 -0
  3. package/dist/chainflip/index.js +3 -0
  4. package/dist/chainflip/index.js.map +11 -0
  5. package/dist/chunk-fazw0jvt.js +3 -0
  6. package/dist/chunk-fazw0jvt.js.map +9 -0
  7. package/dist/chunk-tvrdndbw.js +4 -0
  8. package/dist/chunk-tvrdndbw.js.map +9 -0
  9. package/dist/evm/index.cjs +3 -0
  10. package/dist/evm/index.cjs.map +10 -0
  11. package/dist/evm/index.js +3 -0
  12. package/dist/evm/index.js.map +10 -0
  13. package/dist/index.cjs +3 -0
  14. package/dist/index.cjs.map +9 -0
  15. package/dist/index.js +2 -0
  16. package/dist/index.js.map +9 -0
  17. package/dist/kado/index.cjs +20 -0
  18. package/dist/kado/index.cjs.map +12 -0
  19. package/dist/kado/index.js +20 -0
  20. package/dist/kado/index.js.map +12 -0
  21. package/dist/radix/index.cjs +3 -0
  22. package/dist/radix/index.cjs.map +10 -0
  23. package/dist/radix/index.js +3 -0
  24. package/dist/radix/index.js.map +10 -0
  25. package/dist/thorchain/index.cjs +3 -0
  26. package/dist/thorchain/index.cjs.map +11 -0
  27. package/dist/thorchain/index.js +3 -0
  28. package/dist/thorchain/index.js.map +11 -0
  29. package/package.json +64 -0
  30. package/src/chainflip/broker.ts +127 -0
  31. package/src/chainflip/index.ts +3 -0
  32. package/src/chainflip/plugin.ts +73 -0
  33. package/src/chainflip/types.ts +48 -0
  34. package/src/evm/index.ts +82 -0
  35. package/src/index.ts +17 -0
  36. package/src/kado/helpers.ts +117 -0
  37. package/src/kado/index.ts +3 -0
  38. package/src/kado/plugin.ts +234 -0
  39. package/src/kado/types.ts +225 -0
  40. package/src/radix/index.ts +36 -0
  41. package/src/thorchain/index.ts +3 -0
  42. package/src/thorchain/plugin.ts +492 -0
  43. package/src/thorchain/shared.ts +23 -0
  44. package/src/thorchain/types.ts +83 -0
@@ -0,0 +1,492 @@
1
+ import {
2
+ ApproveMode,
3
+ type ApproveReturnType,
4
+ AssetValue,
5
+ Chain,
6
+ type CryptoChain,
7
+ type EVMChain,
8
+ EVMChains,
9
+ type ErrorKeys,
10
+ FeeOption,
11
+ MemoType,
12
+ ProviderName,
13
+ SwapKitError,
14
+ type SwapKitPluginParams,
15
+ type SwapParams,
16
+ createPlugin,
17
+ getMemoForDeposit,
18
+ getMemoForLeaveAndBond,
19
+ getMemoForNamePreferredAssetRegister,
20
+ getMemoForNameRegister,
21
+ getMemoForSaverDeposit,
22
+ getMemoForSaverWithdraw,
23
+ getMemoForUnbond,
24
+ getMemoForWithdraw,
25
+ getMinAmountByChain,
26
+ wrapWithThrow,
27
+ } from "@swapkit/helpers";
28
+ import { type QuoteResponseRoute, SwapKitApi, type THORNodeType } from "@swapkit/helpers/api";
29
+ import {
30
+ MayaArbitrumVaultAbi,
31
+ MayaEthereumVaultAbi,
32
+ TCAvalancheDepositABI,
33
+ TCBaseDepositABI,
34
+ TCBscDepositABI,
35
+ TCEthereumVaultAbi,
36
+ } from "@swapkit/helpers/contracts";
37
+
38
+ import { prepareTxParams, validateAddressType } from "./shared";
39
+ import type {
40
+ AddLiquidityParams,
41
+ AddLiquidityPartParams,
42
+ ApproveParams,
43
+ CoreTxParams,
44
+ CreateLiquidityParams,
45
+ NodeActionParams,
46
+ RegisterThornameParams,
47
+ SavingsParams,
48
+ WithdrawParams,
49
+ } from "./types";
50
+
51
+ const gasFeeMultiplier: Record<FeeOption, number> = {
52
+ [FeeOption.Average]: 1.2,
53
+ [FeeOption.Fast]: 1.5,
54
+ [FeeOption.Fastest]: 2,
55
+ };
56
+
57
+ const TCSpecificAbi = {
58
+ [Chain.Avalanche]: TCAvalancheDepositABI,
59
+ [Chain.Base]: TCBaseDepositABI,
60
+ [Chain.BinanceSmartChain]: TCBscDepositABI,
61
+ [Chain.Ethereum]: TCEthereumVaultAbi,
62
+ };
63
+
64
+ const MayaSpecificAbi = {
65
+ [Chain.Arbitrum]: MayaArbitrumVaultAbi,
66
+ [Chain.Ethereum]: MayaEthereumVaultAbi,
67
+ };
68
+
69
+ export const ThorchainPlugin = createPlugin({
70
+ name: "thorchain",
71
+ methods: createTCBasedPlugin(Chain.THORChain),
72
+ properties: {
73
+ supportedSwapkitProviders: [ProviderName.THORCHAIN, ProviderName.THORCHAIN_STREAMING],
74
+ },
75
+ });
76
+
77
+ export const MayachainPlugin = createPlugin({
78
+ name: "mayachain",
79
+ methods: createTCBasedPlugin(Chain.Maya),
80
+ properties: {
81
+ supportedSwapkitProviders: [ProviderName.MAYACHAIN],
82
+ },
83
+ });
84
+
85
+ function getInboundDataFunction(type?: THORNodeType) {
86
+ return async function getInboundDataByChain<T extends Chain>(chain: T) {
87
+ if (
88
+ (type === "thorchain" && chain === Chain.THORChain) ||
89
+ (type === "mayachain" && chain === Chain.Maya)
90
+ ) {
91
+ return { gas_rate: "0", router: "", address: "", halted: false, chain };
92
+ }
93
+
94
+ const inboundData = await SwapKitApi.thornode.getInboundAddresses(type);
95
+ const chainAddressData = inboundData.find((item) => item.chain === chain);
96
+
97
+ if (!chainAddressData) throw new SwapKitError("core_inbound_data_not_found");
98
+ if (chainAddressData?.halted) throw new SwapKitError("core_chain_halted");
99
+
100
+ return chainAddressData;
101
+ };
102
+ }
103
+
104
+ type PluginChain = Chain.Maya | Chain.THORChain;
105
+
106
+ function createTCBasedPlugin<T extends PluginChain>(pluginChain: T) {
107
+ return function plugin({ getWallet }: SwapKitPluginParams) {
108
+ const pluginType = pluginChain === Chain.Maya ? "mayachain" : "thorchain";
109
+ const getInboundDataByChain = getInboundDataFunction(pluginType);
110
+
111
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: TODO: refactor/split
112
+ async function approve<T extends ApproveMode>({
113
+ assetValue,
114
+ type = "checkOnly" as T,
115
+ }: { type: T; assetValue: AssetValue }) {
116
+ const router = (await getInboundDataByChain(assetValue.chain)).router as string;
117
+
118
+ const chain = assetValue.chain as EVMChain;
119
+
120
+ const isEVMChain = EVMChains.includes(chain as EVMChain);
121
+ const isNativeEVM = isEVMChain && assetValue.isGasAsset;
122
+
123
+ if (isNativeEVM || !isEVMChain || assetValue.isSynthetic) {
124
+ return Promise.resolve(type === "checkOnly" ? true : "approved") as ApproveReturnType<T>;
125
+ }
126
+
127
+ const wallet = getWallet(chain);
128
+
129
+ if (!wallet) {
130
+ throw new SwapKitError("core_wallet_connection_not_found");
131
+ }
132
+
133
+ const walletAction = type === "checkOnly" ? wallet.isApproved : wallet.approve;
134
+
135
+ if (!(assetValue.address && wallet.address)) {
136
+ throw new SwapKitError("core_approve_asset_address_or_from_not_found");
137
+ }
138
+
139
+ return walletAction({
140
+ amount: assetValue.getBaseValue("bigint"),
141
+ assetAddress: assetValue.address,
142
+ from: wallet.address,
143
+ spenderAddress: router,
144
+ });
145
+ }
146
+
147
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: TODO refactor
148
+ async function deposit({
149
+ assetValue,
150
+ recipient,
151
+ router,
152
+ ...rest
153
+ }: CoreTxParams & { router?: string }) {
154
+ const abis = pluginType === "thorchain" ? TCSpecificAbi : MayaSpecificAbi;
155
+ const { chain, symbol, ticker } = assetValue;
156
+
157
+ const wallet = getWallet(chain as CryptoChain);
158
+ if (!wallet) {
159
+ throw new SwapKitError("core_wallet_connection_not_found");
160
+ }
161
+ const { address } = wallet;
162
+ const isAddressValidated = validateAddressType({ address, chain });
163
+ if (!isAddressValidated) {
164
+ throw new SwapKitError("core_transaction_invalid_sender_address");
165
+ }
166
+
167
+ const params = prepareTxParams({ from: address, assetValue, recipient, router, ...rest });
168
+
169
+ try {
170
+ const abi = abis?.[chain as keyof typeof abis];
171
+
172
+ if (!abi) {
173
+ const wallet = getWallet(chain as PluginChain);
174
+ const shouldDeposit = pluginChain === chain && recipient === "";
175
+ // TODO: Ask @Towan - that's the same action? :)
176
+ return shouldDeposit ? wallet.deposit(params) : wallet.transfer(params);
177
+ }
178
+
179
+ const { getChecksumAddressFromAsset } = await import("@swapkit/toolboxes/evm");
180
+ const wallet = getWallet(chain as EVMChain);
181
+
182
+ return wallet.call<string>({
183
+ abi,
184
+ contractAddress: router || ((await getInboundDataByChain(chain)).router as string),
185
+ funcName: "depositWithExpiry",
186
+ funcParams: [
187
+ recipient,
188
+ getChecksumAddressFromAsset({ chain, symbol, ticker }, chain as EVMChain),
189
+ assetValue.getBaseValue("string"),
190
+ params.memo,
191
+ rest.expiration || Number.parseInt(`${(Date.now() + 15 * 60 * 1000) / 1000}`),
192
+ ],
193
+ txOverrides: {
194
+ from: params.from,
195
+ value: assetValue.isGasAsset ? assetValue.getBaseValue("bigint") : undefined,
196
+ },
197
+ });
198
+ } catch (error) {
199
+ const errorMessage =
200
+ // @ts-expect-error Fine to use error as string
201
+ typeof error === "string" ? error.toLowerCase() : error?.message.toLowerCase();
202
+ const isInsufficientFunds = errorMessage?.includes("insufficient funds");
203
+ const isGas = errorMessage?.includes("gas");
204
+ const isServer = errorMessage?.includes("server");
205
+ const isUserRejected = errorMessage?.includes("user rejected");
206
+ const errorKey: ErrorKeys = isInsufficientFunds
207
+ ? "core_transaction_deposit_insufficient_funds_error"
208
+ : isGas
209
+ ? "core_transaction_deposit_gas_error"
210
+ : isServer
211
+ ? "core_transaction_deposit_server_error"
212
+ : isUserRejected
213
+ ? "core_transaction_user_rejected"
214
+ : "core_transaction_deposit_error";
215
+
216
+ throw new SwapKitError(errorKey, error);
217
+ }
218
+ }
219
+
220
+ async function depositToProtocol({
221
+ memo,
222
+ assetValue,
223
+ }: { assetValue: AssetValue; memo: string }) {
224
+ const mimir = await SwapKitApi.thornode.getMimirInfo(pluginType);
225
+
226
+ // check if trading is halted or not
227
+ if (mimir.HALTCHAINGLOBAL >= 1 || mimir.HALTTHORCHAIN >= 1) {
228
+ throw new SwapKitError("thorchain_chain_halted");
229
+ }
230
+
231
+ return deposit({ assetValue, recipient: "", memo });
232
+ }
233
+
234
+ async function depositToPool({
235
+ assetValue,
236
+ memo,
237
+ feeOptionKey = FeeOption.Fast,
238
+ }: { assetValue: AssetValue; memo: string; feeOptionKey?: FeeOption }) {
239
+ const {
240
+ gas_rate = "0",
241
+ router,
242
+ address: poolAddress,
243
+ } = await getInboundDataByChain(assetValue.chain);
244
+
245
+ return deposit({
246
+ assetValue,
247
+ recipient: poolAddress,
248
+ memo,
249
+ router,
250
+ feeRate: Number.parseInt(gas_rate) * gasFeeMultiplier[feeOptionKey],
251
+ });
252
+ }
253
+
254
+ function approveAssetValue(params: ApproveParams) {
255
+ return approve({ ...params, type: ApproveMode.Approve });
256
+ }
257
+
258
+ function isAssetValueApproved(params: ApproveParams) {
259
+ return approve({ ...params, type: ApproveMode.CheckOnly });
260
+ }
261
+
262
+ function registerName({ assetValue, ...params }: RegisterThornameParams) {
263
+ return depositToProtocol({ assetValue, memo: getMemoForNameRegister(params) });
264
+ }
265
+
266
+ function registerPreferredAsset({
267
+ assetValue,
268
+ payoutAddress,
269
+ name,
270
+ ownerAddress,
271
+ }: {
272
+ assetValue: AssetValue;
273
+ payoutAddress?: string;
274
+ name: string;
275
+ ownerAddress: string;
276
+ }) {
277
+ const payout = payoutAddress || getWallet(assetValue.chain as CryptoChain)?.address;
278
+
279
+ if (!payout) {
280
+ throw new SwapKitError("thorchain_preferred_asset_payout_required");
281
+ }
282
+
283
+ return depositToProtocol({
284
+ assetValue: AssetValue.from({ chain: pluginChain }),
285
+ memo: getMemoForNamePreferredAssetRegister({
286
+ asset: assetValue.toString(),
287
+ chain: assetValue.chain,
288
+ name,
289
+ owner: ownerAddress,
290
+ payout,
291
+ }),
292
+ });
293
+ }
294
+
295
+ function nodeAction({ type, assetValue, address }: NodeActionParams) {
296
+ const memo =
297
+ type === MemoType.UNBOND
298
+ ? getMemoForUnbond({ address, unbondAmount: assetValue.getBaseValue("number") })
299
+ : getMemoForLeaveAndBond({ type, address });
300
+
301
+ const assetToTransfer =
302
+ type === MemoType.BOND ? assetValue : getMinAmountByChain(pluginChain);
303
+ return depositToProtocol({ memo, assetValue: assetToTransfer });
304
+ }
305
+
306
+ async function createLiquidity({ baseAssetValue, assetValue }: CreateLiquidityParams) {
307
+ if (baseAssetValue.lte(0) || assetValue.lte(0)) {
308
+ throw new SwapKitError("core_transaction_create_liquidity_invalid_params");
309
+ }
310
+
311
+ const assetAddress = getWallet(assetValue.chain as CryptoChain).address;
312
+ const baseAssetAddress = getWallet(pluginChain).address;
313
+
314
+ const baseAssetTx = await wrapWithThrow(() => {
315
+ return depositToPool({
316
+ assetValue: baseAssetValue,
317
+ memo: getMemoForDeposit({ ...assetValue, address: assetAddress }),
318
+ });
319
+ }, "core_transaction_create_liquidity_base_error");
320
+
321
+ const assetTx = await wrapWithThrow(() => {
322
+ return depositToPool({
323
+ assetValue,
324
+ memo: getMemoForDeposit({ ...assetValue, address: baseAssetAddress }),
325
+ });
326
+ }, "core_transaction_create_liquidity_asset_error");
327
+
328
+ return { baseAssetTx, assetTx };
329
+ }
330
+
331
+ function addLiquidityPart({
332
+ assetValue,
333
+ poolAddress,
334
+ address,
335
+ symmetric,
336
+ }: AddLiquidityPartParams) {
337
+ if (symmetric && !address) {
338
+ throw new SwapKitError("core_transaction_add_liquidity_invalid_params");
339
+ }
340
+ const memo = getMemoForDeposit({
341
+ chain: poolAddress.split(".")[0] as Chain,
342
+ symbol: poolAddress.split(".")[1] as string,
343
+ address: symmetric ? address : "",
344
+ });
345
+
346
+ return depositToPool({ assetValue, memo });
347
+ }
348
+
349
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: TODO: Refactor
350
+ async function addLiquidity({
351
+ baseAssetValue,
352
+ assetValue,
353
+ baseAssetAddr,
354
+ assetAddr,
355
+ isPendingSymmAsset,
356
+ mode = "sym",
357
+ }: AddLiquidityParams) {
358
+ const { chain, symbol } = assetValue;
359
+ const isSym = mode === "sym";
360
+ const baseTransfer = baseAssetValue?.gt(0) && (isSym || mode === "baseAsset");
361
+ const assetTransfer = assetValue?.gt(0) && (isSym || mode === "asset");
362
+ const includeBaseAddress = isPendingSymmAsset || baseTransfer;
363
+ const baseAssetWalletAddress = getWallet(pluginChain).address;
364
+
365
+ const baseAddress = includeBaseAddress ? baseAssetAddr || baseAssetWalletAddress : "";
366
+ const assetAddress =
367
+ isSym || mode === "asset" ? assetAddr || getWallet(chain as CryptoChain).address : "";
368
+
369
+ if (!(baseTransfer || assetTransfer)) {
370
+ throw new SwapKitError("core_transaction_add_liquidity_invalid_params");
371
+ }
372
+ if (includeBaseAddress && !baseAddress) {
373
+ throw new SwapKitError("core_transaction_add_liquidity_base_address");
374
+ }
375
+
376
+ const baseAssetTx =
377
+ baseTransfer && baseAssetValue
378
+ ? await wrapWithThrow(() => {
379
+ return depositToPool({
380
+ assetValue: baseAssetValue,
381
+ memo: getMemoForDeposit({ chain, symbol, address: assetAddress }),
382
+ });
383
+ }, "core_transaction_add_liquidity_base_error")
384
+ : undefined;
385
+
386
+ const assetTx =
387
+ assetTransfer && assetValue
388
+ ? await wrapWithThrow(() => {
389
+ return depositToPool({
390
+ assetValue,
391
+ memo: getMemoForDeposit({ chain, symbol, address: baseAddress }),
392
+ });
393
+ }, "core_transaction_add_liquidity_asset_error")
394
+ : undefined;
395
+
396
+ return { baseAssetTx, assetTx };
397
+ }
398
+
399
+ function savings({ assetValue, memo, percent, type }: SavingsParams) {
400
+ const { chain, symbol } = assetValue;
401
+ const isDeposit = type === "add";
402
+ const memoString = isDeposit
403
+ ? getMemoForSaverDeposit({ symbol, chain })
404
+ : getMemoForSaverWithdraw({
405
+ basisPoints: Math.min(10000, Math.round(percent * 100)),
406
+ symbol,
407
+ chain,
408
+ });
409
+
410
+ return depositToPool({
411
+ memo: memo || memoString,
412
+ assetValue: isDeposit ? assetValue : getMinAmountByChain(chain),
413
+ });
414
+ }
415
+
416
+ function withdraw({ memo, assetValue, percent, from, to }: WithdrawParams) {
417
+ const targetAsset =
418
+ to === "baseAsset" && from !== "baseAsset"
419
+ ? AssetValue.from({ chain: pluginChain })
420
+ : (from === "sym" && to === "sym") || from === "baseAsset" || from === "asset"
421
+ ? undefined
422
+ : assetValue;
423
+
424
+ const value = getMinAmountByChain(from === "asset" ? assetValue.chain : pluginChain);
425
+ const memoString =
426
+ memo ||
427
+ getMemoForWithdraw({
428
+ symbol: assetValue.symbol,
429
+ chain: assetValue.chain,
430
+ ticker: assetValue.ticker,
431
+ basisPoints: Math.min(10000, Math.round(percent * 100)),
432
+ targetAsset: targetAsset?.toString(),
433
+ });
434
+
435
+ return depositToPool({ assetValue: value, memo: memoString });
436
+ }
437
+
438
+ async function swap({
439
+ feeOptionKey,
440
+ route,
441
+ }: SwapParams<typeof pluginType, QuoteResponseRoute>) {
442
+ const { memo, expiration, targetAddress } = route;
443
+
444
+ const assetValue = await AssetValue.from({
445
+ asyncTokenLookup: true,
446
+ asset: route.sellAsset,
447
+ value: route.sellAmount,
448
+ });
449
+
450
+ if (!assetValue) {
451
+ throw new SwapKitError("core_swap_asset_not_recognized");
452
+ }
453
+
454
+ const isRecipientValidated = validateAddressType({
455
+ address: route.destinationAddress,
456
+ chain: AssetValue.from({ asset: route.buyAsset }).chain,
457
+ });
458
+
459
+ if (!isRecipientValidated) {
460
+ throw new SwapKitError("core_transaction_invalid_recipient_address");
461
+ }
462
+
463
+ const { address: recipient } = await getInboundDataByChain(assetValue.chain);
464
+
465
+ return deposit({
466
+ expiration: Number(expiration),
467
+ assetValue,
468
+ memo,
469
+ feeOptionKey,
470
+ router: targetAddress,
471
+ recipient,
472
+ });
473
+ }
474
+
475
+ return {
476
+ addLiquidity,
477
+ addLiquidityPart,
478
+ approveAssetValue,
479
+ createLiquidity,
480
+ deposit,
481
+ depositToPool,
482
+ getInboundDataByChain,
483
+ isAssetValueApproved,
484
+ nodeAction,
485
+ registerName,
486
+ registerPreferredAsset,
487
+ savings,
488
+ swap,
489
+ withdraw,
490
+ };
491
+ };
492
+ }
@@ -0,0 +1,23 @@
1
+ import { Chain } from "@swapkit/helpers";
2
+ import type { CoreTxParams } from "./types";
3
+
4
+ export function validateAddressType({ chain, address }: { chain?: Chain; address?: string }) {
5
+ if (!address) return false;
6
+
7
+ switch (chain) {
8
+ case Chain.Bitcoin:
9
+ // filter out taproot addresses
10
+ return !address.startsWith("bc1p");
11
+ default:
12
+ return true;
13
+ }
14
+ }
15
+
16
+ export function prepareTxParams({
17
+ assetValue,
18
+ from,
19
+ memo = "",
20
+ ...restTxParams
21
+ }: CoreTxParams & { from: string; router?: string }) {
22
+ return { ...restTxParams, memo, from, assetValue };
23
+ }
@@ -0,0 +1,83 @@
1
+ import type { AssetValue, FeeOption, MemoType } from "@swapkit/helpers";
2
+
3
+ export type AddLiquidityPartParams = {
4
+ assetValue: AssetValue;
5
+ address?: string;
6
+ poolAddress: string;
7
+ symmetric: boolean;
8
+ };
9
+
10
+ export type AddLiquidityParams = {
11
+ assetAddr?: string;
12
+ assetValue: AssetValue;
13
+ baseAssetAddr?: string;
14
+ baseAssetValue: AssetValue;
15
+ isPendingSymmAsset?: boolean;
16
+ mode?: "sym" | "baseAsset" | "asset";
17
+ };
18
+
19
+ export type ApproveParams = {
20
+ assetValue: AssetValue;
21
+ contractAddress?: string;
22
+ };
23
+
24
+ export type CreateLiquidityParams = {
25
+ baseAssetValue: AssetValue;
26
+ assetValue: AssetValue;
27
+ };
28
+
29
+ export type CoreTxParams = {
30
+ assetValue: AssetValue;
31
+ recipient: string;
32
+ memo?: string;
33
+ feeOptionKey?: FeeOption;
34
+ feeRate?: number;
35
+ data?: string;
36
+ from?: string;
37
+ expiration?: number;
38
+ };
39
+
40
+ export type LoanParams = {
41
+ assetValue: AssetValue;
42
+ memo?: string;
43
+ minAmount: AssetValue;
44
+ type: "open" | "close";
45
+ };
46
+
47
+ export type NodeActionParams = { address: string } & (
48
+ | { type: MemoType.BOND | MemoType.UNBOND; assetValue: AssetValue }
49
+ | { type: MemoType.LEAVE; assetValue?: undefined }
50
+ );
51
+
52
+ export type SavingsParams = { assetValue: AssetValue; memo?: string } & (
53
+ | { type: "add"; percent?: undefined }
54
+ | { type: "withdraw"; percent: number }
55
+ );
56
+
57
+ export type RegisterThornameParams = {
58
+ assetValue: AssetValue;
59
+ name: string;
60
+ chain: string;
61
+ address: string;
62
+ owner?: string;
63
+ preferredAsset?: string;
64
+ };
65
+
66
+ export type RegisterPreferredAssetParams = {
67
+ assetValue: AssetValue;
68
+ name: string;
69
+ chain: string;
70
+ address: string;
71
+ owner: string;
72
+ };
73
+
74
+ type CommonWithdrawParams = {
75
+ assetValue: AssetValue;
76
+ memo?: string;
77
+ percent: number;
78
+ };
79
+
80
+ export type WithdrawParams = CommonWithdrawParams & {
81
+ from: "sym" | "baseAsset" | "asset";
82
+ to: "sym" | "baseAsset" | "asset";
83
+ };