mainnet-js 3.1.7 → 4.0.0-next.10

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 (267) hide show
  1. package/dist/module/cache/IndexedDbCache.d.ts +1 -1
  2. package/dist/module/cache/IndexedDbCache.d.ts.map +1 -1
  3. package/dist/module/cache/MemoryCache.d.ts +1 -1
  4. package/dist/module/cache/MemoryCache.d.ts.map +1 -1
  5. package/dist/module/cache/WebStorageCache.d.ts +1 -1
  6. package/dist/module/cache/WebStorageCache.d.ts.map +1 -1
  7. package/dist/module/cache/walletCache.d.ts +16 -6
  8. package/dist/module/cache/walletCache.d.ts.map +1 -1
  9. package/dist/module/cache/walletCache.js +92 -34
  10. package/dist/module/cache/walletCache.js.map +1 -1
  11. package/dist/module/cli.js +1 -2
  12. package/dist/module/cli.js.map +1 -1
  13. package/dist/module/db/index.d.ts +1 -1
  14. package/dist/module/db/index.d.ts.map +1 -1
  15. package/dist/module/db/index.js +1 -1
  16. package/dist/module/db/index.js.map +1 -1
  17. package/dist/module/enum.d.ts +1 -1
  18. package/dist/module/enum.d.ts.map +1 -1
  19. package/dist/module/history/getHistory.d.ts +1 -1
  20. package/dist/module/history/getHistory.d.ts.map +1 -1
  21. package/dist/module/history/getHistory.js +3 -3
  22. package/dist/module/history/getHistory.js.map +1 -1
  23. package/dist/module/index.d.ts +25 -22
  24. package/dist/module/index.d.ts.map +1 -1
  25. package/dist/module/index.js +33 -26
  26. package/dist/module/index.js.map +1 -1
  27. package/dist/module/interface.d.ts +12 -2
  28. package/dist/module/interface.d.ts.map +1 -1
  29. package/dist/module/interface.js.map +1 -1
  30. package/dist/module/libauth.d.ts +1 -1
  31. package/dist/module/libauth.d.ts.map +1 -1
  32. package/dist/module/libauth.js +1 -1
  33. package/dist/module/libauth.js.map +1 -1
  34. package/dist/module/mine/mine.d.ts +2 -7
  35. package/dist/module/mine/mine.d.ts.map +1 -1
  36. package/dist/module/mine/mine.js +6 -27
  37. package/dist/module/mine/mine.js.map +1 -1
  38. package/dist/module/network/Connection.d.ts +1 -12
  39. package/dist/module/network/Connection.d.ts.map +1 -1
  40. package/dist/module/network/Connection.js +24 -33
  41. package/dist/module/network/Connection.js.map +1 -1
  42. package/dist/module/network/ElectrumNetworkProvider.d.ts +16 -17
  43. package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
  44. package/dist/module/network/ElectrumNetworkProvider.js +91 -93
  45. package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
  46. package/dist/module/network/MockNetworkProvider.d.ts +28 -0
  47. package/dist/module/network/MockNetworkProvider.d.ts.map +1 -0
  48. package/dist/module/network/MockNetworkProvider.js +74 -0
  49. package/dist/module/network/MockNetworkProvider.js.map +1 -0
  50. package/dist/module/network/NetworkProvider.d.ts +9 -2
  51. package/dist/module/network/NetworkProvider.d.ts.map +1 -1
  52. package/dist/module/network/configuration.d.ts +2 -4
  53. package/dist/module/network/configuration.d.ts.map +1 -1
  54. package/dist/module/network/configuration.js +25 -50
  55. package/dist/module/network/configuration.js.map +1 -1
  56. package/dist/module/network/constant.d.ts +7 -7
  57. package/dist/module/network/constant.d.ts.map +1 -1
  58. package/dist/module/network/constant.js +21 -24
  59. package/dist/module/network/constant.js.map +1 -1
  60. package/dist/module/network/default.d.ts +5 -3
  61. package/dist/module/network/default.d.ts.map +1 -1
  62. package/dist/module/network/default.js +29 -51
  63. package/dist/module/network/default.js.map +1 -1
  64. package/dist/module/network/index.d.ts +4 -4
  65. package/dist/module/network/index.d.ts.map +1 -1
  66. package/dist/module/network/index.js +2 -2
  67. package/dist/module/network/index.js.map +1 -1
  68. package/dist/module/network/interface.d.ts +0 -6
  69. package/dist/module/network/interface.d.ts.map +1 -1
  70. package/dist/module/rate/ExchangeRate.d.ts +1 -1
  71. package/dist/module/rate/ExchangeRate.d.ts.map +1 -1
  72. package/dist/module/rate/ExchangeRate.js +13 -7
  73. package/dist/module/rate/ExchangeRate.js.map +1 -1
  74. package/dist/module/transaction/Wif.d.ts +3 -3
  75. package/dist/module/transaction/Wif.d.ts.map +1 -1
  76. package/dist/module/transaction/Wif.js +4 -4
  77. package/dist/module/transaction/Wif.js.map +1 -1
  78. package/dist/module/transaction/allocateFee.d.ts +1 -1
  79. package/dist/module/transaction/allocateFee.d.ts.map +1 -1
  80. package/dist/module/transaction/allocateFee.js +2 -2
  81. package/dist/module/transaction/allocateFee.js.map +1 -1
  82. package/dist/module/util/deriveCashaddr.js.map +1 -1
  83. package/dist/module/util/deriveNetwork.js +1 -1
  84. package/dist/module/util/deriveNetwork.js.map +1 -1
  85. package/dist/module/util/getAddrsByXpubKey.js +1 -1
  86. package/dist/module/util/getAddrsByXpubKey.js.map +1 -1
  87. package/dist/module/util/getXPubKey.js +1 -1
  88. package/dist/module/util/getXPubKey.js.map +1 -1
  89. package/dist/module/util/hd.d.ts +2 -0
  90. package/dist/module/util/hd.d.ts.map +1 -1
  91. package/dist/module/util/hd.js +41 -0
  92. package/dist/module/util/hd.js.map +1 -1
  93. package/dist/module/util/index.d.ts +7 -9
  94. package/dist/module/util/index.d.ts.map +1 -1
  95. package/dist/module/util/index.js +7 -9
  96. package/dist/module/util/index.js.map +1 -1
  97. package/dist/module/util/transaction.js +1 -1
  98. package/dist/module/util/transaction.js.map +1 -1
  99. package/dist/module/wallet/Base.d.ts +13 -9
  100. package/dist/module/wallet/Base.d.ts.map +1 -1
  101. package/dist/module/wallet/Base.js +54 -58
  102. package/dist/module/wallet/Base.js.map +1 -1
  103. package/dist/module/wallet/HDWallet.d.ts.map +1 -1
  104. package/dist/module/wallet/HDWallet.js +19 -38
  105. package/dist/module/wallet/HDWallet.js.map +1 -1
  106. package/dist/module/wallet/Util.d.ts +4 -22
  107. package/dist/module/wallet/Util.d.ts.map +1 -1
  108. package/dist/module/wallet/Util.js +75 -102
  109. package/dist/module/wallet/Util.js.map +1 -1
  110. package/dist/module/wallet/Watch.d.ts +24 -5
  111. package/dist/module/wallet/Watch.d.ts.map +1 -1
  112. package/dist/module/wallet/Watch.js +141 -17
  113. package/dist/module/wallet/Watch.js.map +1 -1
  114. package/dist/module/wallet/Wif.d.ts +2 -6
  115. package/dist/module/wallet/Wif.d.ts.map +1 -1
  116. package/dist/module/wallet/Wif.js +3 -69
  117. package/dist/module/wallet/Wif.js.map +1 -1
  118. package/dist/module/wallet/createWallet.d.ts +1 -1
  119. package/dist/module/wallet/createWallet.d.ts.map +1 -1
  120. package/dist/module/wallet/createWallet.js +2 -1
  121. package/dist/module/wallet/createWallet.js.map +1 -1
  122. package/dist/module/wallet/interface.d.ts +3 -2
  123. package/dist/module/wallet/interface.d.ts.map +1 -1
  124. package/dist/module/wallet/model.d.ts +2 -1
  125. package/dist/module/wallet/model.d.ts.map +1 -1
  126. package/dist/module/wallet/model.js +1 -1
  127. package/dist/module/wallet/model.js.map +1 -1
  128. package/package.json +17 -29
  129. package/dist/index.html +0 -9
  130. package/dist/mainnet-3.1.7.js +0 -2066
  131. package/dist/module/network/util.d.ts +0 -3
  132. package/dist/module/network/util.d.ts.map +0 -1
  133. package/dist/module/network/util.js +0 -27
  134. package/dist/module/network/util.js.map +0 -1
  135. package/dist/module/test/expect.d.ts +0 -12
  136. package/dist/module/test/expect.d.ts.map +0 -1
  137. package/dist/module/test/expect.js +0 -47
  138. package/dist/module/test/expect.js.map +0 -1
  139. package/dist/module/test/fetch.d.ts +0 -3
  140. package/dist/module/test/fetch.d.ts.map +0 -1
  141. package/dist/module/test/fetch.js +0 -32
  142. package/dist/module/test/fetch.js.map +0 -1
  143. package/dist/module/util/randomBytes.d.ts +0 -2
  144. package/dist/module/util/randomBytes.d.ts.map +0 -1
  145. package/dist/module/util/randomBytes.js +0 -13
  146. package/dist/module/util/randomBytes.js.map +0 -1
  147. package/dist/tsconfig.tsbuildinfo +0 -1
  148. package/src/cache/IndexedDbCache.test.ts +0 -15
  149. package/src/cache/IndexedDbCache.ts +0 -172
  150. package/src/cache/MemoryCache.test.ts +0 -15
  151. package/src/cache/MemoryCache.ts +0 -32
  152. package/src/cache/WebStorageCache.test.ts +0 -15
  153. package/src/cache/WebStorageCache.ts +0 -38
  154. package/src/cache/index.ts +0 -2
  155. package/src/cache/interface.ts +0 -9
  156. package/src/cache/walletCache.ts +0 -254
  157. package/src/chain.ts +0 -3
  158. package/src/cli.ts +0 -32
  159. package/src/config.ts +0 -23
  160. package/src/constant.ts +0 -27
  161. package/src/db/ExchangeRateProvider.ts +0 -28
  162. package/src/db/StorageProvider.ts +0 -64
  163. package/src/db/index.ts +0 -2
  164. package/src/db/interface.ts +0 -11
  165. package/src/enum.ts +0 -34
  166. package/src/history/getHistory.test.ts +0 -290
  167. package/src/history/getHistory.ts +0 -411
  168. package/src/history/interface.ts +0 -24
  169. package/src/index.ts +0 -48
  170. package/src/interface.ts +0 -72
  171. package/src/libauth.ts +0 -11
  172. package/src/message/index.ts +0 -2
  173. package/src/message/interface.ts +0 -40
  174. package/src/message/signed.test.ts +0 -309
  175. package/src/message/signed.ts +0 -201
  176. package/src/mine/index.ts +0 -1
  177. package/src/mine/mine.test.ts +0 -10
  178. package/src/mine/mine.ts +0 -42
  179. package/src/network/Connection.test.ts +0 -51
  180. package/src/network/Connection.ts +0 -73
  181. package/src/network/ElectrumNetworkProvider.ts +0 -657
  182. package/src/network/NetworkProvider.ts +0 -180
  183. package/src/network/Rpc.test.ts +0 -130
  184. package/src/network/configuration.test.ts +0 -59
  185. package/src/network/configuration.ts +0 -72
  186. package/src/network/constant.ts +0 -43
  187. package/src/network/default.ts +0 -120
  188. package/src/network/electrum.test.ts +0 -28
  189. package/src/network/getRelayFeeCache.test.ts +0 -15
  190. package/src/network/getRelayFeeCache.ts +0 -23
  191. package/src/network/index.ts +0 -14
  192. package/src/network/interface.ts +0 -80
  193. package/src/network/util.test.ts +0 -24
  194. package/src/network/util.ts +0 -30
  195. package/src/rate/ExchangeRate.test.headless.js +0 -35
  196. package/src/rate/ExchangeRate.test.ts +0 -51
  197. package/src/rate/ExchangeRate.ts +0 -142
  198. package/src/test/expect.ts +0 -59
  199. package/src/test/fetch.ts +0 -39
  200. package/src/test/json.test.ts +0 -13
  201. package/src/transaction/Wif.ts +0 -680
  202. package/src/transaction/allocateFee.test.ts +0 -298
  203. package/src/transaction/allocateFee.ts +0 -149
  204. package/src/util/amountInSatoshi.test.ts +0 -27
  205. package/src/util/amountInSatoshi.ts +0 -33
  206. package/src/util/asSendRequestObject.ts +0 -81
  207. package/src/util/base64.test.ts +0 -39
  208. package/src/util/base64.ts +0 -12
  209. package/src/util/browserNotSupported.ts +0 -7
  210. package/src/util/checkForEmptySeed.ts +0 -9
  211. package/src/util/checkUtxos.ts +0 -29
  212. package/src/util/checkWifNetwork.ts +0 -24
  213. package/src/util/convert.test.ts +0 -46
  214. package/src/util/convert.ts +0 -50
  215. package/src/util/delay.ts +0 -3
  216. package/src/util/deriveCashaddr.test.ts +0 -164
  217. package/src/util/deriveCashaddr.ts +0 -143
  218. package/src/util/deriveLockscript.ts +0 -16
  219. package/src/util/deriveNetwork.ts +0 -19
  220. package/src/util/derivePublicKeyHash.test.ts +0 -55
  221. package/src/util/derivePublicKeyHash.ts +0 -64
  222. package/src/util/floor.test.ts +0 -21
  223. package/src/util/floor.ts +0 -4
  224. package/src/util/getAddrsByXpubKey.test.ts +0 -115
  225. package/src/util/getAddrsByXpubKey.ts +0 -86
  226. package/src/util/getRuntimePlatform.test.headless.js +0 -40
  227. package/src/util/getRuntimePlatform.test.ts +0 -5
  228. package/src/util/getRuntimePlatform.ts +0 -31
  229. package/src/util/getUsdRate.ts +0 -5
  230. package/src/util/getXPubKey.ts +0 -39
  231. package/src/util/hash160.test.ts +0 -18
  232. package/src/util/hash160.ts +0 -12
  233. package/src/util/hd.ts +0 -16
  234. package/src/util/header.test.ts +0 -34
  235. package/src/util/header.ts +0 -26
  236. package/src/util/index.ts +0 -33
  237. package/src/util/randomBytes.ts +0 -13
  238. package/src/util/randomInt.test.ts +0 -15
  239. package/src/util/randomInt.ts +0 -4
  240. package/src/util/sanitizeAddress.ts +0 -10
  241. package/src/util/sanitizeUnit.ts +0 -11
  242. package/src/util/satoshiToAmount.test.ts +0 -6
  243. package/src/util/satoshiToAmount.ts +0 -33
  244. package/src/util/sumSendRequestAmounts.ts +0 -34
  245. package/src/util/sumUtxoValue.ts +0 -27
  246. package/src/util/transaction.ts +0 -10
  247. package/src/wallet/Base.ts +0 -1563
  248. package/src/wallet/Cashtokens.test.headless.js +0 -730
  249. package/src/wallet/Cashtokens.test.ts +0 -1411
  250. package/src/wallet/HDWallet.test.ts +0 -1086
  251. package/src/wallet/HDWallet.ts +0 -992
  252. package/src/wallet/Util.test.ts +0 -134
  253. package/src/wallet/Util.ts +0 -191
  254. package/src/wallet/WalletCache.test.ts +0 -45
  255. package/src/wallet/Watch.ts +0 -441
  256. package/src/wallet/Wif.bip39.test.ts +0 -48
  257. package/src/wallet/Wif.test.ts +0 -1189
  258. package/src/wallet/Wif.ts +0 -687
  259. package/src/wallet/Wif.watchOnly.test.ts +0 -58
  260. package/src/wallet/createWallet.ts +0 -238
  261. package/src/wallet/enum.ts +0 -18
  262. package/src/wallet/interface.ts +0 -102
  263. package/src/wallet/model.test.ts +0 -24
  264. package/src/wallet/model.ts +0 -352
  265. package/tsconfig.browser.json +0 -11
  266. package/tsconfig.json +0 -33
  267. package/webpack.config.cjs +0 -132
