@swapkit/core 1.0.0-rc.17 → 1.0.0-rc.170
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.
- package/dist/index.js +3 -0
- package/dist/index.js.map +37 -0
- package/package.json +26 -49
- package/src/__tests__/helpers.test.ts +65 -0
- package/src/aggregator/contracts/avaxGeneric.ts +50 -50
- package/src/aggregator/contracts/avaxWoofi.ts +80 -80
- package/src/aggregator/contracts/bscGeneric.ts +59 -59
- package/src/aggregator/contracts/ethGeneric.ts +50 -50
- package/src/aggregator/contracts/index.ts +30 -28
- package/src/aggregator/contracts/pancakeV2.ts +80 -80
- package/src/aggregator/contracts/pangolin.ts +65 -65
- package/src/aggregator/contracts/routers/index.ts +58 -0
- package/src/aggregator/contracts/routers/kyber.ts +402 -0
- package/src/aggregator/contracts/routers/oneinch.ts +2188 -0
- package/src/aggregator/contracts/routers/pancakeswap.ts +340 -0
- package/src/aggregator/contracts/routers/pangolin.ts +340 -0
- package/src/aggregator/contracts/routers/sushiswap.ts +340 -0
- package/src/aggregator/contracts/routers/traderJoe.ts +340 -0
- package/src/aggregator/contracts/routers/uniswapv2.ts +340 -0
- package/src/aggregator/contracts/routers/uniswapv3.ts +254 -0
- package/src/aggregator/contracts/routers/woofi.ts +171 -0
- package/src/aggregator/contracts/sushiswap.ts +65 -65
- package/src/aggregator/contracts/traderJoe.ts +65 -65
- package/src/aggregator/contracts/uniswapV2.ts +65 -65
- package/src/aggregator/contracts/uniswapV2Leg.ts +70 -70
- package/src/aggregator/contracts/uniswapV3_100.ts +70 -70
- package/src/aggregator/contracts/uniswapV3_10000.ts +70 -70
- package/src/aggregator/contracts/uniswapV3_3000.ts +70 -70
- package/src/aggregator/contracts/uniswapV3_500.ts +70 -70
- package/src/aggregator/getSwapParams.ts +12 -12
- package/src/client.ts +438 -0
- package/src/helpers/explorerUrls.ts +45 -0
- package/src/index.ts +6 -4
- package/src/types.ts +44 -0
- package/LICENSE +0 -201
- package/dist/index-9e36735e.cjs +0 -1
- package/dist/index-cf1865cd.js +0 -649
- package/dist/index.cjs +0 -2
- package/dist/index.d.ts +0 -216
- package/dist/index.es.js +0 -4181
- package/src/client/__tests__/helpers.test.ts +0 -69
- package/src/client/explorerUrls.ts +0 -62
- package/src/client/index.ts +0 -699
- package/src/client/thornode.ts +0 -31
- package/src/client/types.ts +0 -103
package/src/client/index.ts
DELETED
|
@@ -1,699 +0,0 @@
|
|
|
1
|
-
import type { Keys, ThornameRegisterParam } from '@swapkit/helpers';
|
|
2
|
-
import {
|
|
3
|
-
AssetValue,
|
|
4
|
-
gasFeeMultiplier,
|
|
5
|
-
getMemoFor,
|
|
6
|
-
getMinAmountByChain,
|
|
7
|
-
SwapKitError,
|
|
8
|
-
SwapKitNumber,
|
|
9
|
-
} from '@swapkit/helpers';
|
|
10
|
-
import type { CosmosLikeToolbox } from '@swapkit/toolbox-cosmos';
|
|
11
|
-
import type { AVAXToolbox, BSCToolbox, ETHToolbox, EVMToolbox } from '@swapkit/toolbox-evm';
|
|
12
|
-
import type { UTXOToolbox } from '@swapkit/toolbox-utxo';
|
|
13
|
-
import type {
|
|
14
|
-
AddChainWalletParams,
|
|
15
|
-
EVMChain,
|
|
16
|
-
EVMWalletOptions,
|
|
17
|
-
ExtendParams,
|
|
18
|
-
WalletOption,
|
|
19
|
-
} from '@swapkit/types';
|
|
20
|
-
import {
|
|
21
|
-
AGG_SWAP,
|
|
22
|
-
Chain,
|
|
23
|
-
ChainToChainId,
|
|
24
|
-
FeeOption,
|
|
25
|
-
MemoType,
|
|
26
|
-
SWAP_IN,
|
|
27
|
-
SWAP_OUT,
|
|
28
|
-
TCAvalancheDepositABI,
|
|
29
|
-
TCBscDepositABI,
|
|
30
|
-
TCEthereumVaultAbi,
|
|
31
|
-
} from '@swapkit/types';
|
|
32
|
-
|
|
33
|
-
import type { AGG_CONTRACT_ADDRESS } from '../aggregator/contracts/index.ts';
|
|
34
|
-
import { lowercasedContractAbiMapping } from '../aggregator/contracts/index.ts';
|
|
35
|
-
import { getSwapInParams } from '../aggregator/getSwapParams.ts';
|
|
36
|
-
|
|
37
|
-
import { getExplorerAddressUrl, getExplorerTxUrl } from './explorerUrls.ts';
|
|
38
|
-
import { getInboundData, getMimirData } from './thornode.ts';
|
|
39
|
-
import type {
|
|
40
|
-
CoreTxParams,
|
|
41
|
-
EVMWallet,
|
|
42
|
-
SwapParams,
|
|
43
|
-
ThorchainWallet,
|
|
44
|
-
Wallet,
|
|
45
|
-
WalletMethods,
|
|
46
|
-
} from './types.ts';
|
|
47
|
-
|
|
48
|
-
const getEmptyWalletStructure = () =>
|
|
49
|
-
(Object.values(Chain) as Chain[]).reduce(
|
|
50
|
-
(acc, chain) => {
|
|
51
|
-
acc[chain] = null;
|
|
52
|
-
return acc;
|
|
53
|
-
},
|
|
54
|
-
{} as Record<Chain, null>,
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
export class SwapKitCore<T = ''> {
|
|
58
|
-
public connectedChains: Wallet = getEmptyWalletStructure();
|
|
59
|
-
public connectedWallets: WalletMethods = getEmptyWalletStructure();
|
|
60
|
-
public readonly stagenet: boolean = false;
|
|
61
|
-
|
|
62
|
-
constructor({ stagenet }: { stagenet?: boolean } | undefined = {}) {
|
|
63
|
-
this.stagenet = !!stagenet;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
getAddress = (chain: Chain) => this.connectedChains[chain]?.address || '';
|
|
67
|
-
getExplorerTxUrl = (chain: Chain, txHash: string) => getExplorerTxUrl({ chain, txHash });
|
|
68
|
-
getWallet = <T extends Chain>(chain: Chain) => this.connectedWallets[chain] as WalletMethods[T];
|
|
69
|
-
getExplorerAddressUrl = (chain: Chain, address: string) =>
|
|
70
|
-
getExplorerAddressUrl({ chain, address });
|
|
71
|
-
getBalance = async (chain: Chain, potentialScamFilter?: boolean) => {
|
|
72
|
-
const wallet = await this.getWalletByChain(chain, potentialScamFilter);
|
|
73
|
-
|
|
74
|
-
return wallet?.balance || [];
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
swap = async ({ streamSwap, recipient, route, feeOptionKey }: SwapParams) => {
|
|
78
|
-
const { quoteMode } = route.meta;
|
|
79
|
-
const evmChain = quoteMode.startsWith('ERC20-')
|
|
80
|
-
? Chain.Ethereum
|
|
81
|
-
: quoteMode.startsWith('ARC20-')
|
|
82
|
-
? Chain.Avalanche
|
|
83
|
-
: Chain.BinanceSmartChain;
|
|
84
|
-
|
|
85
|
-
if (!route.complete) throw new SwapKitError('core_swap_route_not_complete');
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
if (AGG_SWAP.includes(quoteMode)) {
|
|
89
|
-
const walletMethods = this.connectedWallets[evmChain];
|
|
90
|
-
if (!walletMethods?.sendTransaction) {
|
|
91
|
-
throw new SwapKitError('core_wallet_connection_not_found');
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const transaction = streamSwap ? route?.streamingSwap?.transaction : route?.transaction;
|
|
95
|
-
if (!transaction) throw new SwapKitError('core_swap_route_transaction_not_found');
|
|
96
|
-
|
|
97
|
-
const { isHexString, parseUnits } = await import('ethers');
|
|
98
|
-
const { data, from, to, value } = route.transaction;
|
|
99
|
-
|
|
100
|
-
const params = {
|
|
101
|
-
data,
|
|
102
|
-
from,
|
|
103
|
-
to: to.toLowerCase(),
|
|
104
|
-
chainId: BigInt(ChainToChainId[evmChain]),
|
|
105
|
-
value: value
|
|
106
|
-
? new SwapKitNumber({
|
|
107
|
-
value: !isHexString(value) ? parseUnits(value, 'wei').toString(16) : value,
|
|
108
|
-
}).baseValueBigInt
|
|
109
|
-
: 0n,
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
return walletMethods.sendTransaction(params, feeOptionKey) as Promise<string>;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (SWAP_OUT.includes(quoteMode)) {
|
|
116
|
-
if (!route.calldata.fromAsset) throw new SwapKitError('core_swap_asset_not_recognized');
|
|
117
|
-
const asset = await AssetValue.fromString(route.calldata.fromAsset);
|
|
118
|
-
if (!asset) throw new SwapKitError('core_swap_asset_not_recognized');
|
|
119
|
-
|
|
120
|
-
const { address: recipient } = await this.#getInboundDataByChain(asset.chain);
|
|
121
|
-
const {
|
|
122
|
-
contract: router,
|
|
123
|
-
calldata: { expiration, amountIn, memo, memoStreamingSwap },
|
|
124
|
-
} = route;
|
|
125
|
-
|
|
126
|
-
const assetValue = asset.add(SwapKitNumber.fromBigInt(BigInt(amountIn), asset.decimal));
|
|
127
|
-
const swapMemo = (streamSwap ? memoStreamingSwap || memo : memo) as string;
|
|
128
|
-
|
|
129
|
-
return this.deposit({
|
|
130
|
-
expiration,
|
|
131
|
-
assetValue,
|
|
132
|
-
memo: swapMemo,
|
|
133
|
-
feeOptionKey,
|
|
134
|
-
router,
|
|
135
|
-
recipient,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (SWAP_IN.includes(quoteMode)) {
|
|
140
|
-
const { calldata, contract: contractAddress } = route;
|
|
141
|
-
if (!contractAddress) throw new SwapKitError('core_swap_contract_not_found');
|
|
142
|
-
|
|
143
|
-
const walletMethods = this.connectedWallets[evmChain];
|
|
144
|
-
const from = this.getAddress(evmChain);
|
|
145
|
-
if (!walletMethods?.sendTransaction || !from) {
|
|
146
|
-
throw new SwapKitError('core_wallet_connection_not_found');
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const { getProvider, toChecksumAddress } = await import('@swapkit/toolbox-evm');
|
|
150
|
-
const provider = getProvider(evmChain);
|
|
151
|
-
const abi = lowercasedContractAbiMapping[contractAddress.toLowerCase()];
|
|
152
|
-
|
|
153
|
-
if (!abi) throw new SwapKitError('core_swap_contract_not_supported', { contractAddress });
|
|
154
|
-
|
|
155
|
-
const contract = await walletMethods.createContract?.(contractAddress, abi, provider);
|
|
156
|
-
|
|
157
|
-
const tx = await contract.getFunction('swapIn').populateTransaction(
|
|
158
|
-
...getSwapInParams({
|
|
159
|
-
streamSwap,
|
|
160
|
-
toChecksumAddress,
|
|
161
|
-
contractAddress: contractAddress as AGG_CONTRACT_ADDRESS,
|
|
162
|
-
recipient,
|
|
163
|
-
calldata,
|
|
164
|
-
}),
|
|
165
|
-
{ from },
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
return walletMethods.sendTransaction(tx, feeOptionKey) as Promise<string>;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
throw new SwapKitError('core_swap_quote_mode_not_supported', { quoteMode });
|
|
172
|
-
} catch (error) {
|
|
173
|
-
throw new SwapKitError('core_swap_transaction_error', error);
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
getWalletByChain = async (chain: Chain, potentialScamFilter?: boolean) => {
|
|
178
|
-
const address = this.getAddress(chain);
|
|
179
|
-
if (!address) return null;
|
|
180
|
-
|
|
181
|
-
const balance = (await this.getWallet(chain)?.getBalance(address, potentialScamFilter)) ?? [
|
|
182
|
-
AssetValue.fromChainOrSignature(chain),
|
|
183
|
-
];
|
|
184
|
-
|
|
185
|
-
this.connectedChains[chain] = {
|
|
186
|
-
address,
|
|
187
|
-
balance,
|
|
188
|
-
walletType: this.connectedChains[chain]?.walletType as WalletOption,
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
return { ...this.connectedChains[chain] };
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
approveAssetValue = (assetValue: AssetValue, contractAddress?: string) =>
|
|
195
|
-
this.#approve({ assetValue, type: 'approve', contractAddress });
|
|
196
|
-
|
|
197
|
-
isAssetValueApproved = (assetValue: AssetValue, contractAddress?: string) =>
|
|
198
|
-
this.#approve<boolean>({ assetValue, contractAddress, type: 'checkOnly' });
|
|
199
|
-
|
|
200
|
-
validateAddress = ({ address, chain }: { address: string; chain: Chain }) =>
|
|
201
|
-
this.getWallet(chain)?.validateAddress?.(address);
|
|
202
|
-
|
|
203
|
-
transfer = async (params: CoreTxParams & { router?: string }) => {
|
|
204
|
-
const walletInstance = this.connectedWallets[params.assetValue.chain];
|
|
205
|
-
if (!walletInstance) throw new SwapKitError('core_wallet_connection_not_found');
|
|
206
|
-
|
|
207
|
-
try {
|
|
208
|
-
return await walletInstance.transfer(this.#prepareTxParams(params));
|
|
209
|
-
} catch (error) {
|
|
210
|
-
throw new SwapKitError('core_swap_transaction_error', error);
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
deposit = async ({
|
|
215
|
-
assetValue,
|
|
216
|
-
recipient,
|
|
217
|
-
router,
|
|
218
|
-
...rest
|
|
219
|
-
}: CoreTxParams & { router?: string }) => {
|
|
220
|
-
const { chain, symbol, ticker } = assetValue;
|
|
221
|
-
const walletInstance = this.connectedWallets[chain];
|
|
222
|
-
if (!walletInstance) throw new SwapKitError('core_wallet_connection_not_found');
|
|
223
|
-
|
|
224
|
-
const params = this.#prepareTxParams({ assetValue, recipient, router, ...rest });
|
|
225
|
-
|
|
226
|
-
try {
|
|
227
|
-
switch (chain) {
|
|
228
|
-
case Chain.THORChain: {
|
|
229
|
-
const wallet = walletInstance as ThorchainWallet;
|
|
230
|
-
return await (recipient === '' ? wallet.deposit(params) : wallet.transfer(params));
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
case Chain.Ethereum:
|
|
234
|
-
case Chain.BinanceSmartChain:
|
|
235
|
-
case Chain.Avalanche: {
|
|
236
|
-
const { getChecksumAddressFromAsset } = await import('@swapkit/toolbox-evm');
|
|
237
|
-
|
|
238
|
-
const abi =
|
|
239
|
-
chain === Chain.Avalanche
|
|
240
|
-
? TCAvalancheDepositABI
|
|
241
|
-
: chain === Chain.BinanceSmartChain
|
|
242
|
-
? TCBscDepositABI
|
|
243
|
-
: TCEthereumVaultAbi;
|
|
244
|
-
|
|
245
|
-
const response = await (
|
|
246
|
-
walletInstance as EVMWallet<typeof AVAXToolbox | typeof ETHToolbox | typeof BSCToolbox>
|
|
247
|
-
).call({
|
|
248
|
-
abi,
|
|
249
|
-
contractAddress:
|
|
250
|
-
router || ((await this.#getInboundDataByChain(chain as EVMChain)).router as string),
|
|
251
|
-
funcName: 'depositWithExpiry',
|
|
252
|
-
funcParams: [
|
|
253
|
-
recipient,
|
|
254
|
-
getChecksumAddressFromAsset({ chain, symbol, ticker }, chain),
|
|
255
|
-
// TODO: (@Towan) Re-Check on that conversion 🙏
|
|
256
|
-
assetValue.getBaseValue('bigint').toString(),
|
|
257
|
-
params.memo,
|
|
258
|
-
rest.expiration,
|
|
259
|
-
],
|
|
260
|
-
txOverrides: {
|
|
261
|
-
from: params.from,
|
|
262
|
-
value: assetValue.isGasAsset ? assetValue.getBaseValue('bigint') : undefined,
|
|
263
|
-
},
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
return response as string;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
default: {
|
|
270
|
-
return await walletInstance.transfer(params);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
} catch (error: any) {
|
|
274
|
-
const errorMessage = (error?.message || error?.toString()).toLowerCase();
|
|
275
|
-
const isInsufficientFunds = errorMessage?.includes('insufficient funds');
|
|
276
|
-
const isGas = errorMessage?.includes('gas');
|
|
277
|
-
const isServer = errorMessage?.includes('server');
|
|
278
|
-
const errorKey: Keys = isInsufficientFunds
|
|
279
|
-
? 'core_transaction_deposit_insufficient_funds_error'
|
|
280
|
-
: isGas
|
|
281
|
-
? 'core_transaction_deposit_gas_error'
|
|
282
|
-
: isServer
|
|
283
|
-
? 'core_transaction_deposit_server_error'
|
|
284
|
-
: 'core_transaction_deposit_error';
|
|
285
|
-
|
|
286
|
-
throw new SwapKitError(errorKey, error);
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* TC related Methods
|
|
292
|
-
*/
|
|
293
|
-
createLiquidity = async ({
|
|
294
|
-
runeAssetValue,
|
|
295
|
-
assetValue,
|
|
296
|
-
}: {
|
|
297
|
-
runeAssetValue: AssetValue;
|
|
298
|
-
assetValue: AssetValue;
|
|
299
|
-
}) => {
|
|
300
|
-
if (runeAssetValue.lte(0) || assetValue.lte(0)) {
|
|
301
|
-
throw new SwapKitError('core_transaction_create_liquidity_invalid_params');
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
let runeTx = '';
|
|
305
|
-
let assetTx = '';
|
|
306
|
-
|
|
307
|
-
try {
|
|
308
|
-
runeTx = await this.#depositToPool({
|
|
309
|
-
assetValue: runeAssetValue,
|
|
310
|
-
memo: getMemoFor(MemoType.DEPOSIT, {
|
|
311
|
-
...assetValue,
|
|
312
|
-
address: this.getAddress(assetValue.chain),
|
|
313
|
-
}),
|
|
314
|
-
});
|
|
315
|
-
} catch (error) {
|
|
316
|
-
throw new SwapKitError('core_transaction_create_liquidity_rune_error', error);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
try {
|
|
320
|
-
assetTx = await this.#depositToPool({
|
|
321
|
-
assetValue,
|
|
322
|
-
memo: getMemoFor(MemoType.DEPOSIT, {
|
|
323
|
-
...assetValue,
|
|
324
|
-
address: this.getAddress(Chain.THORChain),
|
|
325
|
-
}),
|
|
326
|
-
});
|
|
327
|
-
} catch (error) {
|
|
328
|
-
throw new SwapKitError('core_transaction_create_liquidity_asset_error', error);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
return { runeTx, assetTx };
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
addLiquidity = async ({
|
|
335
|
-
poolIdentifier,
|
|
336
|
-
runeAssetValue,
|
|
337
|
-
assetValue,
|
|
338
|
-
runeAddr,
|
|
339
|
-
assetAddr,
|
|
340
|
-
isPendingSymmAsset,
|
|
341
|
-
mode = 'sym',
|
|
342
|
-
}: {
|
|
343
|
-
poolIdentifier: string;
|
|
344
|
-
runeAssetValue: AssetValue;
|
|
345
|
-
assetValue: AssetValue;
|
|
346
|
-
isPendingSymmAsset?: boolean;
|
|
347
|
-
runeAddr?: string;
|
|
348
|
-
assetAddr?: string;
|
|
349
|
-
mode?: 'sym' | 'rune' | 'asset';
|
|
350
|
-
}) => {
|
|
351
|
-
const [chain, ...symbolPath] = poolIdentifier.split('.') as [Chain, string];
|
|
352
|
-
const isSym = mode === 'sym';
|
|
353
|
-
const runeTransfer = runeAssetValue?.gt(0) && (isSym || mode === 'rune');
|
|
354
|
-
const assetTransfer = assetValue?.gt(0) && (isSym || mode === 'asset');
|
|
355
|
-
const includeRuneAddress = isPendingSymmAsset || runeTransfer;
|
|
356
|
-
const runeAddress = includeRuneAddress ? runeAddr || this.getAddress(Chain.THORChain) : '';
|
|
357
|
-
const assetAddress = isSym || mode === 'asset' ? assetAddr || this.getAddress(chain) : '';
|
|
358
|
-
|
|
359
|
-
if (!runeTransfer && !assetTransfer) {
|
|
360
|
-
throw new SwapKitError('core_transaction_add_liquidity_invalid_params');
|
|
361
|
-
}
|
|
362
|
-
if (includeRuneAddress && !runeAddress) {
|
|
363
|
-
throw new SwapKitError('core_transaction_add_liquidity_no_rune_address');
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
let runeTx, assetTx;
|
|
367
|
-
const sharedParams = { chain, symbol: symbolPath.join('.') };
|
|
368
|
-
|
|
369
|
-
if (runeTransfer && runeAssetValue) {
|
|
370
|
-
try {
|
|
371
|
-
runeTx = await this.#depositToPool({
|
|
372
|
-
assetValue: runeAssetValue,
|
|
373
|
-
memo: getMemoFor(MemoType.DEPOSIT, { ...sharedParams, address: assetAddress }),
|
|
374
|
-
});
|
|
375
|
-
} catch (error) {
|
|
376
|
-
throw new SwapKitError('core_transaction_add_liquidity_rune_error', error);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
if (assetTransfer && assetValue) {
|
|
381
|
-
try {
|
|
382
|
-
assetTx = await this.#depositToPool({
|
|
383
|
-
assetValue,
|
|
384
|
-
memo: getMemoFor(MemoType.DEPOSIT, { ...sharedParams, address: runeAddress }),
|
|
385
|
-
});
|
|
386
|
-
} catch (error) {
|
|
387
|
-
throw new SwapKitError('core_transaction_add_liquidity_asset_error', error);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
return { runeTx, assetTx };
|
|
392
|
-
};
|
|
393
|
-
|
|
394
|
-
withdraw = async ({
|
|
395
|
-
memo,
|
|
396
|
-
assetValue,
|
|
397
|
-
percent,
|
|
398
|
-
from,
|
|
399
|
-
to,
|
|
400
|
-
}: {
|
|
401
|
-
memo?: string;
|
|
402
|
-
assetValue: AssetValue;
|
|
403
|
-
percent: number;
|
|
404
|
-
from: 'sym' | 'rune' | 'asset';
|
|
405
|
-
to: 'sym' | 'rune' | 'asset';
|
|
406
|
-
}) => {
|
|
407
|
-
const targetAsset =
|
|
408
|
-
to === 'rune'
|
|
409
|
-
? AssetValue.fromChainOrSignature(Chain.THORChain)
|
|
410
|
-
: (from === 'sym' && to === 'sym') || from === 'rune' || from === 'asset'
|
|
411
|
-
? undefined
|
|
412
|
-
: assetValue;
|
|
413
|
-
|
|
414
|
-
try {
|
|
415
|
-
const txHash = await this.#depositToPool({
|
|
416
|
-
assetValue: getMinAmountByChain(from === 'asset' ? assetValue.chain : Chain.THORChain),
|
|
417
|
-
memo:
|
|
418
|
-
memo ||
|
|
419
|
-
getMemoFor(MemoType.WITHDRAW, {
|
|
420
|
-
symbol: assetValue.symbol,
|
|
421
|
-
chain: assetValue.chain,
|
|
422
|
-
ticker: assetValue.ticker,
|
|
423
|
-
basisPoints: Math.max(10000, Math.round(percent * 100)),
|
|
424
|
-
targetAssetString: targetAsset?.toString(),
|
|
425
|
-
singleSide: false,
|
|
426
|
-
}),
|
|
427
|
-
});
|
|
428
|
-
|
|
429
|
-
return txHash;
|
|
430
|
-
} catch (error) {
|
|
431
|
-
throw new SwapKitError('core_transaction_withdraw_error', error);
|
|
432
|
-
}
|
|
433
|
-
};
|
|
434
|
-
|
|
435
|
-
savings = async ({
|
|
436
|
-
assetValue,
|
|
437
|
-
memo,
|
|
438
|
-
percent,
|
|
439
|
-
type,
|
|
440
|
-
}: { assetValue: AssetValue; memo?: string } & (
|
|
441
|
-
| { type: 'add'; percent?: undefined }
|
|
442
|
-
| { type: 'withdraw'; percent: number }
|
|
443
|
-
)) => {
|
|
444
|
-
const memoType = type === 'add' ? MemoType.DEPOSIT : MemoType.WITHDRAW;
|
|
445
|
-
const memoString =
|
|
446
|
-
memo ||
|
|
447
|
-
getMemoFor(memoType, {
|
|
448
|
-
ticker: assetValue.ticker,
|
|
449
|
-
symbol: assetValue.symbol,
|
|
450
|
-
chain: assetValue.chain,
|
|
451
|
-
singleSide: true,
|
|
452
|
-
basisPoints: percent ? Math.max(10000, Math.round(percent * 100)) : undefined,
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
return this.#depositToPool({ assetValue, memo: memoString });
|
|
456
|
-
};
|
|
457
|
-
|
|
458
|
-
loan = ({
|
|
459
|
-
assetValue,
|
|
460
|
-
memo,
|
|
461
|
-
minAmount,
|
|
462
|
-
type,
|
|
463
|
-
}: {
|
|
464
|
-
assetValue: AssetValue;
|
|
465
|
-
memo?: string;
|
|
466
|
-
minAmount: AssetValue;
|
|
467
|
-
type: 'open' | 'close';
|
|
468
|
-
}) =>
|
|
469
|
-
this.#depositToPool({
|
|
470
|
-
assetValue,
|
|
471
|
-
memo:
|
|
472
|
-
memo ||
|
|
473
|
-
getMemoFor(type === 'open' ? MemoType.OPEN_LOAN : MemoType.CLOSE_LOAN, {
|
|
474
|
-
asset: assetValue.toString(),
|
|
475
|
-
minAmount: minAmount.toString(),
|
|
476
|
-
address: this.getAddress(assetValue.chain),
|
|
477
|
-
}),
|
|
478
|
-
});
|
|
479
|
-
|
|
480
|
-
nodeAction = ({
|
|
481
|
-
type,
|
|
482
|
-
assetValue,
|
|
483
|
-
address,
|
|
484
|
-
}: { address: string } & (
|
|
485
|
-
| { type: 'bond' | 'unbond'; assetValue: AssetValue }
|
|
486
|
-
| { type: 'leave'; assetValue?: undefined }
|
|
487
|
-
)) => {
|
|
488
|
-
const memoType =
|
|
489
|
-
type === 'bond' ? MemoType.BOND : type === 'unbond' ? MemoType.UNBOND : MemoType.LEAVE;
|
|
490
|
-
const memo = getMemoFor(memoType, {
|
|
491
|
-
address,
|
|
492
|
-
unbondAmount: type === 'unbond' ? assetValue.baseValueNumber : undefined,
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
return this.#thorchainTransfer({
|
|
496
|
-
memo,
|
|
497
|
-
assetValue: type === 'bond' ? assetValue : getMinAmountByChain(Chain.THORChain),
|
|
498
|
-
});
|
|
499
|
-
};
|
|
500
|
-
|
|
501
|
-
registerThorname = ({
|
|
502
|
-
assetValue,
|
|
503
|
-
...param
|
|
504
|
-
}: ThornameRegisterParam & { assetValue: AssetValue }) =>
|
|
505
|
-
this.#thorchainTransfer({ assetValue, memo: getMemoFor(MemoType.THORNAME_REGISTER, param) });
|
|
506
|
-
|
|
507
|
-
extend = ({ wallets, config, apis = {}, rpcUrls = {} }: ExtendParams<T>) => {
|
|
508
|
-
try {
|
|
509
|
-
wallets.forEach((wallet) => {
|
|
510
|
-
// @ts-expect-error ANCHOR - Not Worth
|
|
511
|
-
this[wallet.connectMethodName] = wallet.connect({
|
|
512
|
-
addChain: this.#addConnectedChain,
|
|
513
|
-
config: config || {},
|
|
514
|
-
apis,
|
|
515
|
-
rpcUrls,
|
|
516
|
-
});
|
|
517
|
-
});
|
|
518
|
-
} catch (error) {
|
|
519
|
-
throw new SwapKitError('core_extend_error', error);
|
|
520
|
-
}
|
|
521
|
-
};
|
|
522
|
-
|
|
523
|
-
estimateMaxSendableAmount = async ({
|
|
524
|
-
chain,
|
|
525
|
-
params,
|
|
526
|
-
}: {
|
|
527
|
-
chain: Chain;
|
|
528
|
-
params: { from: string; recipient: string; assetValue: AssetValue };
|
|
529
|
-
}) => {
|
|
530
|
-
const walletMethods = this.getWallet<typeof chain>(chain);
|
|
531
|
-
|
|
532
|
-
switch (chain) {
|
|
533
|
-
case Chain.Arbitrum:
|
|
534
|
-
case Chain.Avalanche:
|
|
535
|
-
case Chain.BinanceSmartChain:
|
|
536
|
-
case Chain.Ethereum:
|
|
537
|
-
case Chain.Optimism:
|
|
538
|
-
case Chain.Polygon: {
|
|
539
|
-
const { estimateMaxSendableAmount } = await import('@swapkit/toolbox-evm');
|
|
540
|
-
return estimateMaxSendableAmount({
|
|
541
|
-
...params,
|
|
542
|
-
toolbox: walletMethods as EVMToolbox,
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
case Chain.Bitcoin:
|
|
547
|
-
case Chain.BitcoinCash:
|
|
548
|
-
case Chain.Dogecoin:
|
|
549
|
-
case Chain.Litecoin:
|
|
550
|
-
return (walletMethods as UTXOToolbox).estimateMaxSendableAmount(params);
|
|
551
|
-
|
|
552
|
-
case Chain.Binance:
|
|
553
|
-
case Chain.THORChain:
|
|
554
|
-
case Chain.Cosmos: {
|
|
555
|
-
const { estimateMaxSendableAmount } = await import('@swapkit/toolbox-cosmos');
|
|
556
|
-
return estimateMaxSendableAmount({
|
|
557
|
-
...params,
|
|
558
|
-
toolbox: walletMethods as CosmosLikeToolbox,
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
default:
|
|
563
|
-
throw new SwapKitError('core_estimated_max_spendable_chain_not_supported');
|
|
564
|
-
}
|
|
565
|
-
};
|
|
566
|
-
|
|
567
|
-
/**
|
|
568
|
-
* Wallet connection methods
|
|
569
|
-
*/
|
|
570
|
-
connectXDEFI = async (_chains: Chain[]): Promise<void> => {
|
|
571
|
-
throw new SwapKitError('core_wallet_xdefi_not_installed');
|
|
572
|
-
};
|
|
573
|
-
connectEVMWallet = async (_chains: Chain[] | Chain, _wallet: EVMWalletOptions): Promise<void> => {
|
|
574
|
-
throw new SwapKitError('core_wallet_evmwallet_not_installed');
|
|
575
|
-
};
|
|
576
|
-
connectWalletconnect = async (_chains: Chain[], _options?: any): Promise<void> => {
|
|
577
|
-
throw new SwapKitError('core_wallet_walletconnect_not_installed');
|
|
578
|
-
};
|
|
579
|
-
connectKeystore = async (_chains: Chain[], _phrase: string): Promise<void> => {
|
|
580
|
-
throw new SwapKitError('core_wallet_keystore_not_installed');
|
|
581
|
-
};
|
|
582
|
-
connectLedger = async (_chains: Chain, _derivationPath: number[]): Promise<void> => {
|
|
583
|
-
throw new SwapKitError('core_wallet_ledger_not_installed');
|
|
584
|
-
};
|
|
585
|
-
connectTrezor = async (_chains: Chain, _derivationPath: number[]): Promise<void> => {
|
|
586
|
-
throw new SwapKitError('core_wallet_trezor_not_installed');
|
|
587
|
-
};
|
|
588
|
-
connectKeplr = async (_chain: Chain): Promise<void> => {
|
|
589
|
-
throw new SwapKitError('core_wallet_keplr_not_installed');
|
|
590
|
-
};
|
|
591
|
-
connectOkx = async (_chains: Chain[]): Promise<void> => {
|
|
592
|
-
throw new SwapKitError('core_wallet_okx_not_installed');
|
|
593
|
-
};
|
|
594
|
-
disconnectChain = (chain: Chain) => {
|
|
595
|
-
this.connectedChains[chain] = null;
|
|
596
|
-
this.connectedWallets[chain] = null;
|
|
597
|
-
};
|
|
598
|
-
|
|
599
|
-
#getInboundDataByChain = async (chain: Chain) => {
|
|
600
|
-
if (chain === Chain.THORChain) {
|
|
601
|
-
return {
|
|
602
|
-
gas_rate: '0',
|
|
603
|
-
router: '0',
|
|
604
|
-
address: '',
|
|
605
|
-
halted: false,
|
|
606
|
-
chain: Chain.THORChain,
|
|
607
|
-
};
|
|
608
|
-
}
|
|
609
|
-
const inboundData = await getInboundData(this.stagenet);
|
|
610
|
-
const chainAddressData = inboundData.find((item) => item.chain === chain);
|
|
611
|
-
|
|
612
|
-
if (!chainAddressData) throw new SwapKitError('core_inbound_data_not_found');
|
|
613
|
-
if (chainAddressData?.halted) throw new SwapKitError('core_chain_halted');
|
|
614
|
-
|
|
615
|
-
return chainAddressData;
|
|
616
|
-
};
|
|
617
|
-
|
|
618
|
-
#addConnectedChain = ({ chain, wallet, walletMethods }: AddChainWalletParams) => {
|
|
619
|
-
this.connectedChains[chain] = wallet;
|
|
620
|
-
this.connectedWallets[chain] = walletMethods;
|
|
621
|
-
};
|
|
622
|
-
|
|
623
|
-
#approve = async <T = string>({
|
|
624
|
-
assetValue: { baseValueBigInt, address, chain, isGasAsset, isSynthetic },
|
|
625
|
-
type = 'checkOnly',
|
|
626
|
-
contractAddress,
|
|
627
|
-
}: {
|
|
628
|
-
assetValue: AssetValue;
|
|
629
|
-
type?: 'checkOnly' | 'approve';
|
|
630
|
-
contractAddress?: string;
|
|
631
|
-
}) => {
|
|
632
|
-
const isEVMChain = [Chain.Ethereum, Chain.Avalanche, Chain.BinanceSmartChain].includes(chain);
|
|
633
|
-
const isNativeEVM = isEVMChain && isGasAsset;
|
|
634
|
-
|
|
635
|
-
if (isNativeEVM || !isEVMChain || isSynthetic) return true;
|
|
636
|
-
|
|
637
|
-
const walletMethods = this.connectedWallets[chain as EVMChain];
|
|
638
|
-
const walletAction = type === 'checkOnly' ? walletMethods?.isApproved : walletMethods?.approve;
|
|
639
|
-
|
|
640
|
-
if (!walletAction) throw new SwapKitError('core_wallet_connection_not_found');
|
|
641
|
-
|
|
642
|
-
const from = this.getAddress(chain);
|
|
643
|
-
|
|
644
|
-
if (!address || !from) throw new SwapKitError('core_approve_asset_address_or_from_not_found');
|
|
645
|
-
|
|
646
|
-
const spenderAddress =
|
|
647
|
-
contractAddress || ((await this.#getInboundDataByChain(chain)).router as string);
|
|
648
|
-
|
|
649
|
-
return walletAction({
|
|
650
|
-
amount: baseValueBigInt,
|
|
651
|
-
assetAddress: address,
|
|
652
|
-
from,
|
|
653
|
-
spenderAddress,
|
|
654
|
-
}) as Promise<T>;
|
|
655
|
-
};
|
|
656
|
-
|
|
657
|
-
#depositToPool = async ({
|
|
658
|
-
assetValue,
|
|
659
|
-
memo,
|
|
660
|
-
feeOptionKey = FeeOption.Fast,
|
|
661
|
-
}: {
|
|
662
|
-
assetValue: AssetValue;
|
|
663
|
-
memo: string;
|
|
664
|
-
feeOptionKey?: FeeOption;
|
|
665
|
-
}) => {
|
|
666
|
-
const {
|
|
667
|
-
gas_rate,
|
|
668
|
-
router,
|
|
669
|
-
address: poolAddress,
|
|
670
|
-
} = await this.#getInboundDataByChain(assetValue.chain);
|
|
671
|
-
const feeRate = (parseInt(gas_rate) || 0) * gasFeeMultiplier[feeOptionKey];
|
|
672
|
-
|
|
673
|
-
return this.deposit({
|
|
674
|
-
assetValue,
|
|
675
|
-
recipient: poolAddress,
|
|
676
|
-
memo,
|
|
677
|
-
router,
|
|
678
|
-
feeRate,
|
|
679
|
-
});
|
|
680
|
-
};
|
|
681
|
-
|
|
682
|
-
#thorchainTransfer = async ({ memo, assetValue }: { assetValue: AssetValue; memo: string }) => {
|
|
683
|
-
const mimir = await getMimirData(this.stagenet);
|
|
684
|
-
|
|
685
|
-
// check if trading is halted or not
|
|
686
|
-
if (mimir['HALTCHAINGLOBAL'] >= 1 || mimir['HALTTHORCHAIN'] >= 1) {
|
|
687
|
-
throw new SwapKitError('core_chain_halted');
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
return this.deposit({ assetValue, recipient: '', memo });
|
|
691
|
-
};
|
|
692
|
-
|
|
693
|
-
#prepareTxParams = ({ assetValue, ...restTxParams }: CoreTxParams & { router?: string }) => ({
|
|
694
|
-
...restTxParams,
|
|
695
|
-
memo: restTxParams.memo || '',
|
|
696
|
-
from: this.getAddress(assetValue.chain),
|
|
697
|
-
assetValue,
|
|
698
|
-
});
|
|
699
|
-
}
|