@swapkit/toolboxes 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 (83) hide show
  1. package/dist/chunk-fazw0jvt.js +3 -0
  2. package/dist/chunk-fazw0jvt.js.map +9 -0
  3. package/dist/chunk-tvrdndbw.js +4 -0
  4. package/dist/chunk-tvrdndbw.js.map +9 -0
  5. package/dist/cosmos/index.cjs +3 -0
  6. package/dist/cosmos/index.cjs.map +19 -0
  7. package/dist/cosmos/index.js +3 -0
  8. package/dist/cosmos/index.js.map +19 -0
  9. package/dist/evm/index.cjs +3 -0
  10. package/dist/evm/index.cjs.map +18 -0
  11. package/dist/evm/index.js +3 -0
  12. package/dist/evm/index.js.map +18 -0
  13. package/dist/index.cjs +3 -0
  14. package/dist/index.cjs.map +9 -0
  15. package/dist/index.js +3 -0
  16. package/dist/index.js.map +9 -0
  17. package/dist/radix/index.cjs +3 -0
  18. package/dist/radix/index.cjs.map +10 -0
  19. package/dist/radix/index.js +3 -0
  20. package/dist/radix/index.js.map +10 -0
  21. package/dist/solana/index.cjs +3 -0
  22. package/dist/solana/index.cjs.map +10 -0
  23. package/dist/solana/index.js +3 -0
  24. package/dist/solana/index.js.map +10 -0
  25. package/dist/substrate/index.cjs +3 -0
  26. package/dist/substrate/index.cjs.map +12 -0
  27. package/dist/substrate/index.js +3 -0
  28. package/dist/substrate/index.js.map +12 -0
  29. package/dist/utxo/index.cjs +3 -0
  30. package/dist/utxo/index.cjs.map +17 -0
  31. package/dist/utxo/index.js +3 -0
  32. package/dist/utxo/index.js.map +17 -0
  33. package/package.json +102 -0
  34. package/src/cosmos/index.ts +8 -0
  35. package/src/cosmos/thorchainUtils/addressFormat.ts +23 -0
  36. package/src/cosmos/thorchainUtils/index.ts +4 -0
  37. package/src/cosmos/thorchainUtils/messages.ts +244 -0
  38. package/src/cosmos/thorchainUtils/registry.ts +47 -0
  39. package/src/cosmos/thorchainUtils/types/client-types.ts +79 -0
  40. package/src/cosmos/thorchainUtils/types/index.ts +1 -0
  41. package/src/cosmos/thorchainUtils/types/proto/MsgCompiled.js +2806 -0
  42. package/src/cosmos/thorchainUtils/types/proto/MsgCompiled.ts +2802 -0
  43. package/src/cosmos/thorchainUtils/util.ts +46 -0
  44. package/src/cosmos/toolbox/BaseCosmosToolbox.ts +257 -0
  45. package/src/cosmos/toolbox/gaia.ts +39 -0
  46. package/src/cosmos/toolbox/getToolboxByChain.ts +29 -0
  47. package/src/cosmos/toolbox/kujira.ts +61 -0
  48. package/src/cosmos/toolbox/thorchain.ts +305 -0
  49. package/src/cosmos/types.ts +42 -0
  50. package/src/cosmos/util.ts +230 -0
  51. package/src/evm/__tests__/ethereum.test.ts +147 -0
  52. package/src/evm/api.ts +157 -0
  53. package/src/evm/contracts/eth/multicall.ts +165 -0
  54. package/src/evm/contracts/op/gasOracle.ts +151 -0
  55. package/src/evm/helpers.ts +213 -0
  56. package/src/evm/index.ts +15 -0
  57. package/src/evm/toolbox/baseEVMToolbox.ts +670 -0
  58. package/src/evm/toolbox/evm.ts +89 -0
  59. package/src/evm/toolbox/getToolboxByChain.ts +37 -0
  60. package/src/evm/toolbox/op.ts +152 -0
  61. package/src/evm/types.ts +110 -0
  62. package/src/index.ts +0 -0
  63. package/src/radix/index.ts +151 -0
  64. package/src/radix/toolbox.ts +693 -0
  65. package/src/solana/index.ts +49 -0
  66. package/src/solana/toolbox.ts +271 -0
  67. package/src/substrate/index.ts +3 -0
  68. package/src/substrate/toolbox/baseSubstrateToolbox.ts +288 -0
  69. package/src/substrate/toolbox/index.ts +40 -0
  70. package/src/substrate/types/index.ts +2 -0
  71. package/src/substrate/types/network.ts +42 -0
  72. package/src/substrate/types/wallet.ts +78 -0
  73. package/src/utxo/helpers/api.ts +431 -0
  74. package/src/utxo/helpers/bchaddrjs.ts +177 -0
  75. package/src/utxo/helpers/coinselect.ts +96 -0
  76. package/src/utxo/helpers/index.ts +5 -0
  77. package/src/utxo/helpers/txSize.ts +103 -0
  78. package/src/utxo/helpers/utils.ts +48 -0
  79. package/src/utxo/index.ts +7 -0
  80. package/src/utxo/toolbox/bitcoinCash.ts +268 -0
  81. package/src/utxo/toolbox/index.ts +41 -0
  82. package/src/utxo/toolbox/utxo.ts +372 -0
  83. package/src/utxo/types.ts +51 -0