@@ -1,680 +0,0 @@
1
- import {
2
- walletTemplateP2pkhNonHd,
3
- cashAddressToLockingBytecode,
4
- Compiler,
5
- encodeTransaction,
6
- generateTransaction,
7
- importWalletTemplate,
8
- AnyCompilerConfiguration,
9
- AuthenticationProgramStateCommon,
10
- Output,
11
- hexToBin,
12
- verifyTransactionTokens,
13
- decodeTransaction,
14
- TransactionTemplateFixed,
15
- CompilationContextBch,
16
- walletTemplateToCompilerBch,
17
- } from "@bitauth/libauth";
18
- import { NFTCapability, TokenI, Utxo } from "../interface.js";
19
- import { allocateFee } from "./allocateFee.js";
20
-
21
- import { DUST_UTXO_THRESHOLD } from "../constant.js";
22
- import {
23
- OpReturnData,
24
- SendRequest,
25
- SendRequestType,
26
- SourceOutput,
27
- TokenSendRequest,
28
- } from "../wallet/model.js";
29
- import { sumSendRequestAmounts } from "../util/sumSendRequestAmounts.js";
30
- import { sumUtxoValue } from "../util/sumUtxoValue.js";
31
- import { FeePaidByEnum } from "../wallet/enum.js";
32
- import { WalletCache } from "../cache/walletCache.js";
33
-
34
- export const placeholderPrivateKey =
35
- "0000000000000000000000000000000000000000000000000000000000000001";
36
- export const placeholderPrivateKeyBin = hexToBin(placeholderPrivateKey);
37
-
38
- // Build a transaction for a p2pkh transaction for a non HD wallet
39
- export async function buildP2pkhNonHdTransaction({
40
- inputs,
41
- outputs,
42
- signingKey,
43
- fee = 0n,
44
- discardChange = false,
45
- feePaidBy = FeePaidByEnum.change,
46
- changeAddress = "",
47
- walletCache,
48
- }: {
49
- inputs: Utxo[];
50
- outputs: Array<SendRequest | TokenSendRequest | OpReturnData>;
51
- signingKey?: Uint8Array;
52
- fee?: bigint;
53
- discardChange?: boolean;
54
- feePaidBy?: FeePaidByEnum;
55
- changeAddress?: string;
56
- walletCache: WalletCache;
57
- }) {
58
- if (!signingKey) {
59
- throw new Error("Missing signing key when building transaction");
60
- }
61
-
62
- const template = importWalletTemplate(walletTemplateP2pkhNonHd);
63
- if (typeof template === "string") {
64
- throw new Error("Transaction template error");
65
- }
66
-
67
- const compiler = walletTemplateToCompilerBch(template);
68
- const inputAmount = sumUtxoValue(inputs);
69
-
70
- const sendAmount = await sumSendRequestAmounts(outputs);
71
-
72
- const changeAmount = BigInt(inputAmount) - BigInt(sendAmount) - BigInt(fee);
73
-
74
- outputs = allocateFee(outputs, fee, feePaidBy, changeAmount);
75
-
76
- const lockedOutputs = await prepareOutputs(outputs);
77
-
78
- if (!changeAddress) {
79
- changeAddress = inputs[0].address;
80
- }
81
-
82
- if (discardChange !== true) {
83
- if (changeAmount > DUST_UTXO_THRESHOLD) {
84
- const changeLockingBytecode = cashAddressToLockingBytecode(changeAddress);
85
- if (typeof changeLockingBytecode === "string") {
86
- throw Error(changeLockingBytecode);
87
- }
88
- lockedOutputs.push({
89
- lockingBytecode: changeLockingBytecode.bytecode,
90
- valueSatoshis: BigInt(changeAmount),
91
- });
92
- }
93
- }
94
-
95
- const { preparedInputs, sourceOutputs } = prepareInputs({
96
- inputs,
97
- compiler,
98
- signingKey,
99
- walletCache,
100
- });
101
- const result = generateTransaction({
102
- inputs: preparedInputs,
103
- locktime: 0,
104
- outputs: lockedOutputs,
105
- version: 2,
106
- });
107
-
108
- if (!result.success) {
109
- throw Error("Error building transaction with fee");
110
- }
111
-
112
- const tokenValidationResult = verifyTransactionTokens(
113
- result.transaction,
114
- sourceOutputs,
115
- { maximumTokenCommitmentLength: 40 }
116
- );
117
- if (tokenValidationResult !== true && fee > 0) {
118
- throw tokenValidationResult;
119
- }
120
-
121
- return { transaction: result.transaction, sourceOutputs: sourceOutputs };
122
- }
123
-
124
- export function prepareInputs({
125
- inputs,
126
- compiler,
127
- signingKey,
128
- walletCache,
129
- }: {
130
- inputs: Utxo[];
131
- compiler: Compiler<
132
- CompilationContextBch,
133
- AnyCompilerConfiguration<CompilationContextBch>,
134
- AuthenticationProgramStateCommon
135
- >;
136
- signingKey: Uint8Array;
137
- walletCache: WalletCache;
138
- }) {
139
- const preparedInputs: any[] = [];
140
- const sourceOutputs: any[] = [];
141
- for (const i of inputs) {
142
- const utxoTxnValue = i.satoshis;
143
- const utxoIndex = i.vout;
144
- // slice will create a clone of the array
145
- const utxoOutpointTransactionHash = new Uint8Array(
146
- i.txid.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16))
147
- );
148
- // reverse the cloned copy
149
- // utxoOutpointTransactionHash.reverse();
150
- if (!utxoOutpointTransactionHash || utxoIndex === undefined) {
151
- throw new Error("Missing unspent outpoint when building transaction");
152
- }
153
-
154
- const libAuthToken = i.token && {
155
- amount: BigInt(i.token.amount),
156
- category: hexToBin(i.token.category),
157
- nft:
158
- i.token.nft?.capability !== undefined ||
159
- i.token.nft?.commitment !== undefined
160
- ? {
161
- capability: i.token.nft?.capability,
162
- commitment:
163
- i.token.nft?.commitment !== undefined &&
164
- hexToBin(i.token.nft?.commitment!),
165
- }
166
- : undefined,
167
- };
168
- const key =
169
- walletCache.get(i.address)?.privateKey ??
170
- (signingKey?.length ? signingKey : Uint8Array.from(Array(32)));
171
- const newInput = {
172
- outpointIndex: utxoIndex,
173
- outpointTransactionHash: utxoOutpointTransactionHash,
174
- sequenceNumber: 0,
175
- unlockingBytecode: {
176
- compiler,
177
- data: {
178
- keys: { privateKeys: { key: key } },
179
- },
180
- valueSatoshis: BigInt(utxoTxnValue),
181
- script: "unlock",
182
- token: libAuthToken,
183
- },
184
- };
185
-
186
- preparedInputs.push(newInput);
187
-
188
- const lockingBytecode = cashAddressToLockingBytecode(i.address);
189
- if (typeof lockingBytecode === "string") {
190
- throw lockingBytecode;
191
- }
192
-
193
- sourceOutputs.push({
194
- outpointIndex: utxoIndex,
195
- outpointTransactionHash: utxoOutpointTransactionHash,
196
- sequenceNumber: 0,
197
- unlockingBytecode: Uint8Array.from([]),
198
-
199
- // additional info for sourceOutputs
200
- lockingBytecode: lockingBytecode.bytecode,
201
- valueSatoshis: BigInt(utxoTxnValue),
202
- token: libAuthToken,
203
- });
204
- }
205
- return { preparedInputs, sourceOutputs };
206
- }
207
-
208
- /**
209
- * prepareOutputs - create outputs for a transaction from a list of send requests
210
- *
211
- * a wrapper function
212
- *
213
- * @returns A promise to a list of unspent outputs
214
- */
215
- export async function prepareOutputs(
216
- outputs: Array<SendRequest | TokenSendRequest | OpReturnData>
217
- ) {
218
- const lockedOutputs: Output[] = [];
219
- for (const output of outputs) {
220
- if (output instanceof TokenSendRequest) {
221
- lockedOutputs.push(prepareTokenOutputs(output));
222
- continue;
223
- }
224
-
225
- if (output instanceof OpReturnData) {
226
- lockedOutputs.push(prepareOpReturnOutput(output));
227
- continue;
228
- }
229
-
230
- const outputLockingBytecode = cashAddressToLockingBytecode(output.cashaddr);
231
- if (typeof outputLockingBytecode === "string")
232
- throw new Error(outputLockingBytecode);
233
-
234
- const sendAmount = Number(output.value);
235
- if (sendAmount % 1 !== 0) {
236
- throw Error(
237
- `Cannot send ${sendAmount} satoshis, (fractional sats do not exist, yet), please use an integer number.`
238
- );
239
- }
240
- const lockedOutput: Output = {
241
- lockingBytecode: outputLockingBytecode.bytecode,
242
- valueSatoshis: BigInt(sendAmount),
243
- };
244
- lockedOutputs.push(lockedOutput);
245
- }
246
- return lockedOutputs;
247
- }
248
-
249
- /**
250
- * prepareOpReturnOutput - create an output for OP_RETURN data
251
- *
252
- * @returns A promise to a list of unspent outputs
253
- */
254
- export function prepareOpReturnOutput(request: OpReturnData): Output {
255
- return {
256
- lockingBytecode: request.buffer,
257
- valueSatoshis: BigInt(0),
258
- };
259
- }
260
-
261
- /**
262
- * prepareOpReturnOutput - create an output for token data
263
- *
264
- * @returns A libauth Output
265
- */
266
- export function prepareTokenOutputs(request: TokenSendRequest): Output {
267
- const token: TokenI = request;
268
- const outputLockingBytecode = cashAddressToLockingBytecode(request.cashaddr);
269
- if (typeof outputLockingBytecode === "string")
270
- throw new Error(outputLockingBytecode);
271
-
272
- const libAuthToken = {
273
- amount: BigInt(token.amount),
274
- category: hexToBin(token.category),
275
- nft:
276
- token.nft?.capability !== undefined || token.nft?.commitment !== undefined
277
- ? {
278
- capability: token.nft?.capability,
279
- commitment:
280
- token.nft?.commitment !== undefined &&
281
- hexToBin(token.nft?.commitment!),
282
- }
283
- : undefined,
284
- };
285
-
286
- return {
287
- lockingBytecode: outputLockingBytecode.bytecode,
288
- valueSatoshis: BigInt(request.value || 1000),
289
- token: libAuthToken,
290
- } as Output;
291
- }
292
-
293
- /**
294
- * getSuitableUtxos - Filter a list of unspent transaction outputs to the minimum needed to complete a transaction
295
- *
296
- * a intermediate function
297
- *
298
- * @param unspentOutputs An unfiltered list of available unspent transaction outputs
299
- *
300
- * @returns A promise to a list of unspent outputs
301
- */
302
- export async function getSuitableUtxos(
303
- inputs: Utxo[],
304
- amountRequired: bigint | undefined,
305
- bestHeight: number,
306
- feePaidBy: FeePaidByEnum,
307
- requests: SendRequestType[],
308
- ensureUtxos: Utxo[] = [],
309
- tokenOperation: "send" | "genesis" | "mint" | "burn" = "send"
310
- ): Promise<Utxo[]> {
311
- const utxoKey = (u: Utxo) => `${u.txid}:${u.vout}`;
312
- const selectedSet = new Set<string>();
313
- const suitableUtxos: Utxo[] = [];
314
-
315
- for (const u of ensureUtxos) {
316
- const key = utxoKey(u);
317
- if (!selectedSet.has(key)) {
318
- selectedSet.add(key);
319
- suitableUtxos.push(u);
320
- }
321
- }
322
-
323
- let amountAvailable = suitableUtxos.reduce(
324
- (sum, u) => sum + BigInt(u.satoshis),
325
- BigInt(0)
326
- );
327
- const tokenRequests = requests.filter(
328
- (val) => val instanceof TokenSendRequest
329
- ) as TokenSendRequest[];
330
-
331
- const usedIndices = new Set<number>();
332
-
333
- // Track how many times each selected UTXO has been "claimed" by a request
334
- const claimedUtxos = new Map<string, number>();
335
-
336
- // find matching utxos for token transfers
337
- if (tokenOperation === "send") {
338
- for (const request of tokenRequests) {
339
- // Search suitableUtxos then inputs sequentially to find matching tokens
340
- const matchCommitment = (val: Utxo) =>
341
- val.token?.category === request.category &&
342
- val.token?.nft?.capability === request.nft?.capability &&
343
- val.token?.nft?.commitment === request.nft?.commitment;
344
-
345
- // For NFTs (non-fungible), each request needs its own UTXO
346
- // For FT-only requests, a single UTXO can satisfy multiple requests
347
- const isFungibleOnly =
348
- request.nft?.capability === undefined &&
349
- request.nft?.commitment === undefined;
350
-
351
- // Check already-selected suitable utxos first (no need to re-add)
352
- let found = false;
353
- if (isFungibleOnly) {
354
- found = suitableUtxos.some(matchCommitment);
355
- } else {
356
- // For NFTs, find an unclaimed matching UTXO in suitableUtxos
357
- for (const val of suitableUtxos) {
358
- if (!matchCommitment(val)) continue;
359
- const key = utxoKey(val);
360
- const claims = claimedUtxos.get(key) || 0;
361
- if (claims === 0) {
362
- claimedUtxos.set(key, claims + 1);
363
- found = true;
364
- break;
365
- }
366
- }
367
- }
368
-
369
- if (!found) {
370
- // Search available inputs for same commitment match
371
- for (let i = 0; i < inputs.length; i++) {
372
- if (usedIndices.has(i)) continue;
373
- const val = inputs[i];
374
- if (val.token?.category !== request.category) continue;
375
- if (!matchCommitment(val)) continue;
376
- const key = utxoKey(val);
377
- if (selectedSet.has(key)) continue;
378
-
379
- selectedSet.add(key);
380
- suitableUtxos.push(val);
381
- usedIndices.add(i);
382
- amountAvailable += BigInt(val.satoshis);
383
- if (!isFungibleOnly) {
384
- claimedUtxos.set(key, 1);
385
- }
386
- found = true;
387
- break;
388
- }
389
- }
390
-
391
- if (found) continue;
392
-
393
- if (
394
- request.nft?.capability === NFTCapability.minting ||
395
- request.nft?.capability === NFTCapability.mutable
396
- ) {
397
- // Check already-selected suitable utxos first
398
- const alreadyHas = suitableUtxos.some(
399
- (val) =>
400
- val.token?.category === request.category &&
401
- val.token?.nft?.capability === request.nft?.capability
402
- );
403
- if (alreadyHas) continue;
404
-
405
- let foundCapability = false;
406
- for (let i = 0; i < inputs.length; i++) {
407
- if (usedIndices.has(i)) continue;
408
- const val = inputs[i];
409
- if (
410
- val.token?.category === request.category &&
411
- val.token?.nft?.capability === request.nft?.capability
412
- ) {
413
- const key = utxoKey(val);
414
- if (selectedSet.has(key)) continue;
415
-
416
- selectedSet.add(key);
417
- suitableUtxos.push(val);
418
- usedIndices.add(i);
419
- amountAvailable += BigInt(val.satoshis);
420
- foundCapability = true;
421
- break;
422
- }
423
- }
424
- if (foundCapability) continue;
425
- }
426
-
427
- // handle splitting the hybrid (FT+NFT) token into its parts
428
- if (
429
- request.nft?.capability === undefined &&
430
- request.nft?.commitment === undefined
431
- ) {
432
- const hasCategoryInSuitable = suitableUtxos.some(
433
- (val) => val.token?.category === request.category
434
- );
435
- const hasCategoryInInputs =
436
- !hasCategoryInSuitable &&
437
- inputs.some(
438
- (val, i) =>
439
- !usedIndices.has(i) && val.token?.category === request.category
440
- );
441
- if (hasCategoryInSuitable || hasCategoryInInputs) {
442
- continue;
443
- }
444
- }
445
-
446
- throw Error(
447
- `No suitable token utxos available to send token with id "${request.category}", capability "${request.nft?.capability}", commitment "${request.nft?.commitment}"`
448
- );
449
- }
450
- }
451
-
452
- // find plain bch outputs
453
- for (let i = 0; i < inputs.length; i++) {
454
- // check early if we already have enough
455
- if (amountRequired && amountAvailable > amountRequired) {
456
- break;
457
- }
458
- if (usedIndices.has(i)) continue;
459
- const u = inputs[i];
460
- if (u.token) continue;
461
-
462
- const key = utxoKey(u);
463
- if (selectedSet.has(key)) continue;
464
-
465
- selectedSet.add(key);
466
- suitableUtxos.push(u);
467
- amountAvailable += BigInt(u.satoshis);
468
- }
469
-
470
- // if the fee is split with a feePaidBy option, skip checking change.
471
- if (feePaidBy && feePaidBy != FeePaidByEnum.change) {
472
- return suitableUtxos;
473
- }
474
-
475
- // If the amount needed is met, or no amount is given, return
476
- if (typeof amountRequired === "undefined") {
477
- return suitableUtxos;
478
- } else if (amountAvailable < amountRequired) {
479
- const e = Error(
480
- `Amount required was not met, ${amountRequired} satoshis needed, ${amountAvailable} satoshis available`
481
- );
482
- e["data"] = {
483
- required: amountRequired,
484
- available: amountAvailable,
485
- };
486
- throw e;
487
- } else {
488
- return suitableUtxos;
489
- }
490
- }
491
-
492
- // model-based imprecise and fast fee estimation
493
- export async function getFeeAmountSimple({
494
- utxos,
495
- sendRequests,
496
- relayFeePerByteInSatoshi,
497
- discardChange,
498
- }: {
499
- utxos: Utxo[];
500
- sendRequests: Array<SendRequest | TokenSendRequest | OpReturnData>;
501
- sourceAddress: string;
502
- relayFeePerByteInSatoshi: number;
503
- feePaidBy: FeePaidByEnum;
504
- discardChange?: boolean;
505
- }): Promise<bigint> {
506
- const inputSizeP2pkh = 148;
507
- const outputSizeP2pkh = 34;
508
-
509
- const inputTotalSize = utxos.reduce(
510
- (prev, curr) =>
511
- prev +
512
- (curr.token
513
- ? inputSizeP2pkh +
514
- 1 +
515
- 34 +
516
- Math.round(1 + (curr.token.nft?.commitment?.length ?? 0) / 2) +
517
- (curr.token.amount ? 9 : 0)
518
- : inputSizeP2pkh),
519
- 0
520
- );
521
-
522
- const outputSize = (sendRequest: SendRequestType) => {
523
- if (sendRequest.hasOwnProperty("category")) {
524
- const tokenRequest = sendRequest as TokenSendRequest;
525
- return (
526
- outputSizeP2pkh +
527
- 1 +
528
- 34 +
529
- Math.round(1 + (tokenRequest.nft?.commitment?.length ?? 0) / 2) +
530
- (tokenRequest.amount ? 9 : 0)
531
- );
532
- } else if (sendRequest.hasOwnProperty("buffer")) {
533
- return 9 + (sendRequest as OpReturnData).buffer.length;
534
- } else {
535
- return outputSizeP2pkh;
536
- }
537
- };
538
-
539
- const outputTotalSize =
540
- sendRequests.reduce((prev, curr) => prev + outputSize(curr), 0) +
541
- (discardChange ? 0 : outputSizeP2pkh);
542
-
543
- return BigInt(
544
- Math.ceil(
545
- (inputTotalSize + outputTotalSize + 16) * relayFeePerByteInSatoshi
546
- )
547
- );
548
- }
549
-
550
- // precise fee estimation
551
- export async function getFeeAmount({
552
- utxos,
553
- sendRequests,
554
- sourceAddress,
555
- relayFeePerByteInSatoshi,
556
- feePaidBy,
557
- discardChange,
558
- walletCache,
559
- }: {
560
- utxos: Utxo[];
561
- sendRequests: Array<SendRequest | TokenSendRequest | OpReturnData>;
562
- sourceAddress: string;
563
- relayFeePerByteInSatoshi: number;
564
- feePaidBy: FeePaidByEnum;
565
- discardChange?: boolean;
566
- walletCache: WalletCache;
567
- }) {
568
- // build transaction
569
- if (utxos) {
570
- // Build the transaction to get the approximate size
571
- const { encodedTransaction: draftTransaction } =
572
- await buildEncodedTransaction({
573
- inputs: utxos,
574
- outputs: sendRequests,
575
- signingKey: placeholderPrivateKeyBin,
576
- fee: 0n, //DUST_UTXO_THRESHOLD
577
- discardChange: discardChange ?? false,
578
- feePaidBy,
579
- changeAddress: "",
580
- walletCache,
581
- });
582
-
583
- return BigInt(
584
- Math.ceil(draftTransaction.length * relayFeePerByteInSatoshi + 1)
585
- );
586
- } else {
587
- throw Error(
588
- "The available inputs in the wallet cannot satisfy this send request"
589
- );
590
- }
591
- }
592
-
593
- // Build encoded transaction
594
- export async function buildEncodedTransaction({
595
- inputs,
596
- outputs,
597
- signingKey,
598
- fee = 0n,
599
- discardChange = false,
600
- feePaidBy = FeePaidByEnum.change,
601
- changeAddress = "",
602
- buildUnsigned = false,
603
- walletCache,
604
- }: {
605
- inputs: Utxo[];
606
- outputs: Array<SendRequest | TokenSendRequest | OpReturnData>;
607
- signingKey: Uint8Array;
608
- fee?: bigint;
609
- discardChange?: boolean;
610
- feePaidBy?: FeePaidByEnum;
611
- changeAddress?: string;
612
- buildUnsigned?: boolean;
613
- walletCache: WalletCache;
614
- }) {
615
- const { transaction, sourceOutputs } = await buildP2pkhNonHdTransaction({
616
- inputs,
617
- outputs,
618
- signingKey,
619
- fee,
620
- discardChange,
621
- feePaidBy,
622
- changeAddress,
623
- walletCache,
624
- });
625
-
626
- if (buildUnsigned === true) {
627
- transaction.inputs.forEach(
628
- (input) => (input.unlockingBytecode = Uint8Array.from([]))
629
- );
630
- }
631
-
632
- return { encodedTransaction: encodeTransaction(transaction), sourceOutputs };
633
- }
634
-
635
- export async function signUnsignedTransaction(
636
- transaction: Uint8Array | string,
637
- sourceOutputs: SourceOutput[],
638
- signingKey: Uint8Array
639
- ): Promise<Uint8Array> {
640
- if (typeof transaction === "string") {
641
- transaction = hexToBin(transaction);
642
- }
643
-
644
- const decoded = decodeTransaction(transaction);
645
- if (typeof decoded === "string") {
646
- throw decoded;
647
- }
648
-
649
- const template = importWalletTemplate(walletTemplateP2pkhNonHd);
650
- if (typeof template === "string") {
651
- throw new Error("Transaction template error");
652
- }
653
-
654
- const compiler = walletTemplateToCompilerBch(template);
655
- const transactionTemplate: Readonly<
656
- TransactionTemplateFixed<typeof compiler>
657
- > = { ...decoded };
658
- for (const [index, input] of decoded.inputs.entries()) {
659
- const sourceOutput = sourceOutputs[index];
660
- transactionTemplate.inputs[index] = {
661
- ...input,
662
- unlockingBytecode: {
663
- compiler,
664
- data: {
665
- keys: { privateKeys: { key: signingKey } },
666
- },
667
- valueSatoshis: sourceOutput.valueSatoshis,
668
- script: "unlock",
669
- token: sourceOutput.token,
670
- },
671
- };
672
- }
673
-
674
- const result = generateTransaction(transactionTemplate);
675
- if (!result.success) {
676
- throw result.errors;
677
- }
678
-
679
- return encodeTransaction(result.transaction);
680
- }