@swapkit/toolboxes 1.0.0-beta.0
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/chunk-fazw0jvt.js +3 -0
- package/dist/chunk-fazw0jvt.js.map +9 -0
- package/dist/chunk-tvrdndbw.js +4 -0
- package/dist/chunk-tvrdndbw.js.map +9 -0
- package/dist/cosmos/index.cjs +3 -0
- package/dist/cosmos/index.cjs.map +19 -0
- package/dist/cosmos/index.js +3 -0
- package/dist/cosmos/index.js.map +19 -0
- package/dist/evm/index.cjs +3 -0
- package/dist/evm/index.cjs.map +24 -0
- package/dist/evm/index.js +3 -0
- package/dist/evm/index.js.map +24 -0
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +9 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +9 -0
- package/dist/radix/index.cjs +3 -0
- package/dist/radix/index.cjs.map +10 -0
- package/dist/radix/index.js +3 -0
- package/dist/radix/index.js.map +10 -0
- package/dist/solana/index.cjs +3 -0
- package/dist/solana/index.cjs.map +10 -0
- package/dist/solana/index.js +3 -0
- package/dist/solana/index.js.map +10 -0
- package/dist/substrate/index.cjs +3 -0
- package/dist/substrate/index.cjs.map +12 -0
- package/dist/substrate/index.js +3 -0
- package/dist/substrate/index.js.map +12 -0
- package/dist/utxo/index.cjs +3 -0
- package/dist/utxo/index.cjs.map +18 -0
- package/dist/utxo/index.js +3 -0
- package/dist/utxo/index.js.map +18 -0
- package/package.json +105 -0
- package/src/cosmos/index.ts +11 -0
- package/src/cosmos/thorchainUtils/addressFormat.ts +24 -0
- package/src/cosmos/thorchainUtils/index.ts +4 -0
- package/src/cosmos/thorchainUtils/messages.ts +244 -0
- package/src/cosmos/thorchainUtils/registry.ts +47 -0
- package/src/cosmos/thorchainUtils/types/client-types.ts +80 -0
- package/src/cosmos/thorchainUtils/types/index.ts +1 -0
- package/src/cosmos/thorchainUtils/types/proto/MsgCompiled.js +2806 -0
- package/src/cosmos/thorchainUtils/types/proto/MsgCompiled.ts +2802 -0
- package/src/cosmos/thorchainUtils/util.ts +46 -0
- package/src/cosmos/toolbox/BaseCosmosToolbox.ts +254 -0
- package/src/cosmos/toolbox/gaia.ts +39 -0
- package/src/cosmos/toolbox/getToolboxByChain.ts +29 -0
- package/src/cosmos/toolbox/kujira.ts +61 -0
- package/src/cosmos/toolbox/thorchain.ts +321 -0
- package/src/cosmos/types.ts +31 -0
- package/src/cosmos/util.ts +230 -0
- package/src/evm/__tests__/ethereum.test.ts +147 -0
- package/src/evm/api.ts +157 -0
- package/src/evm/contracts/eth/multicall.ts +165 -0
- package/src/evm/contracts/op/gasOracle.ts +151 -0
- package/src/evm/helpers.ts +145 -0
- package/src/evm/index.ts +20 -0
- package/src/evm/provider.ts +6 -0
- package/src/evm/toolbox/EVMToolbox.ts +662 -0
- package/src/evm/toolbox/arb.ts +61 -0
- package/src/evm/toolbox/avax.ts +36 -0
- package/src/evm/toolbox/base.ts +42 -0
- package/src/evm/toolbox/bsc.ts +34 -0
- package/src/evm/toolbox/eth.ts +44 -0
- package/src/evm/toolbox/getToolboxByChain.ts +42 -0
- package/src/evm/toolbox/matic.ts +42 -0
- package/src/evm/toolbox/op.ts +163 -0
- package/src/evm/types.ts +118 -0
- package/src/index.ts +0 -0
- package/src/radix/index.ts +151 -0
- package/src/radix/toolbox.ts +693 -0
- package/src/solana/index.ts +49 -0
- package/src/solana/toolbox.ts +272 -0
- package/src/substrate/index.ts +3 -0
- package/src/substrate/toolbox/baseSubstrateToolbox.ts +286 -0
- package/src/substrate/toolbox/index.ts +40 -0
- package/src/substrate/types/index.ts +2 -0
- package/src/substrate/types/network.ts +42 -0
- package/src/substrate/types/wallet.ts +78 -0
- package/src/utxo/helpers/api.ts +431 -0
- package/src/utxo/helpers/bchaddrjs.ts +177 -0
- package/src/utxo/helpers/coinselect.ts +96 -0
- package/src/utxo/helpers/index.ts +5 -0
- package/src/utxo/helpers/txSize.ts +104 -0
- package/src/utxo/helpers/utils.ts +45 -0
- package/src/utxo/index.ts +9 -0
- package/src/utxo/toolbox/bitcoinCash.ts +281 -0
- package/src/utxo/toolbox/index.ts +37 -0
- package/src/utxo/toolbox/utxo.ts +360 -0
- package/src/utxo/types.ts +70 -0
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import type { Pubkey, Secp256k1HdWallet } from "@cosmjs/amino";
|
|
2
|
+
import type { Account } from "@cosmjs/stargate";
|
|
3
|
+
import { base64 } from "@scure/base";
|
|
4
|
+
import {
|
|
5
|
+
BaseDecimal,
|
|
6
|
+
Chain,
|
|
7
|
+
type ChainId,
|
|
8
|
+
CosmosChainPrefixes,
|
|
9
|
+
DerivationPath,
|
|
10
|
+
FeeOption,
|
|
11
|
+
RequestClient,
|
|
12
|
+
SKConfig,
|
|
13
|
+
SwapKitError,
|
|
14
|
+
SwapKitNumber,
|
|
15
|
+
} from "@swapkit/helpers";
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
buildAminoMsg,
|
|
19
|
+
buildDepositTx,
|
|
20
|
+
buildEncodedTxBody,
|
|
21
|
+
buildTransferTx,
|
|
22
|
+
convertToSignable,
|
|
23
|
+
createDefaultAminoTypes,
|
|
24
|
+
createDefaultRegistry,
|
|
25
|
+
parseAminoMessageForDirectSigning,
|
|
26
|
+
} from "../thorchainUtils/index";
|
|
27
|
+
import type {
|
|
28
|
+
DepositParam,
|
|
29
|
+
ThorchainConstantsResponse,
|
|
30
|
+
} from "../thorchainUtils/types/client-types";
|
|
31
|
+
import type { Signer, TransferParams } from "../types";
|
|
32
|
+
import {
|
|
33
|
+
createOfflineStargateClient,
|
|
34
|
+
createSigningStargateClient,
|
|
35
|
+
createStargateClient,
|
|
36
|
+
getDefaultChainFee,
|
|
37
|
+
} from "../util";
|
|
38
|
+
import { BaseCosmosToolbox } from "./BaseCosmosToolbox";
|
|
39
|
+
|
|
40
|
+
function secp256k1HdWalletFromMnemonic({
|
|
41
|
+
prefix,
|
|
42
|
+
derivationPath,
|
|
43
|
+
}: { prefix: string; derivationPath: string }) {
|
|
44
|
+
return async function secp256k1HdWalletFromMnemonic(mnemonic: string, index = 0) {
|
|
45
|
+
const { Secp256k1HdWallet } = await import("@cosmjs/amino");
|
|
46
|
+
const { stringToPath } = await import("@cosmjs/crypto");
|
|
47
|
+
|
|
48
|
+
return Secp256k1HdWallet.fromMnemonic(mnemonic, {
|
|
49
|
+
hdPaths: [stringToPath(`${derivationPath}/${index}`)],
|
|
50
|
+
prefix,
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function exportSignature(signature: Uint8Array) {
|
|
56
|
+
return base64.encode(signature);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function signMultisigTx(
|
|
60
|
+
wallet: Secp256k1HdWallet,
|
|
61
|
+
tx: string,
|
|
62
|
+
chain: Chain.THORChain | Chain.Maya,
|
|
63
|
+
) {
|
|
64
|
+
const {
|
|
65
|
+
msgs,
|
|
66
|
+
accountNumber,
|
|
67
|
+
sequence,
|
|
68
|
+
chainId,
|
|
69
|
+
fee,
|
|
70
|
+
memo,
|
|
71
|
+
}: {
|
|
72
|
+
msgs: ReturnType<typeof buildAminoMsg>[];
|
|
73
|
+
accountNumber: number;
|
|
74
|
+
sequence: number;
|
|
75
|
+
chainId: ChainId;
|
|
76
|
+
fee: ReturnType<typeof getDefaultChainFee>;
|
|
77
|
+
memo: string;
|
|
78
|
+
} = JSON.parse(tx);
|
|
79
|
+
|
|
80
|
+
const address = (await wallet.getAccounts())?.[0]?.address || "";
|
|
81
|
+
const aminoTypes = await createDefaultAminoTypes(chain);
|
|
82
|
+
const registry = await createDefaultRegistry();
|
|
83
|
+
const signingClient = await createOfflineStargateClient(wallet, { registry, aminoTypes });
|
|
84
|
+
const msgForSigning = [];
|
|
85
|
+
|
|
86
|
+
for (const msg of msgs) {
|
|
87
|
+
const signMsg = await convertToSignable(msg, chain);
|
|
88
|
+
msgForSigning.push(signMsg);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const {
|
|
92
|
+
signatures: [signature],
|
|
93
|
+
} = await signingClient.sign(address, msgForSigning, fee, memo, {
|
|
94
|
+
accountNumber,
|
|
95
|
+
sequence,
|
|
96
|
+
chainId,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const bodyBytes = await buildEncodedTxBody({
|
|
100
|
+
chain,
|
|
101
|
+
memo,
|
|
102
|
+
msgs: msgs.map(parseAminoMessageForDirectSigning),
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
return { signature: exportSignature(signature as Uint8Array), bodyBytes };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function broadcastMultisigTx({ prefix, rpcUrl }: { prefix: string; rpcUrl: string }) {
|
|
109
|
+
return async function broadcastMultisigTx(
|
|
110
|
+
tx: string,
|
|
111
|
+
signers: Signer[],
|
|
112
|
+
membersPubKeys: string[],
|
|
113
|
+
threshold: number,
|
|
114
|
+
bodyBytes: Uint8Array,
|
|
115
|
+
) {
|
|
116
|
+
const { encodeSecp256k1Pubkey, pubkeyToAddress } = await import("@cosmjs/amino");
|
|
117
|
+
const { makeMultisignedTxBytes } = await import("@cosmjs/stargate");
|
|
118
|
+
|
|
119
|
+
const { sequence, fee } = JSON.parse(tx);
|
|
120
|
+
const multisigPubkey = await createMultisig(membersPubKeys, threshold);
|
|
121
|
+
|
|
122
|
+
const addressesAndSignatures: [string, Uint8Array][] = signers.map((signer) => [
|
|
123
|
+
pubkeyToAddress(encodeSecp256k1Pubkey(base64.decode(signer.pubKey)), prefix),
|
|
124
|
+
base64.decode(signer.signature),
|
|
125
|
+
]);
|
|
126
|
+
|
|
127
|
+
const broadcaster = await createStargateClient(rpcUrl);
|
|
128
|
+
|
|
129
|
+
const { transactionHash } = await broadcaster.broadcastTx(
|
|
130
|
+
makeMultisignedTxBytes(
|
|
131
|
+
multisigPubkey,
|
|
132
|
+
sequence,
|
|
133
|
+
fee,
|
|
134
|
+
bodyBytes,
|
|
135
|
+
new Map<string, Uint8Array>(addressesAndSignatures),
|
|
136
|
+
),
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
return transactionHash;
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function createMultisig(pubKeys: string[], threshold: number, noSortPubKeys = true) {
|
|
144
|
+
const { createMultisigThresholdPubkey, encodeSecp256k1Pubkey } = await import("@cosmjs/amino");
|
|
145
|
+
return createMultisigThresholdPubkey(
|
|
146
|
+
pubKeys.map((pubKey) => encodeSecp256k1Pubkey(base64.decode(pubKey))),
|
|
147
|
+
threshold,
|
|
148
|
+
noSortPubKeys,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function importSignature(signature: string) {
|
|
153
|
+
return base64.decode(signature);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async function signWithPrivateKey({
|
|
157
|
+
privateKey,
|
|
158
|
+
message,
|
|
159
|
+
}: { privateKey: Uint8Array; message: string }) {
|
|
160
|
+
const { Secp256k1 } = await import("@cosmjs/crypto");
|
|
161
|
+
|
|
162
|
+
const signature = await Secp256k1.createSignature(base64.decode(message), privateKey);
|
|
163
|
+
return base64.encode(Buffer.concat([signature.r(32), signature.s(32)]));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function verifySignature(getAccount: (address: string) => Promise<Account | null>) {
|
|
167
|
+
return async function verifySignature({
|
|
168
|
+
signature,
|
|
169
|
+
message,
|
|
170
|
+
address,
|
|
171
|
+
}: {
|
|
172
|
+
signature: string;
|
|
173
|
+
message: string;
|
|
174
|
+
address: string;
|
|
175
|
+
}) {
|
|
176
|
+
const account = await getAccount(address);
|
|
177
|
+
if (!account?.pubkey) throw new SwapKitError("toolbox_cosmos_verify_signature_no_pubkey");
|
|
178
|
+
const { Secp256k1Signature, Secp256k1 } = await import("@cosmjs/crypto");
|
|
179
|
+
|
|
180
|
+
const secpSignature = Secp256k1Signature.fromFixedLength(base64.decode(signature));
|
|
181
|
+
return Secp256k1.verifySignature(secpSignature, base64.decode(message), account.pubkey.value);
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function BaseThorchainToolbox(chain: Chain.THORChain | Chain.Maya) {
|
|
186
|
+
const nodeUrl = SKConfig.get("nodeUrls")[chain];
|
|
187
|
+
const rpcUrl = SKConfig.get("rpcUrls")[chain];
|
|
188
|
+
const { isStagenet } = SKConfig.get("envs");
|
|
189
|
+
|
|
190
|
+
const isThorchain = chain === Chain.THORChain;
|
|
191
|
+
const chainPrefix = `${isStagenet ? "s" : ""}${CosmosChainPrefixes[chain]}`;
|
|
192
|
+
const derivationPath = DerivationPath[chain];
|
|
193
|
+
|
|
194
|
+
const cosmosToolbox = BaseCosmosToolbox({ chain, derivationPath, prefix: chainPrefix });
|
|
195
|
+
const defaultFee = getDefaultChainFee(chain);
|
|
196
|
+
|
|
197
|
+
function loadAddressBalances(address: string) {
|
|
198
|
+
try {
|
|
199
|
+
return cosmosToolbox.getBalance(address);
|
|
200
|
+
} catch (error) {
|
|
201
|
+
return Promise.reject(error);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async function getFees() {
|
|
206
|
+
let fee: SwapKitNumber;
|
|
207
|
+
|
|
208
|
+
const constantsUrl = `${nodeUrl}/${isThorchain ? "thorchain" : "mayachain"}/constants`;
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
const {
|
|
212
|
+
int_64_values: { NativeTransactionFee: nativeFee },
|
|
213
|
+
} = await RequestClient.get<ThorchainConstantsResponse>(constantsUrl);
|
|
214
|
+
|
|
215
|
+
if (!nativeFee || Number.isNaN(nativeFee) || nativeFee < 0) {
|
|
216
|
+
throw new Error(`Invalid nativeFee: ${nativeFee.toString()}`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
fee = new SwapKitNumber(nativeFee);
|
|
220
|
+
} catch {
|
|
221
|
+
fee = new SwapKitNumber({ value: isThorchain ? 0.02 : 1, decimal: BaseDecimal[chain] });
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return { [FeeOption.Average]: fee, [FeeOption.Fast]: fee, [FeeOption.Fastest]: fee };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async function transfer({
|
|
228
|
+
from,
|
|
229
|
+
recipient,
|
|
230
|
+
assetValue,
|
|
231
|
+
memo = "",
|
|
232
|
+
signer,
|
|
233
|
+
}: Omit<TransferParams, "recipient"> & { recipient?: string }) {
|
|
234
|
+
const { TxRaw } = await import("cosmjs-types/cosmos/tx/v1beta1/tx");
|
|
235
|
+
if (!signer) throw new Error("Signer not defined");
|
|
236
|
+
|
|
237
|
+
const isAminoSigner = "signAmino" in signer;
|
|
238
|
+
const registry = await createDefaultRegistry();
|
|
239
|
+
const aminoTypes = await createDefaultAminoTypes(chain);
|
|
240
|
+
const signingClient = await createSigningStargateClient(rpcUrl, signer, {
|
|
241
|
+
registry,
|
|
242
|
+
aminoTypes,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
const aminoMessage = buildAminoMsg({ assetValue, from, recipient, memo, chain });
|
|
246
|
+
|
|
247
|
+
if (isAminoSigner) {
|
|
248
|
+
const msgSign = await convertToSignable(aminoMessage, chain);
|
|
249
|
+
|
|
250
|
+
const { signatures, authInfoBytes } = await signingClient.sign(
|
|
251
|
+
from,
|
|
252
|
+
[msgSign],
|
|
253
|
+
defaultFee,
|
|
254
|
+
memo,
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
const tx = TxRaw.encode({
|
|
258
|
+
signatures,
|
|
259
|
+
authInfoBytes,
|
|
260
|
+
bodyBytes: await buildEncodedTxBody({
|
|
261
|
+
chain,
|
|
262
|
+
msgs: [aminoMessage].map(parseAminoMessageForDirectSigning),
|
|
263
|
+
memo,
|
|
264
|
+
}),
|
|
265
|
+
}).finish();
|
|
266
|
+
|
|
267
|
+
const txResponse = await signingClient.broadcastTx(tx);
|
|
268
|
+
|
|
269
|
+
return txResponse.transactionHash;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const preparedMessage = parseAminoMessageForDirectSigning(aminoMessage);
|
|
273
|
+
const msgSign = await convertToSignable(preparedMessage, chain);
|
|
274
|
+
const txResponse = await signingClient.signAndBroadcast(from, [msgSign], defaultFee, memo);
|
|
275
|
+
|
|
276
|
+
return txResponse.transactionHash;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
...cosmosToolbox,
|
|
281
|
+
deposit: (params: DepositParam & { from: string }) => transfer(params),
|
|
282
|
+
pubkeyToAddress: async (pubkey: Pubkey) => {
|
|
283
|
+
const { pubkeyToAddress } = await import("@cosmjs/amino");
|
|
284
|
+
return pubkeyToAddress(pubkey, chainPrefix);
|
|
285
|
+
},
|
|
286
|
+
transfer,
|
|
287
|
+
getFees,
|
|
288
|
+
buildAminoMsg,
|
|
289
|
+
convertToSignable,
|
|
290
|
+
buildDepositTx: buildDepositTx(rpcUrl),
|
|
291
|
+
buildTransferTx: buildTransferTx(rpcUrl),
|
|
292
|
+
buildEncodedTxBody,
|
|
293
|
+
parseAminoMessageForDirectSigning,
|
|
294
|
+
createDefaultAminoTypes: () => createDefaultAminoTypes(chain),
|
|
295
|
+
createDefaultRegistry,
|
|
296
|
+
secp256k1HdWalletFromMnemonic: secp256k1HdWalletFromMnemonic({
|
|
297
|
+
derivationPath,
|
|
298
|
+
prefix: chainPrefix,
|
|
299
|
+
}),
|
|
300
|
+
signMultisigTx: (wallet: Secp256k1HdWallet, tx: string) => signMultisigTx(wallet, tx, chain),
|
|
301
|
+
broadcastMultisigTx: broadcastMultisigTx({ prefix: chainPrefix, rpcUrl }),
|
|
302
|
+
createMultisig,
|
|
303
|
+
importSignature,
|
|
304
|
+
loadAddressBalances,
|
|
305
|
+
signWithPrivateKey,
|
|
306
|
+
verifySignature: verifySignature(cosmosToolbox.getAccount),
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export function ThorchainToolbox() {
|
|
311
|
+
return BaseThorchainToolbox(Chain.THORChain);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export function MayaToolbox() {
|
|
315
|
+
return BaseThorchainToolbox(Chain.Maya);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export type ThorchainWallet = Omit<ReturnType<typeof BaseThorchainToolbox>, "signMessage">;
|
|
319
|
+
export type ThorchainWallets = {
|
|
320
|
+
[chain in Chain.THORChain | Chain.Maya]: ThorchainWallet;
|
|
321
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { OfflineAminoSigner, StdFee } from "@cosmjs/amino";
|
|
2
|
+
import type { OfflineDirectSigner } from "@cosmjs/proto-signing";
|
|
3
|
+
import type { AssetValue, ChainId, FeeOption } from "@swapkit/helpers";
|
|
4
|
+
|
|
5
|
+
export type CosmosSDKClientParams = {
|
|
6
|
+
server: string;
|
|
7
|
+
chainId: ChainId;
|
|
8
|
+
prefix?: string;
|
|
9
|
+
stagenet?: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type TransferParams = {
|
|
13
|
+
assetValue: AssetValue;
|
|
14
|
+
fee?: StdFee | number;
|
|
15
|
+
feeOptionKey?: FeeOption;
|
|
16
|
+
from: string;
|
|
17
|
+
memo?: string;
|
|
18
|
+
privkey?: Uint8Array;
|
|
19
|
+
recipient: string;
|
|
20
|
+
signer?: OfflineDirectSigner | OfflineAminoSigner;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type ToolboxParams = {
|
|
24
|
+
rpcUrl?: string;
|
|
25
|
+
prefix?: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type Signer = {
|
|
29
|
+
pubKey: string;
|
|
30
|
+
signature: string;
|
|
31
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import type { OfflineSigner } from "@cosmjs/proto-signing";
|
|
2
|
+
import type { SigningStargateClientOptions } from "@cosmjs/stargate";
|
|
3
|
+
import {
|
|
4
|
+
AssetValue,
|
|
5
|
+
Chain,
|
|
6
|
+
ChainId,
|
|
7
|
+
type CosmosChain,
|
|
8
|
+
SKConfig,
|
|
9
|
+
defaultRequestHeaders,
|
|
10
|
+
getGasAsset,
|
|
11
|
+
} from "@swapkit/helpers";
|
|
12
|
+
|
|
13
|
+
import type { CosmosNativeTransferTxParams } from "./thorchainUtils";
|
|
14
|
+
|
|
15
|
+
export const USK_KUJIRA_FACTORY_DENOM =
|
|
16
|
+
"FACTORY/KUJIRA1QK00H5ATUTPSV900X202PXX42NPJR9THG58DNQPA72F2P7M2LUASE444A7/UUSK";
|
|
17
|
+
|
|
18
|
+
export const YUM_KUJIRA_FACTORY_DENOM =
|
|
19
|
+
"FACTORY/KUJIRA1YGFXN0ER40KLCNCK8THLTUPRDXLCK6WVNPKF2K/UYUM";
|
|
20
|
+
|
|
21
|
+
export const DEFAULT_COSMOS_FEE_MAINNET = {
|
|
22
|
+
amount: [{ denom: "uatom", amount: "500" }],
|
|
23
|
+
gas: "200000",
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const DEFAULT_KUJI_FEE_MAINNET = {
|
|
27
|
+
amount: [{ denom: "ukuji", amount: "1000" }],
|
|
28
|
+
gas: "200000",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export function getDefaultChainFee(chain: CosmosChain) {
|
|
32
|
+
switch (chain) {
|
|
33
|
+
case Chain.Maya:
|
|
34
|
+
return { amount: [], gas: "10000000000" };
|
|
35
|
+
case Chain.THORChain:
|
|
36
|
+
return { amount: [], gas: "500000000" };
|
|
37
|
+
case Chain.Kujira:
|
|
38
|
+
return DEFAULT_KUJI_FEE_MAINNET;
|
|
39
|
+
default:
|
|
40
|
+
return DEFAULT_COSMOS_FEE_MAINNET;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const getMsgSendDenom = (symbol: string, isThorchain = false) => {
|
|
45
|
+
if (isThorchain) {
|
|
46
|
+
return symbol.toLowerCase();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
switch (symbol) {
|
|
50
|
+
case "uUSK":
|
|
51
|
+
case "USK":
|
|
52
|
+
return USK_KUJIRA_FACTORY_DENOM;
|
|
53
|
+
case "uYUM":
|
|
54
|
+
case "YUM":
|
|
55
|
+
return YUM_KUJIRA_FACTORY_DENOM;
|
|
56
|
+
case "uKUJI":
|
|
57
|
+
case "KUJI":
|
|
58
|
+
return "ukuji";
|
|
59
|
+
case "ATOM":
|
|
60
|
+
case "uATOM":
|
|
61
|
+
return "uatom";
|
|
62
|
+
default:
|
|
63
|
+
return symbol;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const getDenomWithChain = ({ symbol, chain }: AssetValue) => {
|
|
68
|
+
if (chain === Chain.Maya) {
|
|
69
|
+
return (symbol.toUpperCase() !== "CACAO" ? symbol : `${Chain.Maya}.${symbol}`).toUpperCase();
|
|
70
|
+
}
|
|
71
|
+
if (chain === Chain.THORChain) {
|
|
72
|
+
return (
|
|
73
|
+
symbol.toUpperCase() !== "RUNE" ? symbol : `${Chain.THORChain}.${symbol}`
|
|
74
|
+
).toUpperCase();
|
|
75
|
+
}
|
|
76
|
+
return getMsgSendDenom(symbol, false);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// TODO: figure out some better way to initialize from base value
|
|
80
|
+
export const getAssetFromDenom = (denom: string, amount: string) => {
|
|
81
|
+
switch (denom) {
|
|
82
|
+
case "rune":
|
|
83
|
+
return AssetValue.from({
|
|
84
|
+
chain: Chain.THORChain,
|
|
85
|
+
value: Number.parseInt(amount) / 1e8,
|
|
86
|
+
});
|
|
87
|
+
case "uatom":
|
|
88
|
+
case "atom":
|
|
89
|
+
return AssetValue.from({
|
|
90
|
+
chain: Chain.Cosmos,
|
|
91
|
+
value: Number.parseInt(amount) / 1e6,
|
|
92
|
+
});
|
|
93
|
+
case "cacao":
|
|
94
|
+
return AssetValue.from({
|
|
95
|
+
chain: Chain.Maya,
|
|
96
|
+
value: Number.parseInt(amount) / 1e10,
|
|
97
|
+
});
|
|
98
|
+
case "maya":
|
|
99
|
+
return AssetValue.from({
|
|
100
|
+
asset: `${Chain.Maya}.${Chain.Maya}`,
|
|
101
|
+
value: Number.parseInt(amount) / 1e4,
|
|
102
|
+
});
|
|
103
|
+
case "ukuji":
|
|
104
|
+
case "kuji":
|
|
105
|
+
return AssetValue.from({
|
|
106
|
+
chain: Chain.Kujira,
|
|
107
|
+
value: Number.parseInt(amount) / 1e6,
|
|
108
|
+
});
|
|
109
|
+
case USK_KUJIRA_FACTORY_DENOM:
|
|
110
|
+
// USK on Kujira
|
|
111
|
+
return AssetValue.from({
|
|
112
|
+
asset: `${Chain.Kujira}.USK`,
|
|
113
|
+
value: Number.parseInt(amount) / 1e6,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
default:
|
|
117
|
+
return AssetValue.from({
|
|
118
|
+
asset: denom,
|
|
119
|
+
value: Number.parseInt(amount) / 1e8,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export async function createStargateClient(url: string) {
|
|
125
|
+
const { StargateClient } = await import("@cosmjs/stargate");
|
|
126
|
+
|
|
127
|
+
return StargateClient.connect({ url, headers: defaultRequestHeaders });
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export async function createSigningStargateClient(
|
|
131
|
+
url: string,
|
|
132
|
+
signer: any,
|
|
133
|
+
optionsOrBaseGas: string | SigningStargateClientOptions = {},
|
|
134
|
+
) {
|
|
135
|
+
const { SigningStargateClient, GasPrice } = await import("@cosmjs/stargate");
|
|
136
|
+
const gasPrice = typeof optionsOrBaseGas === "string" ? optionsOrBaseGas : "0.0003uatom";
|
|
137
|
+
const options = typeof optionsOrBaseGas === "string" ? {} : optionsOrBaseGas;
|
|
138
|
+
|
|
139
|
+
return SigningStargateClient.connectWithSigner({ url, headers: defaultRequestHeaders }, signer, {
|
|
140
|
+
gasPrice: GasPrice.fromString(gasPrice),
|
|
141
|
+
...options,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export async function createOfflineStargateClient(
|
|
146
|
+
wallet: OfflineSigner,
|
|
147
|
+
registry?: SigningStargateClientOptions,
|
|
148
|
+
) {
|
|
149
|
+
const { SigningStargateClient } = await import("@cosmjs/stargate");
|
|
150
|
+
|
|
151
|
+
return SigningStargateClient.offline(wallet, registry);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export const getRPC = (chainId: ChainId) => {
|
|
155
|
+
const { isStagenet } = SKConfig.get("envs");
|
|
156
|
+
const rpcUrls = SKConfig.get("rpcUrls");
|
|
157
|
+
|
|
158
|
+
switch (chainId) {
|
|
159
|
+
case ChainId.Kujira:
|
|
160
|
+
return rpcUrls.KUJI;
|
|
161
|
+
|
|
162
|
+
case ChainId.THORChain:
|
|
163
|
+
case "thorchain-mainnet-v1" as ChainId:
|
|
164
|
+
return isStagenet ? rpcUrls.THOR_STAGENET : rpcUrls.THOR;
|
|
165
|
+
case ChainId.Maya:
|
|
166
|
+
return isStagenet ? rpcUrls.MAYA_STAGENET : rpcUrls.MAYA;
|
|
167
|
+
|
|
168
|
+
default:
|
|
169
|
+
return rpcUrls.GAIA;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const getTransferMsgTypeByChain = (chain: CosmosChain) => {
|
|
174
|
+
switch (chain) {
|
|
175
|
+
case Chain.Maya:
|
|
176
|
+
case Chain.THORChain:
|
|
177
|
+
return "/types.MsgSend";
|
|
178
|
+
case Chain.Cosmos:
|
|
179
|
+
case Chain.Kujira:
|
|
180
|
+
return "/cosmos.bank.v1beta1.MsgSend";
|
|
181
|
+
default:
|
|
182
|
+
throw new Error("Unsupported chain");
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Used to build tx for Cosmos and Kujira
|
|
188
|
+
*/
|
|
189
|
+
export const buildNativeTransferTx = async ({
|
|
190
|
+
fromAddress,
|
|
191
|
+
toAddress,
|
|
192
|
+
assetValue,
|
|
193
|
+
memo = "",
|
|
194
|
+
fee,
|
|
195
|
+
}: CosmosNativeTransferTxParams) => {
|
|
196
|
+
const { chain, chainId } = assetValue;
|
|
197
|
+
|
|
198
|
+
const url = getRPC(chainId);
|
|
199
|
+
const client = await createStargateClient(url);
|
|
200
|
+
const accountOnChain = await client.getAccount(fromAddress);
|
|
201
|
+
|
|
202
|
+
if (!accountOnChain) {
|
|
203
|
+
throw new Error("Account does not exist");
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const feeAsset = getMsgSendDenom(getGasAsset({ chain }).symbol);
|
|
207
|
+
const defaultFee = getDefaultChainFee(chain as CosmosChain);
|
|
208
|
+
|
|
209
|
+
const txFee =
|
|
210
|
+
feeAsset && fee
|
|
211
|
+
? { amount: [{ denom: feeAsset, amount: fee }], gas: defaultFee.gas }
|
|
212
|
+
: defaultFee;
|
|
213
|
+
|
|
214
|
+
const msgSend = {
|
|
215
|
+
fromAddress,
|
|
216
|
+
toAddress,
|
|
217
|
+
amount: [
|
|
218
|
+
{ amount: assetValue.getBaseValue("string"), denom: getMsgSendDenom(assetValue.symbol) },
|
|
219
|
+
],
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
accountNumber: accountOnChain.accountNumber,
|
|
224
|
+
chainId,
|
|
225
|
+
fee: txFee,
|
|
226
|
+
memo,
|
|
227
|
+
sequence: accountOnChain.sequence,
|
|
228
|
+
msgs: [{ typeUrl: getTransferMsgTypeByChain(chain as CosmosChain), value: msgSend }],
|
|
229
|
+
};
|
|
230
|
+
};
|