@@ -0,0 +1,96 @@
1
+ import { Chain, type UTXOChain } from "@swapkit/helpers";
2
+
3
+ import {
4
+ TX_OVERHEAD,
5
+ UTXOScriptType,
6
+ calculateTxSize,
7
+ getInputSize,
8
+ getOutputSize,
9
+ getScriptTypeForAddress,
10
+ } from "../helpers";
11
+ import type { TargetOutput, UTXOCalculateTxSizeParams, UTXOType } from "../types";
12
+
13
+ export const getDustThreshold = (chain: UTXOChain) => {
14
+ switch (chain) {
15
+ case Chain.Bitcoin:
16
+ case Chain.BitcoinCash:
17
+ return 550;
18
+ case Chain.Dash:
19
+ case Chain.Litecoin:
20
+ return 5500;
21
+ case Chain.Dogecoin:
22
+ return 100000;
23
+ default:
24
+ throw new Error("Invalid Chain");
25
+ }
26
+ };
27
+
28
+ export const accumulative = ({
29
+ inputs,
30
+ outputs,
31
+ feeRate: initialFeeRate = 1,
32
+ chain = Chain.Bitcoin,
33
+ }: UTXOCalculateTxSizeParams & { outputs: TargetOutput[]; chain: UTXOChain }) => {
34
+ const feeRate = Math.ceil(initialFeeRate);
35
+
36
+ const newTxType =
37
+ inputs[0] && "address" in inputs[0] && inputs[0].address
38
+ ? getScriptTypeForAddress(inputs[0].address)
39
+ : UTXOScriptType.P2PKH;
40
+ // skip input if adding it would cost more than input is worth
41
+ const filteredInputs = inputs.filter((input) => getInputSize(input) * feeRate <= input.value);
42
+
43
+ const txSizeWithoutInputs =
44
+ TX_OVERHEAD + outputs.reduce((total, output) => total + getOutputSize(output, newTxType), 0);
45
+
46
+ const amountToSend = outputs.reduce((total, output) => total + output.value, 0);
47
+
48
+ let fees = txSizeWithoutInputs * feeRate;
49
+ let inputsValue = 0;
50
+ const inputsToUse: typeof inputs = [];
51
+
52
+ for (const input of filteredInputs) {
53
+ const inputSize = getInputSize(input);
54
+ const inputFee = feeRate * inputSize;
55
+
56
+ fees += inputFee;
57
+ inputsValue += input.value;
58
+
59
+ inputsToUse.push(input);
60
+
61
+ const totalCost = fees + amountToSend;
62
+
63
+ // we need more inputs
64
+ if (inputsValue < totalCost) continue;
65
+
66
+ const remainder = inputsValue - totalCost;
67
+
68
+ const feeForExtraOutput = feeRate * getOutputSize({ address: "", value: 0 }, newTxType);
69
+
70
+ // potential change address
71
+ if (remainder > feeForExtraOutput) {
72
+ const feeAfterExtraOutput = feeForExtraOutput + fees;
73
+ const remainderAfterExtraOutput = inputsValue - (amountToSend + feeAfterExtraOutput);
74
+
75
+ // is it worth a change output aka can we send it in the future?
76
+ if (
77
+ remainderAfterExtraOutput >
78
+ Math.max(getInputSize({} as UTXOType) * feeRate, getDustThreshold(chain))
79
+ ) {
80
+ return {
81
+ inputs: inputsToUse,
82
+ outputs: outputs.concat({ value: remainderAfterExtraOutput, address: "" }),
83
+ fee: feeAfterExtraOutput,
84
+ };
85
+ }
86
+ }
87
+ return {
88
+ inputs: inputsToUse,
89
+ outputs,
90
+ fee: fees,
91
+ };
92
+ }
93
+
94
+ // We don't have enough inputs, let's calculate transaction fee accrude to the last input
95
+ return { fee: feeRate * calculateTxSize({ inputs, outputs, feeRate }) };
96
+ };
@@ -0,0 +1,5 @@
1
+ export * from "./api";
2
+ export * from "./bchaddrjs";
3
+ export * from "./coinselect";
4
+ export * from "./txSize";
5
+ export * from "./utils";
@@ -0,0 +1,103 @@
1
+ import type {
2
+ TargetOutput,
3
+ UTXOCalculateTxSizeParams,
4
+ UTXOInputWithScriptType,
5
+ UTXOType,
6
+ } from "../types";
7
+
8
+ /**
9
+ * Minimum transaction fee
10
+ * 1000 satoshi/kB (similar to current `minrelaytxfee`)
11
+ * @see https://github.com/bitcoin/bitcoin/blob/db88db47278d2e7208c50d16ab10cb355067d071/src/validation.h#L56
12
+ */
13
+ export const MIN_TX_FEE = 1000;
14
+ export const TX_OVERHEAD = 4 + 1 + 1 + 4; //10
15
+ export const OP_RETURN_OVERHEAD = 1 + 8 + 1; //10
16
+ const TX_INPUT_BASE = 32 + 4 + 1 + 4; // 41
17
+ const TX_INPUT_PUBKEYHASH = 107;
18
+
19
+ export async function compileMemo(memo: string) {
20
+ const { script, opcodes } = await import("bitcoinjs-lib");
21
+ const data = Buffer.from(memo, "utf8"); // converts MEMO to buffer
22
+ return script.compile([opcodes.OP_RETURN as number, data]); // Compile OP_RETURN script
23
+ }
24
+
25
+ export enum UTXOScriptType {
26
+ P2PKH = "P2PKH", // legacy
27
+ // P2SH = 'P2SH', // multisig
28
+ P2WPKH = "P2WPKH", // bech32 - native segwit
29
+ // P2TR = "P2TR", // taproot
30
+ }
31
+
32
+ export const InputSizes: Record<UTXOScriptType, number> = {
33
+ [UTXOScriptType.P2PKH]: 148,
34
+ // [UTXOScriptType.P2SH]: 91,
35
+ [UTXOScriptType.P2WPKH]: 68,
36
+ };
37
+
38
+ export const OutputSizes: Record<UTXOScriptType, number> = {
39
+ [UTXOScriptType.P2PKH]: 34,
40
+ // [UTXOScriptType.P2SH]: 91,
41
+ [UTXOScriptType.P2WPKH]: 31,
42
+ };
43
+
44
+ export const getScriptTypeForAddress = (address: string) => {
45
+ if (address.startsWith("bc1") || address.startsWith("ltc1")) {
46
+ return UTXOScriptType.P2WPKH;
47
+ }
48
+ // if (address.startsWith('3') || address.startsWith('M')) {
49
+ // return UTXOScriptType.P2SH;
50
+ // }
51
+ if (
52
+ address.startsWith("1") ||
53
+ address.startsWith("3") ||
54
+ address.startsWith("L") ||
55
+ address.startsWith("M") ||
56
+ address.startsWith("X") ||
57
+ address.startsWith("D") ||
58
+ address.startsWith("bitcoincash:q") ||
59
+ address.startsWith("q")
60
+ ) {
61
+ return UTXOScriptType.P2PKH;
62
+ }
63
+ throw new Error("Invalid address");
64
+ };
65
+
66
+ export const calculateTxSize = ({ inputs, outputs, feeRate }: UTXOCalculateTxSizeParams) => {
67
+ const newTxType =
68
+ inputs[0] && "address" in inputs[0] && inputs[0].address
69
+ ? getScriptTypeForAddress(inputs[0].address)
70
+ : UTXOScriptType.P2PKH;
71
+ const inputSize = inputs
72
+ .filter(
73
+ (utxo) =>
74
+ utxo.value >=
75
+ InputSizes["type" in utxo ? utxo.type : UTXOScriptType.P2PKH] * Math.ceil(feeRate),
76
+ )
77
+ .reduce((total, utxo) => total + getInputSize(utxo), 0);
78
+
79
+ const outputSize =
80
+ outputs?.reduce((total, output) => total + getOutputSize(output), 0) || OutputSizes[newTxType];
81
+
82
+ return TX_OVERHEAD + inputSize + outputSize;
83
+ };
84
+
85
+ export const getInputSize = (input: UTXOInputWithScriptType | UTXOType) => {
86
+ if ("type" in input) {
87
+ return InputSizes[input.type];
88
+ }
89
+ if ("address" in input && input.address) {
90
+ return InputSizes[getScriptTypeForAddress(input.address as string)];
91
+ }
92
+ return TX_INPUT_BASE + TX_INPUT_PUBKEYHASH;
93
+ };
94
+
95
+ export const getOutputSize = (output: TargetOutput, scriptType?: UTXOScriptType) => {
96
+ if (output?.script) {
97
+ return OP_RETURN_OVERHEAD + output.script.length + (output.script.length >= 74 ? 2 : 1);
98
+ }
99
+ if (scriptType) {
100
+ return OutputSizes[scriptType];
101
+ }
102
+ return OutputSizes[UTXOScriptType.P2PKH];
103
+ };
@@ -0,0 +1,48 @@
1
+ import { Chain, FeeOption } from "@swapkit/helpers";
2
+
3
+ const pid = typeof process !== "undefined" && process.pid ? process.pid.toString(36) : "";
4
+
5
+ export async function getUtxoNetwork() {
6
+ // @ts-ignore TODO: check why wallets doesn't see modules included in toolbox
7
+ const { coininfo } = await import("coininfo");
8
+ const { networks } = await import("bitcoinjs-lib");
9
+
10
+ return function getNetwork(chain: Chain) {
11
+ switch (chain) {
12
+ case Chain.Bitcoin:
13
+ return networks.bitcoin;
14
+ case Chain.BitcoinCash:
15
+ return coininfo.bitcoincash.main.toBitcoinJS();
16
+ case Chain.Dash:
17
+ return coininfo.dash.main.toBitcoinJS();
18
+ case Chain.Litecoin:
19
+ return coininfo.litecoin.main.toBitcoinJS();
20
+
21
+ case Chain.Dogecoin: {
22
+ const bip32 = { private: 0x04358394, public: 0x043587cf };
23
+ const test = coininfo.dogecoin.test;
24
+ test.versions.bip32 = bip32;
25
+ return coininfo.dogecoin.main.toBitcoinJS();
26
+ }
27
+ default:
28
+ throw new Error("Invalid chain");
29
+ }
30
+ };
31
+ }
32
+
33
+ export const standardFeeRates = (rate: number) => ({
34
+ [FeeOption.Average]: rate,
35
+ [FeeOption.Fast]: rate * 1.5,
36
+ [FeeOption.Fastest]: rate * 2.0,
37
+ });
38
+
39
+ let last = 0;
40
+ const now = () => {
41
+ const time = Date.now();
42
+ const lastTime = last || time;
43
+ last = lastTime;
44
+
45
+ return time > last ? time : lastTime + 1;
46
+ };
47
+
48
+ export const uniqid = () => pid + now().toString(36);
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Package
3
+ */
4
+ export * from "./toolbox/index";
5
+ export * from "./toolbox/utxo";
6
+ export * from "./helpers/index";
7
+ export * from "./types";
@@ -0,0 +1,268 @@
1
+ import { Chain, DerivationPath, FeeOption, type UTXOChain } from "@swapkit/helpers";
2
+
3
+ import {
4
+ accumulative,
5
+ Network as bchNetwork,
6
+ compileMemo,
7
+ detectAddressNetwork,
8
+ getUtxoApi,
9
+ getUtxoNetwork,
10
+ isValidAddress,
11
+ toCashAddress,
12
+ toLegacyAddress,
13
+ } from "../helpers";
14
+ import type {
15
+ TargetOutput,
16
+ TransactionType,
17
+ UTXOBuildTxParams,
18
+ UTXOType,
19
+ UTXOWalletTransferParams,
20
+ } from "../types";
21
+ import { createUTXOToolbox } from "./utxo";
22
+
23
+ const chain = Chain.BitcoinCash as UTXOChain;
24
+
25
+ export function stripPrefix(address: string) {
26
+ return address.replace(/(bchtest:|bitcoincash:)/, "");
27
+ }
28
+
29
+ export function validateAddress(address: string) {
30
+ const strippedAddress = stripPrefix(address);
31
+ return (
32
+ isValidAddress(strippedAddress) && detectAddressNetwork(strippedAddress) === bchNetwork.Mainnet
33
+ );
34
+ }
35
+
36
+ export function stripToCashAddress(address: string) {
37
+ return stripPrefix(toCashAddress(address));
38
+ }
39
+
40
+ export async function createBCHToolbox() {
41
+ const { getBalance, getFeeRates, broadcastTx, ...toolbox } = (
42
+ await createUTXOToolbox(Chain.BitcoinCash)
43
+ )();
44
+
45
+ function handleGetBalance(address: string, _scamFilter = true) {
46
+ return getBalance(stripPrefix(toCashAddress(address)));
47
+ }
48
+
49
+ return function createBCHToolbox() {
50
+ return {
51
+ ...toolbox,
52
+ broadcastTx,
53
+ buildBCHTx,
54
+ buildTx,
55
+ createKeysForPath,
56
+ getAddressFromKeys,
57
+ getBalance: handleGetBalance,
58
+ getFeeRates,
59
+ stripPrefix,
60
+ stripToCashAddress,
61
+ validateAddress,
62
+ transfer: transfer({ getFeeRates, broadcastTx }),
63
+ };
64
+ };
65
+ }
66
+
67
+ async function buildBCHTx({ assetValue, recipient, memo, feeRate, sender }: UTXOBuildTxParams) {
68
+ const {
69
+ Transaction,
70
+ TransactionBuilder,
71
+ address: bchAddress,
72
+ // @ts-ignore TODO: check why wallets doesn't see modules included in toolbox
73
+ } = await import("@psf/bitcoincashjs-lib");
74
+ if (!validateAddress(recipient)) throw new Error("Invalid address");
75
+ const utxos = await getUtxoApi(chain).scanUTXOs({
76
+ address: stripToCashAddress(sender),
77
+ fetchTxHex: true,
78
+ });
79
+
80
+ const compiledMemo = memo ? await compileMemo(memo) : null;
81
+
82
+ const targetOutputs: TargetOutput[] = [];
83
+ // output to recipient
84
+ targetOutputs.push({ address: recipient, value: assetValue.getBaseValue("number") });
85
+ const { inputs, outputs } = accumulative({
86
+ inputs: utxos,
87
+ outputs: targetOutputs,
88
+ feeRate,
89
+ chain,
90
+ });
91
+
92
+ // .inputs and .outputs will be undefined if no solution was found
93
+ if (!(inputs && outputs)) throw new Error("Balance insufficient for transaction");
94
+ const getNetwork = await getUtxoNetwork();
95
+ const builder = new TransactionBuilder(getNetwork(chain));
96
+
97
+ await Promise.all(
98
+ inputs.map(async (utxo: UTXOType) => {
99
+ const txHex = await getUtxoApi(chain).getRawTx(utxo.hash);
100
+
101
+ builder.addInput(Transaction.fromBuffer(Buffer.from(txHex, "hex")), utxo.index);
102
+ }),
103
+ );
104
+
105
+ for (const output of outputs) {
106
+ const address =
107
+ "address" in output && output.address ? output.address : toLegacyAddress(sender);
108
+ const getNetwork = await getUtxoNetwork();
109
+ const outputScript = bchAddress.toOutputScript(toLegacyAddress(address), getNetwork(chain));
110
+
111
+ builder.addOutput(outputScript, output.value);
112
+ }
113
+
114
+ // add output for memo
115
+ if (compiledMemo) {
116
+ builder.addOutput(compiledMemo, 0); // Add OP_RETURN {script, value}
117
+ }
118
+
119
+ return { builder, utxos: inputs };
120
+ }
121
+
122
+ function transfer({
123
+ broadcastTx,
124
+ getFeeRates,
125
+ }: {
126
+ broadcastTx: (txHash: string) => Promise<string>;
127
+ getFeeRates: () => Promise<Record<FeeOption, number>>;
128
+ }) {
129
+ return async function transfer({
130
+ signTransaction,
131
+ from,
132
+ recipient,
133
+ assetValue,
134
+ ...rest
135
+ }: UTXOWalletTransferParams<
136
+ { builder: TransactionBuilderType; utxos: UTXOType[] },
137
+ TransactionType
138
+ >) {
139
+ if (!from) throw new Error("From address must be provided");
140
+ if (!recipient) throw new Error("Recipient address must be provided");
141
+ if (!signTransaction) throw new Error("signTransaction must be provided");
142
+
143
+ const feeRate = rest.feeRate || (await getFeeRates())[FeeOption.Fast];
144
+
145
+ // try out if psbt tx is faster/better/nicer
146
+ const { builder, utxos } = await buildBCHTx({
147
+ ...rest,
148
+ assetValue,
149
+ feeRate,
150
+ recipient,
151
+ sender: from,
152
+ });
153
+
154
+ const tx = await signTransaction({ builder, utxos });
155
+ const txHex = tx.toHex();
156
+
157
+ return broadcastTx(txHex);
158
+ };
159
+ }
160
+
161
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: TODO: refactor
162
+ async function buildTx({ assetValue, recipient, memo, feeRate, sender }: UTXOBuildTxParams) {
163
+ const { Psbt } = await import("bitcoinjs-lib");
164
+ const recipientCashAddress = toCashAddress(recipient);
165
+ if (!validateAddress(recipientCashAddress)) throw new Error("Invalid address");
166
+
167
+ const utxos = await getUtxoApi(chain).scanUTXOs({
168
+ address: stripToCashAddress(sender),
169
+ fetchTxHex: true,
170
+ });
171
+
172
+ const feeRateWhole = Number(feeRate.toFixed(0));
173
+ const compiledMemo = memo ? await compileMemo(memo) : null;
174
+
175
+ const targetOutputs = [] as TargetOutput[];
176
+
177
+ // output to recipient
178
+ targetOutputs.push({
179
+ address: toLegacyAddress(recipient),
180
+ value: assetValue.getBaseValue("number"),
181
+ });
182
+
183
+ //2. add output memo to targets (optional)
184
+ if (compiledMemo) {
185
+ targetOutputs.push({ script: compiledMemo, value: 0 });
186
+ }
187
+
188
+ const { inputs, outputs } = accumulative({
189
+ inputs: utxos,
190
+ outputs: targetOutputs,
191
+ feeRate: feeRateWhole,
192
+ chain,
193
+ });
194
+
195
+ // .inputs and .outputs will be undefined if no solution was found
196
+ if (!(inputs && outputs)) throw new Error("Balance insufficient for transaction");
197
+ const getNetwork = await getUtxoNetwork();
198
+ const psbt = new Psbt({ network: getNetwork(chain) }); // Network-specific
199
+
200
+ for (const { hash, index, witnessUtxo } of inputs) {
201
+ psbt.addInput({ hash, index, witnessUtxo });
202
+ }
203
+
204
+ // Outputs
205
+ for (const output of outputs) {
206
+ const address =
207
+ "address" in output && output.address ? output.address : toLegacyAddress(sender);
208
+ const params = output.script
209
+ ? compiledMemo
210
+ ? { script: compiledMemo, value: 0 }
211
+ : undefined
212
+ : { address, value: output.value };
213
+
214
+ if (params) {
215
+ psbt.addOutput(params);
216
+ }
217
+ }
218
+
219
+ return { psbt, utxos, inputs: inputs as UTXOType[] };
220
+ }
221
+
222
+ async function createKeysForPath({
223
+ phrase,
224
+ derivationPath = `${DerivationPath.BCH}/0`,
225
+ wif,
226
+ }: { wif?: string; phrase?: string; derivationPath?: string }) {
227
+ const { ECPairFactory } = await import("ecpair");
228
+ const secp256k1 = await import("@bitcoinerlab/secp256k1");
229
+ const { mnemonicToSeedSync } = await import("@scure/bip39");
230
+ // @ts-ignore TODO: check why wallets doesn't see modules included in toolbox
231
+ const { HDNode } = await import("@psf/bitcoincashjs-lib");
232
+ const getNetwork = await getUtxoNetwork();
233
+
234
+ const network = getNetwork(chain);
235
+
236
+ if (wif) {
237
+ return ECPairFactory(secp256k1).fromWIF(wif, network);
238
+ }
239
+ if (!phrase) throw new Error("No phrase provided");
240
+
241
+ const masterHDNode = HDNode.fromSeedBuffer(Buffer.from(mnemonicToSeedSync(phrase)), network);
242
+ const keyPair = masterHDNode.derivePath(derivationPath).keyPair;
243
+ // TODO: Figure out same pattern as in BTC
244
+ // const testWif = keyPair.toWIF();
245
+ // const k = ECPairFactory(secp256k1).fromWIF(testWif, network);
246
+ // const a = payments.p2pkh({ pubkey: k.publicKey, network });
247
+
248
+ return keyPair;
249
+ }
250
+
251
+ function getAddressFromKeys(keys: { getAddress: (index?: number) => string }) {
252
+ const address = keys.getAddress(0);
253
+ return stripToCashAddress(address);
254
+ }
255
+
256
+ type TransactionBuilderType = {
257
+ inputs: any[];
258
+ sign(
259
+ vin: number,
260
+ keyPair: { getAddress: (index?: number) => string },
261
+ redeemScript?: Buffer,
262
+ hashType?: number,
263
+ witnessValue?: number,
264
+ witnessScript?: Buffer,
265
+ signatureAlgorithm?: string,
266
+ ): void;
267
+ build(): TransactionType;
268
+ };
@@ -0,0 +1,41 @@
1
+ import { Chain, type UTXOChain } from "@swapkit/helpers";
2
+
3
+ import { createBCHToolbox } from "./bitcoinCash";
4
+ import { createUTXOToolbox } from "./utxo";
5
+
6
+ type BCHToolbox = Awaited<ReturnType<typeof createBCHToolbox>>;
7
+ type CommonUTXOToolbox = Awaited<ReturnType<typeof createUTXOToolbox>>;
8
+
9
+ type UTXOToolboxes = {
10
+ [Chain.BitcoinCash]: BCHToolbox;
11
+ [Chain.Bitcoin]: CommonUTXOToolbox;
12
+ [Chain.Dogecoin]: CommonUTXOToolbox;
13
+ [Chain.Litecoin]: CommonUTXOToolbox;
14
+ [Chain.Dash]: CommonUTXOToolbox;
15
+ };
16
+
17
+ export type UTXOWallets = {
18
+ [key in keyof UTXOToolboxes]: ReturnType<UTXOToolboxes[key]>;
19
+ };
20
+
21
+ export async function getToolboxByChain<T extends UTXOChain>(chain: T): Promise<UTXOToolboxes[T]> {
22
+ switch (chain) {
23
+ case Chain.BitcoinCash: {
24
+ const toolbox = await createBCHToolbox();
25
+ return toolbox as UTXOToolboxes[T];
26
+ }
27
+
28
+ case Chain.Bitcoin:
29
+ case Chain.Dogecoin:
30
+ case Chain.Litecoin:
31
+ case Chain.Dash: {
32
+ const toolbox = await createUTXOToolbox(chain);
33
+ return toolbox as UTXOToolboxes[T];
34
+ }
35
+
36
+ default:
37
+ throw new Error(`Chain ${chain} is not supported`);
38
+ }
39
+ }
40
+
41
+ export { stripToCashAddress, stripPrefix, validateAddress } from "./bitcoinCash";