@witnet/sdk 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.
Files changed (149) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +103 -0
  3. package/dist/package.json +72 -0
  4. package/dist/src/bin/helpers.d.ts +91 -0
  5. package/dist/src/bin/helpers.d.ts.map +1 -0
  6. package/dist/src/bin/helpers.js +816 -0
  7. package/dist/src/index.d.ts +5 -0
  8. package/dist/src/index.d.ts.map +1 -0
  9. package/dist/src/index.js +47 -0
  10. package/dist/src/lib/crypto/account.d.ts +32 -0
  11. package/dist/src/lib/crypto/account.d.ts.map +1 -0
  12. package/dist/src/lib/crypto/account.js +106 -0
  13. package/dist/src/lib/crypto/coinbase.d.ts +10 -0
  14. package/dist/src/lib/crypto/coinbase.d.ts.map +1 -0
  15. package/dist/src/lib/crypto/coinbase.js +28 -0
  16. package/dist/src/lib/crypto/index.d.ts +8 -0
  17. package/dist/src/lib/crypto/index.d.ts.map +1 -0
  18. package/dist/src/lib/crypto/index.js +30 -0
  19. package/dist/src/lib/crypto/interfaces.d.ts +85 -0
  20. package/dist/src/lib/crypto/interfaces.d.ts.map +1 -0
  21. package/dist/src/lib/crypto/interfaces.js +3 -0
  22. package/dist/src/lib/crypto/payloads/DataRequestPayload.d.ts +55 -0
  23. package/dist/src/lib/crypto/payloads/DataRequestPayload.d.ts.map +1 -0
  24. package/dist/src/lib/crypto/payloads/DataRequestPayload.js +339 -0
  25. package/dist/src/lib/crypto/payloads/StakePayload.d.ts +28 -0
  26. package/dist/src/lib/crypto/payloads/StakePayload.d.ts.map +1 -0
  27. package/dist/src/lib/crypto/payloads/StakePayload.js +142 -0
  28. package/dist/src/lib/crypto/payloads/UnstakePayload.d.ts +36 -0
  29. package/dist/src/lib/crypto/payloads/UnstakePayload.d.ts.map +1 -0
  30. package/dist/src/lib/crypto/payloads/UnstakePayload.js +154 -0
  31. package/dist/src/lib/crypto/payloads/ValueTransferPayload.d.ts +25 -0
  32. package/dist/src/lib/crypto/payloads/ValueTransferPayload.d.ts.map +1 -0
  33. package/dist/src/lib/crypto/payloads/ValueTransferPayload.js +128 -0
  34. package/dist/src/lib/crypto/payloads.d.ts +57 -0
  35. package/dist/src/lib/crypto/payloads.d.ts.map +1 -0
  36. package/dist/src/lib/crypto/payloads.js +170 -0
  37. package/dist/src/lib/crypto/signer.d.ts +33 -0
  38. package/dist/src/lib/crypto/signer.d.ts.map +1 -0
  39. package/dist/src/lib/crypto/signer.js +194 -0
  40. package/dist/src/lib/crypto/transmitters/DataRequests.d.ts +15 -0
  41. package/dist/src/lib/crypto/transmitters/DataRequests.d.ts.map +1 -0
  42. package/dist/src/lib/crypto/transmitters/DataRequests.js +23 -0
  43. package/dist/src/lib/crypto/transmitters/StakeDeposits.d.ts +12 -0
  44. package/dist/src/lib/crypto/transmitters/StakeDeposits.d.ts.map +1 -0
  45. package/dist/src/lib/crypto/transmitters/StakeDeposits.js +17 -0
  46. package/dist/src/lib/crypto/transmitters/StakeWithdrawals.d.ts +18 -0
  47. package/dist/src/lib/crypto/transmitters/StakeWithdrawals.d.ts.map +1 -0
  48. package/dist/src/lib/crypto/transmitters/StakeWithdrawals.js +53 -0
  49. package/dist/src/lib/crypto/transmitters/ValueTransfers.d.ts +11 -0
  50. package/dist/src/lib/crypto/transmitters/ValueTransfers.d.ts.map +1 -0
  51. package/dist/src/lib/crypto/transmitters/ValueTransfers.js +16 -0
  52. package/dist/src/lib/crypto/transmitters.d.ts +47 -0
  53. package/dist/src/lib/crypto/transmitters.d.ts.map +1 -0
  54. package/dist/src/lib/crypto/transmitters.js +416 -0
  55. package/dist/src/lib/crypto/types.d.ts +161 -0
  56. package/dist/src/lib/crypto/types.d.ts.map +1 -0
  57. package/dist/src/lib/crypto/types.js +273 -0
  58. package/dist/src/lib/crypto/utils.d.ts +21 -0
  59. package/dist/src/lib/crypto/utils.d.ts.map +1 -0
  60. package/dist/src/lib/crypto/utils.js +156 -0
  61. package/dist/src/lib/crypto/wallet.d.ts +120 -0
  62. package/dist/src/lib/crypto/wallet.d.ts.map +1 -0
  63. package/dist/src/lib/crypto/wallet.js +258 -0
  64. package/dist/src/lib/index.d.ts +5 -0
  65. package/dist/src/lib/index.d.ts.map +1 -0
  66. package/dist/src/lib/index.js +44 -0
  67. package/dist/src/lib/radon/ccdr/eth.d.ts +160 -0
  68. package/dist/src/lib/radon/ccdr/eth.d.ts.map +1 -0
  69. package/dist/src/lib/radon/ccdr/eth.js +272 -0
  70. package/dist/src/lib/radon/ccdr/index.d.ts +14 -0
  71. package/dist/src/lib/radon/ccdr/index.d.ts.map +1 -0
  72. package/dist/src/lib/radon/ccdr/index.js +39 -0
  73. package/dist/src/lib/radon/ccdr/wit.d.ts +23 -0
  74. package/dist/src/lib/radon/ccdr/wit.d.ts.map +1 -0
  75. package/dist/src/lib/radon/ccdr/wit.js +35 -0
  76. package/dist/src/lib/radon/filters.d.ts +14 -0
  77. package/dist/src/lib/radon/filters.d.ts.map +1 -0
  78. package/dist/src/lib/radon/filters.js +45 -0
  79. package/dist/src/lib/radon/index.d.ts +296 -0
  80. package/dist/src/lib/radon/index.d.ts.map +1 -0
  81. package/dist/src/lib/radon/index.js +707 -0
  82. package/dist/src/lib/radon/reducers.d.ts +29 -0
  83. package/dist/src/lib/radon/reducers.d.ts.map +1 -0
  84. package/dist/src/lib/radon/reducers.js +66 -0
  85. package/dist/src/lib/radon/types.d.ts +521 -0
  86. package/dist/src/lib/radon/types.d.ts.map +1 -0
  87. package/dist/src/lib/radon/types.js +936 -0
  88. package/dist/src/lib/radon/utils.d.ts +53 -0
  89. package/dist/src/lib/radon/utils.d.ts.map +1 -0
  90. package/dist/src/lib/radon/utils.js +153 -0
  91. package/dist/src/lib/rpc/index.d.ts +3 -0
  92. package/dist/src/lib/rpc/index.d.ts.map +1 -0
  93. package/dist/src/lib/rpc/index.js +19 -0
  94. package/dist/src/lib/rpc/nodes.d.ts +40 -0
  95. package/dist/src/lib/rpc/nodes.d.ts.map +1 -0
  96. package/dist/src/lib/rpc/nodes.js +293 -0
  97. package/dist/src/lib/rpc/provider.d.ts +88 -0
  98. package/dist/src/lib/rpc/provider.d.ts.map +1 -0
  99. package/dist/src/lib/rpc/provider.js +336 -0
  100. package/dist/src/lib/rpc/reporter.d.ts +18 -0
  101. package/dist/src/lib/rpc/reporter.d.ts.map +1 -0
  102. package/dist/src/lib/rpc/reporter.js +30 -0
  103. package/dist/src/lib/rpc/types.d.ts +409 -0
  104. package/dist/src/lib/rpc/types.d.ts.map +1 -0
  105. package/dist/src/lib/rpc/types.js +81 -0
  106. package/dist/src/lib/types.d.ts +18 -0
  107. package/dist/src/lib/types.d.ts.map +1 -0
  108. package/dist/src/lib/types.js +7 -0
  109. package/dist/src/lib/utils.d.ts +13 -0
  110. package/dist/src/lib/utils.d.ts.map +1 -0
  111. package/dist/src/lib/utils.js +97 -0
  112. package/dist/witnet/assets/index.d.ts +30 -0
  113. package/dist/witnet/assets/index.d.ts.map +1 -0
  114. package/dist/witnet/assets/index.js +6 -0
  115. package/dist/witnet/assets/modals/index.d.ts +18 -0
  116. package/dist/witnet/assets/modals/index.d.ts.map +1 -0
  117. package/dist/witnet/assets/modals/index.js +21 -0
  118. package/dist/witnet/assets/modals/web3/eth.d.ts +5 -0
  119. package/dist/witnet/assets/modals/web3/eth.d.ts.map +1 -0
  120. package/dist/witnet/assets/modals/web3/eth.js +26 -0
  121. package/dist/witnet/assets/modals/web3/wit.d.ts +4 -0
  122. package/dist/witnet/assets/modals/web3/wit.d.ts.map +1 -0
  123. package/dist/witnet/assets/modals/web3/wit.js +20 -0
  124. package/dist/witnet/assets/requests.d.ts +11 -0
  125. package/dist/witnet/assets/requests.d.ts.map +1 -0
  126. package/dist/witnet/assets/requests.js +88 -0
  127. package/dist/witnet/witnet.proto.json +1325 -0
  128. package/package.json +72 -0
  129. package/src/bin/cli/history.js +31 -0
  130. package/src/bin/cli/inspect.js +359 -0
  131. package/src/bin/cli/network.js +592 -0
  132. package/src/bin/cli/nodes.js +364 -0
  133. package/src/bin/cli/radon.js +814 -0
  134. package/src/bin/cli/wallet.js +1000 -0
  135. package/src/bin/helpers.js +829 -0
  136. package/src/bin/postinstall.js +9 -0
  137. package/src/bin/toolkit.js +294 -0
  138. package/witnet/assets/_index.js +8 -0
  139. package/witnet/assets/_requests.js +25 -0
  140. package/witnet/assets/_sources.js +36 -0
  141. package/witnet/assets/_templates.js +36 -0
  142. package/witnet/assets/index.js +4 -0
  143. package/witnet/assets/modals/index.js +25 -0
  144. package/witnet/assets/modals/web3/btc.js +0 -0
  145. package/witnet/assets/modals/web3/eth.js +29 -0
  146. package/witnet/assets/modals/web3/sol.js +0 -0
  147. package/witnet/assets/modals/web3/wit.js +23 -0
  148. package/witnet/assets/requests.js +94 -0
  149. package/witnet/witnet.proto.json +1325 -0
@@ -0,0 +1,1000 @@
1
+ const qrcodes = require("qrcode-terminal")
2
+ const prompt = require("inquirer").createPromptModule()
3
+
4
+ const { utils, Witnet } = require("../../../dist/src")
5
+
6
+ const helpers = require("../helpers")
7
+ const { loadAssets } = require("./radon")
8
+
9
+ const { colors, whole_wits } = helpers
10
+
11
+ const options = {
12
+ await: {
13
+ hint: "Await any involved transaction to get eventually mined (default: false).",
14
+ },
15
+ confirmations: {
16
+ hint: "Number of epochs to await after any involved transaction gets mined (implies --await).",
17
+ param: "NUMBER",
18
+ },
19
+ fees: {
20
+ hint: "Specific transaction fees (supersedes --priority).",
21
+ param: "WITS",
22
+ },
23
+ force: {
24
+ hint: "Broadcast transaction/s without user's final confirmation.",
25
+ },
26
+ from: {
27
+ hint: "Specific wallet's address that will pay for the transaction, other than default.",
28
+ param: "WALLET_ADDRESS",
29
+ },
30
+ priority: {
31
+ hint: "Transaction priority: `stinky`, `low`, `medium`, `high`, `opulent`.",
32
+ param: "PRIORITY",
33
+ },
34
+ strategy: {
35
+ hint: "UTXOs selection strategy: `big-first`, `random`, `slim-fit`, `small-first` (default: `slim-fit`).",
36
+ param: "STRATEGY",
37
+ },
38
+ }
39
+
40
+ /// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
41
+ /// CLI SUBMODULE CONSTANTS ===========================================================================================
42
+
43
+ module.exports = {
44
+ envars: {
45
+ WITNET_SDK_PROVIDER_URL: "=> Wit/Oracle RPC provider(s) to connect to, if no otherwise specified.",
46
+ WITNET_SDK_WALLET_MASTER_KEY: "=> Wallet's master key in XPRV format, as exported from either a node, Sheikah or myWitWallet.",
47
+ },
48
+ flags: {
49
+ gap: {
50
+ hint: "Max indexing gap when searching for wallet accounts (default: 10).",
51
+ param: "NUMBER",
52
+ },
53
+ provider: {
54
+ hint: "Public Wit/Oracle JSON-RPC provider, other than default.",
55
+ param: "URL",
56
+ },
57
+ verbose: {
58
+ hint: "Outputs detailed information.",
59
+ },
60
+ },
61
+ router: {
62
+ accounts: {
63
+ hint: "List wallet's HD-accounts treasuring staked, locked or unlocked Wits.",
64
+ params: ["[WIT_ADDRESSES ...]"],
65
+ options: {
66
+ limit: {
67
+ hint: "Max number of HD-accounts to derive.",
68
+ param: "LIMIT",
69
+ },
70
+ "no-funds": {
71
+ hint: "Derive accounts even if they hold no funds.",
72
+ },
73
+ qrcode: {
74
+ hint: "Prints QR codes for all selected accounts.",
75
+ },
76
+ },
77
+ },
78
+ // "create*": {
79
+ // hint: "Create some random master key.",
80
+ // options: {
81
+ // vanity: {
82
+ // hint: "Vanity prefix of the resulting public key hash address (e.g. `herrer0`)",
83
+ // param: "BECH32_PREFIX",
84
+ // },
85
+ // }
86
+ // },
87
+ coinbase: {
88
+ hint: "List withdrawers delegating stake into the coinbase address.",
89
+ options: {
90
+ authorize: {
91
+ hint: "Generate stake authorization code for the specified withdrawer address.",
92
+ param: "WIT_ADDRESS",
93
+ },
94
+ "node-master-key": {
95
+ hint: "Node's master key other than the one set up in environment.",
96
+ param: "XPRV",
97
+ },
98
+ },
99
+ },
100
+ decipher: {
101
+ hint: "Decipher some master key as exported from myWitWallet.",
102
+ },
103
+ delegatees: {
104
+ hint: "List validators treasuring delegated stake from any of the wallet's accounts.",
105
+ },
106
+ notarize: {
107
+ hint: "Ask the Wit/Oracle to notarize and forever store the resolution to some Radon asset.",
108
+ params: ["RAD_BYTECODE | RAD_HASH | RADON_ASSET", "[RADON_ARGS]"],
109
+ options: {
110
+ ...options,
111
+ fees: {
112
+ hint: "Specific unitary reward for every involved validator (supersedes --priority).",
113
+ param: "WITS",
114
+ },
115
+ module: {
116
+ hint: "NPM package where to search for Radon assets.",
117
+ param: "NPM_PACKAGE",
118
+ },
119
+ witnesses: {
120
+ hint: "Number of witnesses in the Witnet network required to attend the oracle query (default: 3).",
121
+ param: "NUMBER",
122
+ },
123
+ },
124
+ },
125
+ provider: {
126
+ hint: "Show the underlying Wit/Oracle RPC provider being used.",
127
+ },
128
+ stake: {
129
+ hint: "Stake specified amount of Wits by using some given authorization code.",
130
+ params: "AUTH_CODE",
131
+ options: {
132
+ ...options,
133
+ value: {
134
+ hint: "Amount in Wits to stake into the validator that signed the authorization (min: 10 KWits).",
135
+ param: "WITS | `all`",
136
+ },
137
+ withdrawer: {
138
+ hint: "Wallet's address with rights to eventually withdraw the staked deposit, plus benefits.",
139
+ param: "WALLET_ADDRESS",
140
+ },
141
+ },
142
+ },
143
+ transfer: {
144
+ hint: "Transfer specified amount of Wits to given address.",
145
+ options: {
146
+ ...options,
147
+ into: {
148
+ hint: "Recipient address.",
149
+ param: "WIT_ADDRESS",
150
+ },
151
+ value: {
152
+ hint: "Amount in Wits to be transfered (e.g. `0.5` Wits).",
153
+ param: "WITS | `all`",
154
+ },
155
+ },
156
+ },
157
+ utxos: {
158
+ hint: "List currently available UTXOs on wallet's specified address, or on all funded accounts otherwise.",
159
+ options: {
160
+ ...options,
161
+ into: {
162
+ hint: "Alternative wallet address where to JOIN or SPLIT the selected UTXOs, other than default.",
163
+ param: "WALLET_ADDRESS",
164
+ },
165
+ join: { hint: "Join selected UTXOs together into a single UTXO (requires --value)." },
166
+ splits: {
167
+ hint: "Number of UTXOs to split the target balance into (max: 50; requires --value).",
168
+ param: "NUMBER",
169
+ },
170
+ value: {
171
+ hint: "Amount in Wits to be either joined or split apart.",
172
+ param: "WITS | `all`",
173
+ },
174
+ },
175
+ },
176
+ withdraw: {
177
+ hint: "Withdraw specified amount of staked Wits from some given delegatee.",
178
+ options: {
179
+ await: options.await,
180
+ confirmations: options.confirmations,
181
+ force: options.force,
182
+ from: {
183
+ hint: "Validator address from whom to withdraw the specified amount.",
184
+ param: "DELEGATEE_PKH",
185
+ },
186
+ into: {
187
+ hint: "Wallet address with rights to withdraw from the delegatee (default: wallet's first account).",
188
+ param: "WALLET_ADDRESS",
189
+ },
190
+ value: {
191
+ hint: "Amount in Wits to withdraw (default: `all`).",
192
+ param: "WITS | `all`",
193
+ },
194
+ },
195
+ },
196
+ },
197
+ subcommands: {
198
+ accounts, coinbase, decipher, delegatees: validators, notarize: resolve, provider, stake, transfer, withdraw: unstake, utxos,
199
+ },
200
+ }
201
+
202
+ /// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
203
+ /// CLI SUBMODULE COMMANDS ============================================================================================
204
+
205
+ async function accounts (options = {}, args = []) {
206
+ const { verbose } = options
207
+
208
+ let wallet
209
+ if (args.length === 0) {
210
+ wallet = await _loadWallet({
211
+ ...options,
212
+ limit: options?.limit || (options["no-funds"] && 10),
213
+ "no-funds": options["no-funds"],
214
+ })
215
+ } else {
216
+ wallet = await _loadWallet({ provider: options?.provider, limit: 1 })
217
+ args.forEach(pkh => {
218
+ if (!wallet.getSigner(pkh)) {
219
+ throw Error(`Input address ${pkh} doesn't belong to the wallet`)
220
+ }
221
+ })
222
+ }
223
+
224
+ if (options?.qrcode) {
225
+ let addrs = []
226
+ if (args.length > 0) {
227
+ addrs = wallet.accounts.filter(account => args.includes(account.pkh))
228
+ } else {
229
+ addrs = wallet.accounts
230
+ }
231
+ addrs.forEach(account => {
232
+ qrcodes.generate(account.pkh)
233
+ console.info(`Wallet account #${account.index + 1}: ${colors.lmagenta(account.pkh)}\n`)
234
+ })
235
+ return
236
+ }
237
+
238
+ const coinbaseWithdrawers = await wallet.coinbase.getWithdrawers()
239
+ const coinbaseBalance = await wallet.coinbase.getBalance()
240
+ const coinbaseColor = utils.totalCoins(coinbaseBalance).pedros > 0n ? colors.mred : (coinbaseWithdrawers.length > 0 ? colors.mcyan : colors.cyan)
241
+ const coinbase = coinbaseWithdrawers.length > 0 || utils.totalCoins(coinbaseBalance).pedros > 0n || utils.totalCoins(await wallet.getBalance()).pedros === 0n
242
+
243
+ const records = []
244
+
245
+ if (coinbase) {
246
+ const coinbaseUtxos = await wallet.coinbase.getUtxos()
247
+ records.push([0, coinbaseColor(wallet.coinbase.pkh), coinbaseUtxos.length, coinbaseBalance])
248
+ }
249
+ records.push(
250
+ ...await Promise.all(
251
+ wallet.accounts.map(async account => {
252
+ const balance = await account.getBalance()
253
+ const utxos = await account.getUtxos()
254
+ return [
255
+ account.index + 1,
256
+ balance.unlocked > 0 ? colors.mmagenta(account.pkh) : colors.magenta(account.pkh),
257
+ utxos.length,
258
+ balance,
259
+ ]
260
+ }),
261
+ )
262
+ )
263
+
264
+ let unlocked = 0n
265
+ helpers.traceTable(
266
+ records.map(([index, pkh, count, balance]) => {
267
+ unlocked += balance.unlocked
268
+ return [
269
+ index,
270
+ pkh,
271
+ count,
272
+ ...(verbose
273
+ ? [
274
+ Witnet.Coins.fromNanowits(balance.locked).wits.toFixed(2),
275
+ Witnet.Coins.fromNanowits(balance.staked).wits.toFixed(2),
276
+ Witnet.Coins.fromNanowits(balance.unlocked).wits.toFixed(2),
277
+ utils.totalCoins(balance).wits.toFixed(2),
278
+ ]
279
+ : [
280
+ Witnet.Coins.fromNanowits(balance.unlocked).wits.toFixed(2),
281
+ ]
282
+ ),
283
+ ]
284
+ }), {
285
+ headlines: [
286
+ "INDEX", `:WALLET ${wallet.network.toUpperCase()} ACCOUNTS`,
287
+ "# UTXOs",
288
+ ...(verbose
289
+ ? ["Locked ($WIT)", "Staked ($WIT)", "Available ($WIT)", "BALANCE ($WIT)"]
290
+ : ["Available ($WIT)"]
291
+ ),
292
+ ],
293
+ humanizers: [
294
+ helpers.commas,,
295
+ helpers.commas, helpers.commas, helpers.commas, helpers.commas, helpers.commas,
296
+ ],
297
+ colors: [
298
+ ,,
299
+ ...(verbose
300
+ ? [colors.white, colors.gray, colors.yellow, colors.myellow, colors.lyellow]
301
+ : [colors.white, colors.myellow]
302
+ ),
303
+ ],
304
+ maxColumnWidth: 48,
305
+ }
306
+ )
307
+ console.info(`^ Available balance: ${colors.lyellow(whole_wits(unlocked, 2))}`)
308
+ }
309
+
310
+ async function coinbase (options = {}) {
311
+ const masterWallet = await _loadWallet({ ...options })
312
+ let wallet
313
+ if (options["node-master-key"]) {
314
+ utils.parseXprv(options["node-master-key"])
315
+ wallet = await _loadWallet({ provider: options?.provider, limit: 1, xprv: options["node-master-key"] })
316
+ } else {
317
+ wallet = masterWallet
318
+ }
319
+
320
+ const coinbaseColor = utils.totalCoins(await wallet.coinbase.getBalance()) > 0 ? colors.mred : colors.lcyan
321
+ console.info(`> ${options["node-master-key"] ? "Coinbase " : "Wallet's coinbase"} address: ${coinbaseColor(wallet.coinbase.pkh)}`)
322
+
323
+ if (options?.authorize) {
324
+ const withdrawer = options.authorize
325
+ const authcode = wallet.coinbase.authorizeStake(withdrawer)
326
+ qrcodes.generate(authcode)
327
+ console.info(`${colors.white(authcode)}`)
328
+ console.info("^ Withdrawer address:", colors.mmagenta(withdrawer))
329
+ } else {
330
+ const records = await wallet.coinbase.getWithdrawers({ by: Witnet.StakesOrderBy.Coins, reverse: true })
331
+ if (records.length > 0) {
332
+ const { verbose } = options
333
+ let staked = 0
334
+ helpers.traceTable(
335
+ records.map((record, index) => {
336
+ staked += record.value.coins
337
+ const withdrawer = (record.key.withdrawer === wallet.coinbase.pkh || record.key.withdrawer === masterWallet.coinbase.PublicKeyHash
338
+ ? (record.value.epochs.witnessing > record.value.nonce || record.value.epochs.mining > record.value.nonce
339
+ ? colors.mred(record.key.withdrawer)
340
+ : colors.red(record.key.withdrawer)
341
+ )
342
+ : (record.value.epochs.witnessing > record.value.nonce || record.value.epochs.mining > record.value.nonce
343
+ ? (masterWallet.getSigner(record.key.withdrawer) ? colors.mgreen(record.key.withdrawer) : colors.mmagenta(record.key.withdrawer))
344
+ : (masterWallet.getSigner(record.key.withdrawer) ? colors.green(record.key.withdrawer) : colors.magenta(record.key.withdrawer))
345
+ )
346
+ )
347
+ const nonce = (record.value.epochs.witnessing > record.value.nonce || record.value.epochs.mining > record.value.nonce
348
+ ? record.value.nonce
349
+ : colors.gray(record.value.nonce || "")
350
+ )
351
+ return [
352
+ index + 1,
353
+ withdrawer,
354
+ nonce,
355
+ ...(verbose
356
+ ? [record.value.epochs.witnessing || "", record.value.epochs.mining || ""]
357
+ : []
358
+ ),
359
+ colors.yellow(Witnet.Coins.fromNanowits(record.value.coins).wits),
360
+ ]
361
+ }), {
362
+ headlines: [
363
+ "RANK",
364
+ "STAKE WITHDRAWERS",
365
+ ...(verbose
366
+ ? ["Nonce", "LW_Epoch", "LM_Epoch"]
367
+ : ["Nonce"]
368
+ ),
369
+ "STAKED ($WIT)",
370
+ ],
371
+ humanizers: [
372
+ ,, ...(verbose
373
+ ? [helpers.commas, helpers.commas, helpers.commas]
374
+ : [helpers.commas]
375
+ ),
376
+ helpers.commas,
377
+ ],
378
+ colors: [
379
+ ,,, ...(verbose
380
+ ? [colors.magenta, colors.cyan, colors.myellow]
381
+ : [colors.myellow]
382
+ ),
383
+ ],
384
+ }
385
+ )
386
+ console.info(`^ Total stake: ${colors.lyellow(whole_wits(staked, 2))}`)
387
+ } else {
388
+ console.info("> Holds no delegated stake.")
389
+ }
390
+ }
391
+ }
392
+
393
+ async function decipher () {
394
+ const user = await prompt([
395
+ {
396
+ message: "Enter XPRV:",
397
+ name: "xprv",
398
+ }, {
399
+ type: "password",
400
+ mask: "*",
401
+ message: "Enter password:",
402
+ name: "passwd",
403
+ },
404
+ ])
405
+ console.info(utils.decipherXprv(user.xprv, user.passwd))
406
+ }
407
+
408
+ async function provider (options = {}) {
409
+ const wallet = await _loadWallet({ unlocked: true, limit: 1, ...options })
410
+ wallet.provider.endpoints.forEach(url => {
411
+ console.info(helpers.colors.colors.magenta(url))
412
+ })
413
+ }
414
+
415
+ async function resolve (options = {}, [pattern, ...args]) {
416
+ const wallet = await _loadWallet({ ...options })
417
+ const ledger = (
418
+ options?.from
419
+ ? (options.from === wallet.coinbase.pkh ? wallet.coinbase : wallet.getAccount(options.from))
420
+ : wallet
421
+ )
422
+ if (!ledger) {
423
+ throw Error("--from address not found in wallet")
424
+ }
425
+ const request = await _loadRadonRequest({ ...options, pattern, args })
426
+ await helpers.traceTransaction(
427
+ Witnet.DataRequests.from(ledger, request), {
428
+ headline: "DATA REQUEST TRANSACTION",
429
+ color: colors.bgreen,
430
+ ...await _loadTransactionParams({ ...options }),
431
+ }
432
+ )
433
+ }
434
+
435
+ async function stake (options = {}, [authorization]) {
436
+ if (!authorization) {
437
+ throw Error("No authorization code was provided")
438
+ } else if (!options?.value) {
439
+ throw Error("No --value was specified")
440
+ } else if (!options?.withdrawer) {
441
+ throw Error("No --withdrawer was specified")
442
+ }
443
+
444
+ const wallet = await _loadWallet({ ...options })
445
+
446
+ // determine ledger and available funds
447
+ let available = 0; let ledger
448
+ if (options?.from) {
449
+ ledger = options.from === wallet.coinbase.pkh ? wallet.coinbase : wallet.getAccount(options.from)
450
+ if (ledger) available = (await ledger.getBalance()).unlocked
451
+ } else {
452
+ ledger = wallet
453
+ available = (await wallet.getBalance()).unlocked + (await wallet.coinbase.getBalance()).unlocked
454
+ }
455
+ if (!ledger) {
456
+ throw Error(`--from address ${options?.from} doesn't belong to the wallet`)
457
+ }
458
+
459
+ // validate withdrawer address
460
+ const withdrawer = Witnet.PublicKeyHash.fromBech32(options?.withdrawer).toBech32(wallet.network)
461
+ if (!wallet.getAccount(withdrawer) && withdrawer !== wallet.coinbase.pkh && !options?.force) {
462
+ const user = await prompt([{
463
+ message: `Withdrawer ${withdrawer} doesn't belong to the wallet. Proceed anyway?`,
464
+ name: "continue",
465
+ type: "confirm",
466
+ default: false,
467
+ }])
468
+ if (!user.continue) {
469
+ throw Error(`--withdrawer address ${withdrawer} not found in wallet`)
470
+ }
471
+ }
472
+
473
+ // determine stake value
474
+ const params = await _loadTransactionParams({ ...options })
475
+ const coins = params?.value === "all" ? Witnet.Coins.fromPedros(available - params.fees.pedros) : Witnet.Coins.fromWits(params?.value)
476
+ if (available < coins.pedros) {
477
+ throw Error(`Insufficient funds ${options?.from ? `on address ${options.from}.` : "on wallet."}`)
478
+ } else if (params?.fees && coins.pedros <= params.fees.pedros) {
479
+ throw Error(`Fees equal or greater than value: ${params.fees.pedros} >= ${coins.pedros}`)
480
+ }
481
+
482
+ // todo: validate withdrawer matches delegatee's withdrawer
483
+
484
+ // deposit stake
485
+ await helpers.traceTransaction(
486
+ Witnet.StakeDeposits.from(ledger), {
487
+ headline: "STAKE DEPOSIT TRANSACTION",
488
+ color: colors.bcyan,
489
+ ...options,
490
+ authorization,
491
+ value: coins,
492
+ withdrawer,
493
+ }
494
+ )
495
+ }
496
+
497
+ async function transfer (options = {}) {
498
+ if (!options?.value) {
499
+ throw Error("No --value was specified")
500
+ }
501
+
502
+ const wallet = await _loadWallet({ ...options })
503
+
504
+ // determine ledger and available funds
505
+ let available = 0n;
506
+ let ledger
507
+ if (options?.from) {
508
+ ledger = options.from === wallet.coinbase.pkh ? wallet.coinbase : wallet.getAccount(options.from)
509
+ } else {
510
+ ledger = wallet
511
+ }
512
+ if (!ledger) {
513
+ throw Error(`--from address ${options?.from} doesn't belong to the wallet`)
514
+ } else {
515
+ const balance = await ledger.getBalance()
516
+ available = balance.unlocked
517
+ }
518
+
519
+ // validate recipient address
520
+ if (!options?.into) {
521
+ throw Error("--into address must be specified")
522
+ }
523
+ const into = Witnet.PublicKeyHash.fromBech32(options?.into).toBech32(wallet.network)
524
+
525
+ // determine transfer params
526
+ const params = await _loadTransactionParams({ ...options })
527
+ const coins = params?.value === "all" ? Witnet.Coins.fromPedros(available - params.fees.pedros) : Witnet.Coins.fromWits(params?.value)
528
+ if (available < coins.pedros) {
529
+ throw Error(`Insufficient funds ${options?.from ? `on address ${options.from}.` : "on wallet."}`)
530
+ } else if (params?.fees && coins.pedros <= params.fees.pedros) {
531
+ throw Error(`Fees equal or greater than value: ${params.fees.pedros} >= ${coins.pedros}`)
532
+ }
533
+
534
+ // transfer value
535
+ await helpers.traceTransaction(
536
+ Witnet.ValueTransfers.from(ledger), {
537
+ headline: "VALUE TRANSFER TRANSACTION",
538
+ color: colors.bblue,
539
+ ...params,
540
+ recipients: [[into, coins]],
541
+ }
542
+ )
543
+ }
544
+
545
+ async function unstake (options = {}) {
546
+
547
+ // load wallet:
548
+ const wallet = await _loadWallet({ ...options })
549
+
550
+ // determine validator address:
551
+ let validator
552
+ if (options?.from) {
553
+ validator = Witnet.PublicKeyHash.fromBech32(options?.from).toBech32(wallet.network)
554
+
555
+ } else {
556
+ const delegatees =
557
+ (await wallet.getDelegatees({ by: Witnet.StakesOrderBy.Coins, reverse: true }, false))
558
+ .filter(entry => !options?.into || entry.key.withdrawer === options?.into)
559
+ if (delegatees.length === 0) throw new Error(`No delegatees to withdraw from.`);
560
+ else if (delegatees.length === 1) validator = delegatees[0].key.validator;
561
+ else {
562
+ const choices = delegatees
563
+ .map(entry => `${colors.mcyan(entry.key.validator)}`)
564
+ .filter((pkh, index, array) => index === array.indexOf(pkh))
565
+ const user = await prompt([{
566
+ choices,
567
+ message: "Validator address ?",
568
+ name: "key",
569
+ type: "list",
570
+ pageSize: 24,
571
+ }]);
572
+ validator = helpers.colorstrip(user.key.split(' ')[0])
573
+ }
574
+ }
575
+
576
+ // determine withdrawer address:
577
+ let withdrawer
578
+ if (options?.into) {
579
+ withdrawer = Witnet.PublicKeyHash.fromBech32(options?.into).toBech32(wallet.network)
580
+
581
+ } else {
582
+ const stakes = (await wallet.provider.stakes({ filter: { validator }})).filter(entry => wallet.getSigner(entry.key.withdrawer) !== undefined);
583
+ if (stakes.length === 0) throw new Error(`Nothing to withdraw from validator ${validator}.`);
584
+ else if (stakes.length === 1) withdrawer = stakes[0].key.withdrawer;
585
+ else {
586
+ const choices = stakes.map(entry => `${colors.mmagenta(entry.key.withdrawer)} [${colors.yellow(Witnet.Coins.fromPedros(entry.value.coins).toString(2))}]`);
587
+ const user = await prompt([{
588
+ choices,
589
+ message: "Withdrawer address ?",
590
+ name: "key",
591
+ type: "list",
592
+ pageSize: 24,
593
+ }]);
594
+ withdrawer = helpers.colorstrip(user.key.split(' ')[0])
595
+ }
596
+ }
597
+
598
+ // validate withdrawer address
599
+ const ledger = await wallet.getSigner(withdrawer)
600
+ if (!ledger) {
601
+ throw Error(`--into address ${withdrawer} doesn't belong to the wallet`)
602
+ }
603
+
604
+ // valite delegatee address:
605
+ const delegatee = (await ledger.getDelegatees()).find(stake =>
606
+ stake.key.validator === validator && stake.key.withdrawer === withdrawer
607
+ )
608
+ if (!delegatee) {
609
+ throw Error(`Nothing to withdraw from ${validator} into ${withdrawer}`)
610
+ }
611
+ const available = BigInt(delegatee.value.coins)
612
+
613
+ // determine withdrawal value:
614
+ const params = await _loadTransactionParams({ ...options, fees: 0n })
615
+
616
+ const value = (params?.value || `all`) === "all"
617
+ ? Witnet.Coins.fromPedros(available - params.fees.pedros)
618
+ : Witnet.Coins.fromWits(params?.value)
619
+
620
+ // validate withdrawal amount:
621
+ if (available < value.pedros + params?.fees.pedros) {
622
+ throw Error(`Cannot withdraw that much: ${value.pedros} > ${available}`)
623
+ } else if (params?.fees && value.pedros <= params.fees.pedros) {
624
+ throw Error(`Fees equal or greater than value: ${params.fees.pedros} >= ${value.pedros}`)
625
+ }
626
+
627
+ // withdraw deposit from validator into withdrawer:
628
+ await helpers.traceTransaction(
629
+ Witnet.StakeWithdrawals.from(ledger), {
630
+ headline: "STAKE WITHDRAWAL TRANSACTION",
631
+ ...params,
632
+ validator,
633
+ value,
634
+ }
635
+ )
636
+ }
637
+
638
+ async function utxos (options = {}) {
639
+ const wallet = await _loadWallet({ ...options })
640
+
641
+ // determine ledger and available funds
642
+ let ledger
643
+ let available = 0n;
644
+ if (options?.from) {
645
+ ledger = options.from === wallet.coinbase.pkh ? wallet.coinbase : wallet.getAccount(options.from)
646
+ if (ledger) available = (await ledger.getBalance()).unlocked;
647
+ } else {
648
+ ledger = wallet
649
+ available = (await wallet.getBalance()).unlocked + (await wallet.coinbase.getBalance()).unlocked
650
+ }
651
+ if (!ledger) {
652
+ throw Error(`Address ${options?.from} doesn't belong to the wallet`)
653
+ }
654
+
655
+ // determine into address
656
+ let into = options?.into
657
+ if (into) {
658
+ if (into !== options?.from && !wallet.getAccount(into) && into !== wallet.coinbase.pkh && !options?.force) {
659
+ const user = await prompt([{
660
+ message: `Recipient address ${into} doesn't belong to the wallet. Proceed anyway?`,
661
+ name: "continue",
662
+ type: "input",
663
+ }])
664
+ if (!user.continue.toLowerCase().startsWith("y")) {
665
+ throw Error(`--into address ${into} not found in wallet`)
666
+ }
667
+ }
668
+ } else {
669
+ into = wallet.pkh
670
+ }
671
+
672
+ // determine if --value is required
673
+ if ((options?.join || options?.split) && !options?.value) {
674
+ throw Error("--value must be specified on JOIN and SPLITS operations.")
675
+ }
676
+
677
+ // extract transaction params
678
+ const params = await _loadTransactionParams({
679
+ ...options,
680
+ force: options?.force || (!options?.join && !options?.splits),
681
+ })
682
+
683
+ // select utxos of either the from account (if specified) or from all funded accounts in the wallet (including the coinbase)
684
+ let value = params?.value === "all"
685
+ ? Witnet.Coins.fromPedros(available - params.fees.pedros)
686
+ : (params?.value ? Witnet.Coins.fromWits(params?.value) : Witnet.Coins.fromPedros(available))
687
+ if (available < value.pedros) {
688
+ throw Error(`Insufficient funds ${options?.from ? `on address ${options.from}.` : "on wallet."}`)
689
+ } else if (params?.fees && value.pedros <= params.fees.pedros) {
690
+ throw Error(`Fees equal or greater than value: ${params.fees.pedros} >= ${value.pedros}`)
691
+ }
692
+ const utxos = await ledger.selectUtxos({ value })
693
+ const covered = utxos.map(utxo => BigInt(utxo.value))?.reduce((prev, curr) => prev + curr, 0n) || 0n
694
+ if (value && covered < value.pedros) {
695
+ throw Error(`Insufficient unlocked UTXOs in ${options?.from ? `wallet account ${ledger.pkh}` : "wallet"}`)
696
+ }
697
+
698
+ // only if at least one utxo is selected, proceed with report and other operations, if any
699
+ if (utxos.length > 0) {
700
+ if (options?.verbose || (!options?.join && !options?.splits)) {
701
+ helpers.traceTable(
702
+ utxos.map((utxo, index) => [
703
+ index + 1,
704
+ utxo.signer === wallet.coinbase.pkh ? colors.mcyan(utxo.signer) : colors.mmagenta(utxo.signer),
705
+ utxo?.internal ? colors.green(utxo.output_pointer) : colors.mgreen(utxo.output_pointer),
706
+ utxo.value,
707
+ ]), {
708
+ headlines: ["INDEX", `WALLET ${wallet.network.toUpperCase()} ADDRESSES`, ":Unlocked UTXO pointers", "UTXO value ($pedros)"],
709
+ humanizers: [helpers.commas,,, helpers.commas],
710
+ colors: [,,, colors.myellow],
711
+ }
712
+ )
713
+ console.info(`^ Available balance: ${colors.lyellow(whole_wits(covered, 2))}`)
714
+ }
715
+
716
+ const valueTransfer = Witnet.ValueTransfers.from(ledger)
717
+
718
+ if (options?.join) {
719
+ const recipients = [[
720
+ // if a split is expected, join utxos into selected account or wallet
721
+ options?.splits ? ledger.pkh : into,
722
+ value,
723
+ ]]
724
+ await helpers.traceTransaction(valueTransfer, {
725
+ headline: `JOINING UTXOs: ${utxos.length} -> ${coins.pedros < covered ? 2 : 1}`,
726
+ ...params,
727
+ await: params?.await || options?.splits !== undefined,
728
+ recipients,
729
+ })
730
+ }
731
+ if (options?.splits) {
732
+ const recipients = []
733
+ const splits = parseInt(options.splits)
734
+ if (splits > 50) {
735
+ throw Error("Not possible to split into more than 50 UTXOs")
736
+ }
737
+ value = Witnet.Coins.fromPedros(BigInt(Math.floor(value.pedros / splits)))
738
+ recipients.push(...Array(splits).fill([into, coins]))
739
+ await helpers.traceTransaction(
740
+ valueTransfer, {
741
+ headline: `SPLITTING UTXOs: ${utxos.length} -> ${coins.pedros * splits < covered ? splits + 1 : splits}`,
742
+ ...params,
743
+ recipients,
744
+ reload: options?.join,
745
+ })
746
+ }
747
+ } else {
748
+ console.info("> No available UTXOs at the moment.")
749
+ }
750
+ }
751
+
752
+ async function validators (options = {}) {
753
+ const { verbose } = options
754
+ const wallet = await _loadWallet({ ...options })
755
+ const order = { by: Witnet.StakesOrderBy.Coins, reverse: true }
756
+
757
+ const coinbaseBalance = await wallet.coinbase.getBalance()
758
+ const coinbase = coinbaseBalance.staked > 0n
759
+
760
+ const records = await wallet.getDelegatees(order, true)
761
+ if (records.length > 0) {
762
+ let staked = 0n
763
+ helpers.traceTable(
764
+ records.map(record => {
765
+ staked += BigInt(record.value.coins)
766
+ return [
767
+ record.key.withdrawer === wallet.coinbase.pkh
768
+ ? colors.mred(record.key.withdrawer)
769
+ : (record.key.validator !== "" ? colors.mmagenta(record.key.withdrawer) : colors.magenta(record.key.withdrawer)),
770
+ ...(record.value.epochs.witnessing > record.value.nonce || record.value.epochs.mining > record.value.nonce
771
+ ? [colors.mcyan(record.key.validator), record.value.nonce]
772
+ : [colors.cyan(record.key.validator), colors.gray(record.value.nonce || "")]
773
+ ),
774
+ ...(verbose
775
+ ? [record.value.epochs.witnessing || "", record.value.epochs.mining || ""]
776
+ : []
777
+ ),
778
+ colors.yellow(record.value.coins),
779
+ ]
780
+ }), {
781
+ headlines: [
782
+ // "INDEX",
783
+ coinbase ? "WALLET COINBASE" : `WALLET ${wallet.network.toUpperCase()} ACCOUNTS`,
784
+ "STAKE DELEGATEES",
785
+ ...(verbose
786
+ ? ["Nonce", "LW_Epoch", "LM_Epoch"]
787
+ : ["Nonce"]
788
+ ),
789
+ "STAKED ($pedros)",
790
+ ],
791
+ humanizers: [
792
+ ,, ...(verbose
793
+ ? [helpers.commas, helpers.commas, helpers.commas]
794
+ : [helpers.commas]
795
+ ),
796
+ helpers.commas,
797
+ ],
798
+ colors: [
799
+ ,,, ...(verbose
800
+ ? [colors.magenta, colors.cyan, colors.myellow]
801
+ : [colors.myellow]
802
+ ),
803
+ ],
804
+ }
805
+ )
806
+ console.info(`^ Total deposits: ${colors.lyellow(whole_wits(staked, 2))}`)
807
+ } else {
808
+ console.info("> No delegatees found.")
809
+ }
810
+ }
811
+
812
+ /// ===================================================================================================================
813
+ /// --- Internal functions --------------------------------------------------------------------------------------------
814
+
815
+ async function _loadRadonRequest (options = {}) {
816
+ const args = options?.args || []
817
+ // TODO:
818
+ // if (options?.pattern && typeof options.pattern === 'string' && utils.isHexString(options.pattern)) {
819
+ // if (utils.isHexStringOfLength(options.pattern, 32)) {
820
+ // throw `Searching RADON_BYTECODE by RAD_HASH not yet supported.`
821
+ // } else try {
822
+ // return Witnet.RadonRequest.fromHexString(pattern)
823
+ // } catch {
824
+ // throw `Invalid RADON_BYTECODE.`
825
+ // }
826
+ // }
827
+
828
+ // load Radon assets from environment
829
+ let assets = utils.searchRadonAssets(
830
+ {
831
+ assets: loadAssets(options),
832
+ pattern: options?.pattern,
833
+ },
834
+ (key, pattern) => key.toLowerCase().indexOf(pattern.toLowerCase()) >= 0
835
+ )
836
+
837
+ if (args.length > 0) {
838
+ // ignore RadonRequests if args were passed from the CLI
839
+ assets = assets.filter(([, artifact]) => !(artifact instanceof Witnet.Radon.RadonRequest))
840
+ }
841
+
842
+ // sort Radon assets alphabetically
843
+ assets = assets.sort((a, b) => {
844
+ if (a[0] < b[0]) return -1
845
+ else if (a[0] > b[0]) return 1
846
+ else return 0
847
+ })
848
+
849
+ let artifact, key
850
+ if (Object.keys(assets).length === 0) {
851
+ if (options?.pattern) {
852
+ throw Error(`No Radon assets named after "${options.pattern}"`)
853
+ } else {
854
+ throw Error("No Radon assets declared yet")
855
+ }
856
+ } else if (Object.keys(assets).length > 1) {
857
+ const user = await prompt([{
858
+ choices: assets.map(([key]) => key),
859
+ message: "Please, select a Radon asset:",
860
+ name: "key",
861
+ type: "list",
862
+ pageSize: 24,
863
+ }]);
864
+ [key, artifact] = assets.find(([key]) => key === user.key)
865
+ } else {
866
+ [key, artifact] = Object.values(assets)[0]
867
+ }
868
+
869
+ if (!(artifact instanceof Witnet.Radon.RadonRequest)) {
870
+ let templateArgs = []
871
+ if (args.length === 0 && artifact?.samples) {
872
+ const sample = await prompt([{
873
+ choices: Object.keys(artifact.samples),
874
+ message: "Select pre-settled Radon args: ",
875
+ name: "key",
876
+ type: "list",
877
+ }])
878
+ templateArgs = artifact.samples[sample.key]
879
+ } else if (args.length === 1 && artifact?.samples) {
880
+ const sample = Object.keys(artifact.samples).find(sample => sample.toLowerCase() === args[0].toLowerCase())
881
+ if (sample) templateArgs = artifact.samples[sample]
882
+ }
883
+
884
+ if (artifact instanceof Witnet.Radon.RadonRetrieval) {
885
+ if (templateArgs.length === 0) templateArgs = [...args]
886
+ if (templateArgs.length < artifact.argsCount) {
887
+ throw Error(`${key}: missing ${artifact.argsCount - templateArgs.length} out of ${artifact.argsCount} parameters`)
888
+ }
889
+ artifact = new Witnet.Radon.RadonRequest({ sources: artifact.foldArgs(templateArgs) })
890
+ } else {
891
+ if (artifact instanceof Witnet.Radon.RadonModal) {
892
+ if (templateArgs.length === 0) templateArgs = [...args]
893
+ if (templateArgs.length === 0 && templateArgs.length < artifact.argsCount + 1) {
894
+ throw Error(`${key}: missing ${artifact.argsCount + 1 - templateArgs.length} out of ${artifact.argsCount + 1} parameters.`)
895
+ }
896
+ artifact.providers = templateArgs.splice(0, 1)[0].split(";")
897
+ artifact = artifact.buildRadonRequest(templateArgs)
898
+ } else if (artifact instanceof Witnet.Radon.RadonTemplate) {
899
+ if (templateArgs.length === 0) {
900
+ templateArgs = new Array(artifact.sources.length)
901
+ artifact.sources.forEach((retrieval, index) => {
902
+ templateArgs[index] = args.splice(0, retrieval.argsCount)
903
+ if (templateArgs[index].length < retrieval.argsCount) {
904
+ throw Error(`${key}: missing ${
905
+ retrieval.argsCount - templateArgs[index].length
906
+ } out of ${
907
+ retrieval.argsCount
908
+ } expected args for template source #${index + 1}`)
909
+ }
910
+ })
911
+ }
912
+ artifact = artifact.buildRadonRequest(templateArgs)
913
+ } else {
914
+ throw Error(`${key}: unsupported Radon asset type ${artifact?.constructor.name}`)
915
+ }
916
+ }
917
+ }
918
+ return artifact
919
+ }
920
+
921
+ async function _loadTransactionParams (options = {}) {
922
+ const confirmations = options?.confirmations ? parseInt(options?.confirmations) : (options?.await ? 0 : undefined)
923
+ let fees = options?.fees ? Witnet.Coins.fromWits(options.fees) : (options?.fees === 0n ? Witnet.Coins.zero() : undefined)
924
+ const value = options?.value ? (options?.value.toLowerCase() === "all" ? "all" : options.value) : undefined
925
+ if (fees === undefined) {
926
+ if (value === "all") {
927
+ throw Error("--fees must be specified if --value is set to `all`")
928
+ }
929
+ let priority = (!options?.priority && options?.force) ? Witnet.TransactionPriority.Medium : options?.priority
930
+ if (!priority) {
931
+ const priorities = {
932
+ "< 60 seconds": Witnet.TransactionPriority.Opulent,
933
+ "< 5 minutes": Witnet.TransactionPriority.High,
934
+ "< 15 minutes": Witnet.TransactionPriority.Medium,
935
+ "< 1 hour": Witnet.TransactionPriority.Low,
936
+ "< 6 hours": Witnet.TransactionPriority.Stinky,
937
+ }
938
+ const user = await prompt([{
939
+ choices: Object.keys(priorities),
940
+ message: "Please, select time to block expectancy:",
941
+ name: "priority",
942
+ type: "list",
943
+ }])
944
+ priority = priorities[user.priority]
945
+ } else if (!Object.values(Witnet.TransactionPriority).includes(priority)) {
946
+ throw Error(`Invalid priority "${priority}"`)
947
+ }
948
+ fees = Witnet.TransactionPriority[priority.charAt(0).toUpperCase() + priority.slice(1)]
949
+ }
950
+ return {
951
+ await: options?.await,
952
+ confirmations,
953
+ fees,
954
+ from: options?.from,
955
+ force: options?.force,
956
+ value,
957
+ verbose: options?.verbose,
958
+ witnesses: options?.witnesses,
959
+ }
960
+ }
961
+
962
+ async function _loadWallet (options = {}) {
963
+ if (!process.env.WITNET_SDK_WALLET_MASTER_KEY) {
964
+ throw Error("No WITNET_SDK_WALLET_MASTER_KEY is settled in environment")
965
+ } else {
966
+ const provider = new Witnet.JsonRpcProvider(options?.provider)
967
+ const strategies = {
968
+ "small-first": Witnet.UtxoSelectionStrategy.SmallFirst,
969
+ "slim-fit": Witnet.UtxoSelectionStrategy.SlimFit,
970
+ "big-first": Witnet.UtxoSelectionStrategy.BigFirst,
971
+ random: Witnet.UtxoSelectionStrategy.Random,
972
+ }
973
+ if (options?.strategy && !strategies[options.strategy]) {
974
+ throw Error(`Unrecognised UTXO selection strategy "${options.strategy}"`)
975
+ }
976
+ const strategy = strategies[options?.strategy || "slim-fit"] || Witnet.UtxoSelectionStrategy.SlimFit
977
+ const gap = options?.gap || 10
978
+ let wallet; const xprv = options?.xprv || process.env.WITNET_SDK_WALLET_MASTER_KEY
979
+ if (xprv.length === 293) {
980
+ const user = await prompt([{ type: "password", mask: "*", message: "Enter password:", name: "passwd" }])
981
+ wallet = Witnet.Wallet.fromEncryptedXprv(xprv, user.passwd, {
982
+ gap,
983
+ provider,
984
+ strategy,
985
+ limit: options?.limit,
986
+ onlyWithFunds: !options["no-funds"],
987
+ })
988
+ } else {
989
+ wallet = Witnet.Wallet.fromXprv(xprv, {
990
+ gap,
991
+ provider,
992
+ strategy,
993
+ limit: options?.limit,
994
+ onlyWithFunds: !options["no-funds"],
995
+ })
996
+ }
997
+
998
+ return options["no-funds"] ? await wallet : await helpers.prompter(wallet)
999
+ }
1000
+ }