@argonprotocol/mainchain 1.1.0-rc.7 → 1.1.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.
@@ -60,8 +60,11 @@ __export(index_exports, {
60
60
  BitcoinLocks: () => BitcoinLocks,
61
61
  BlockWatch: () => BlockWatch,
62
62
  CohortBidder: () => CohortBidder,
63
+ CohortBidderHistory: () => CohortBidderHistory,
64
+ ExtrinsicError: () => ExtrinsicError2,
63
65
  JsonExt: () => JsonExt,
64
66
  Keyring: () => import_api.Keyring,
67
+ MICROGONS_PER_ARGON: () => MICROGONS_PER_ARGON,
65
68
  MiningBids: () => MiningBids,
66
69
  MiningRotations: () => MiningRotations,
67
70
  TxSubmitter: () => TxSubmitter,
@@ -73,6 +76,7 @@ __export(index_exports, {
73
76
  convertPermillToBigNumber: () => convertPermillToBigNumber,
74
77
  createKeyringPair: () => createKeyringPair,
75
78
  decodeAddress: () => import_util_crypto.decodeAddress,
79
+ dispatchErrorToExtrinsicError: () => dispatchErrorToExtrinsicError,
76
80
  dispatchErrorToString: () => dispatchErrorToString,
77
81
  eventDataToJson: () => eventDataToJson,
78
82
  filterUndefined: () => filterUndefined,
@@ -171,119 +175,6 @@ var WageProtector = class _WageProtector {
171
175
  }
172
176
  };
173
177
 
174
- // src/utils.ts
175
- var BN = __toESM(require("bignumber.js"), 1);
176
- var { ROUND_FLOOR } = BN;
177
- function formatArgons(x) {
178
- const isNegative = x < 0;
179
- let format = (0, BN.default)(x.toString()).abs().div(1e6).toFormat(2, ROUND_FLOOR);
180
- if (format.endsWith(".00")) {
181
- format = format.slice(0, -3);
182
- }
183
- return `${isNegative ? "-" : ""}\u20B3${format}`;
184
- }
185
- function formatPercent(x) {
186
- if (!x) return "na";
187
- return `${x.times(100).decimalPlaces(3)}%`;
188
- }
189
- function filterUndefined(obj) {
190
- return Object.fromEntries(
191
- Object.entries(obj).filter(
192
- ([_, value]) => value !== void 0 && value !== null
193
- )
194
- );
195
- }
196
- async function gettersToObject(obj) {
197
- if (obj === null || obj === void 0 || typeof obj !== "object") return obj;
198
- const keys = [];
199
- for (const key in obj) {
200
- keys.push(key);
201
- }
202
- if (Symbol.iterator in obj) {
203
- const iterableToArray = [];
204
- for (const item of obj) {
205
- iterableToArray.push(await gettersToObject(item));
206
- }
207
- return iterableToArray;
208
- }
209
- const result = {};
210
- for (const key of keys) {
211
- const descriptor = Object.getOwnPropertyDescriptor(obj, key);
212
- if (descriptor && typeof descriptor.value === "function") {
213
- continue;
214
- }
215
- const value = descriptor && descriptor.get ? descriptor.get.call(obj) : obj[key];
216
- if (typeof value === "function") continue;
217
- result[key] = await gettersToObject(value);
218
- }
219
- return result;
220
- }
221
- function convertFixedU128ToBigNumber(fixedU128) {
222
- const decimalFactor = new BN.default(10).pow(new BN.default(18));
223
- const rawValue = new BN.default(fixedU128.toString());
224
- return rawValue.div(decimalFactor);
225
- }
226
- function convertPermillToBigNumber(permill) {
227
- const decimalFactor = new BN.default(1e6);
228
- const rawValue = new BN.default(permill.toString());
229
- return rawValue.div(decimalFactor);
230
- }
231
- function eventDataToJson(event) {
232
- const obj = {};
233
- event.data.forEach((data, index) => {
234
- const name = event.data.names?.[index];
235
- obj[name ?? `${index}`] = data.toJSON();
236
- });
237
- return obj;
238
- }
239
- function dispatchErrorToString(client, error) {
240
- let message = error.toString();
241
- if (error.isModule) {
242
- const decoded = client.registry.findMetaError(error.asModule);
243
- const { docs, name, section } = decoded;
244
- message = `${section}.${name}: ${docs.join(" ")}`;
245
- }
246
- return message;
247
- }
248
- function checkForExtrinsicSuccess(events, client) {
249
- return new Promise((resolve, reject) => {
250
- for (const { event } of events) {
251
- if (client.events.system.ExtrinsicSuccess.is(event)) {
252
- resolve();
253
- } else if (client.events.system.ExtrinsicFailed.is(event)) {
254
- const [dispatchError] = event.data;
255
- let errorInfo = dispatchError.toString();
256
- if (dispatchError.isModule) {
257
- const decoded = client.registry.findMetaError(dispatchError.asModule);
258
- errorInfo = `${decoded.section}.${decoded.name}`;
259
- }
260
- reject(
261
- new Error(
262
- `${event.section}.${event.method}:: ExtrinsicFailed:: ${errorInfo}`
263
- )
264
- );
265
- }
266
- }
267
- });
268
- }
269
- var JsonExt = class {
270
- static stringify(obj, space) {
271
- return JSON.stringify(
272
- obj,
273
- (_, v) => typeof v === "bigint" ? `${v}n` : v,
274
- space
275
- );
276
- }
277
- static parse(str) {
278
- return JSON.parse(str, (_, v) => {
279
- if (typeof v === "string" && v.endsWith("n")) {
280
- return BigInt(v.slice(0, -1));
281
- }
282
- return v;
283
- });
284
- }
285
- };
286
-
287
178
  // src/TxSubmitter.ts
288
179
  function logExtrinsicResult(result) {
289
180
  if (process.env.DEBUG) {
@@ -415,13 +306,12 @@ var TxResult = class {
415
306
  }
416
307
  }
417
308
  if (encounteredError) {
418
- const error = dispatchErrorToString(this.client, encounteredError);
419
- if (batchErrorIndex) {
420
- this.reject(
421
- new Error(`Error in batch#${batchErrorIndex}: ${error.toString()}`)
422
- );
423
- }
424
- this.reject(new Error(`Transaction failed: ${error}`));
309
+ const error = dispatchErrorToExtrinsicError(
310
+ this.client,
311
+ encounteredError,
312
+ batchErrorIndex
313
+ );
314
+ this.reject(error);
425
315
  } else {
426
316
  this.inBlockResolve(status.asInBlock.toU8a());
427
317
  }
@@ -436,6 +326,147 @@ var TxResult = class {
436
326
  }
437
327
  };
438
328
 
329
+ // src/utils.ts
330
+ var BN = __toESM(require("bignumber.js"), 1);
331
+ var { ROUND_FLOOR } = BN;
332
+ var MICROGONS_PER_ARGON = 1e6;
333
+ function formatArgons(x) {
334
+ if (x === void 0 || x === null) return "na";
335
+ const isNegative = x < 0;
336
+ let format = (0, BN.default)(x.toString()).abs().div(MICROGONS_PER_ARGON).toFormat(2, ROUND_FLOOR);
337
+ if (format.endsWith(".00")) {
338
+ format = format.slice(0, -3);
339
+ }
340
+ return `${isNegative ? "-" : ""}\u20B3${format}`;
341
+ }
342
+ function formatPercent(x) {
343
+ if (!x) return "na";
344
+ return `${x.times(100).decimalPlaces(3)}%`;
345
+ }
346
+ function filterUndefined(obj) {
347
+ return Object.fromEntries(
348
+ Object.entries(obj).filter(
349
+ ([_, value]) => value !== void 0 && value !== null
350
+ )
351
+ );
352
+ }
353
+ async function gettersToObject(obj) {
354
+ if (obj === null || obj === void 0 || typeof obj !== "object") return obj;
355
+ const keys = [];
356
+ for (const key in obj) {
357
+ keys.push(key);
358
+ }
359
+ if (Symbol.iterator in obj) {
360
+ const iterableToArray = [];
361
+ for (const item of obj) {
362
+ iterableToArray.push(await gettersToObject(item));
363
+ }
364
+ return iterableToArray;
365
+ }
366
+ const result = {};
367
+ for (const key of keys) {
368
+ const descriptor = Object.getOwnPropertyDescriptor(obj, key);
369
+ if (descriptor && typeof descriptor.value === "function") {
370
+ continue;
371
+ }
372
+ const value = descriptor && descriptor.get ? descriptor.get.call(obj) : obj[key];
373
+ if (typeof value === "function") continue;
374
+ result[key] = await gettersToObject(value);
375
+ }
376
+ return result;
377
+ }
378
+ function convertFixedU128ToBigNumber(fixedU128) {
379
+ const decimalFactor = new BN.default(10).pow(new BN.default(18));
380
+ const rawValue = new BN.default(fixedU128.toString());
381
+ return rawValue.div(decimalFactor);
382
+ }
383
+ function convertPermillToBigNumber(permill) {
384
+ const decimalFactor = new BN.default(1e6);
385
+ const rawValue = new BN.default(permill.toString());
386
+ return rawValue.div(decimalFactor);
387
+ }
388
+ function eventDataToJson(event) {
389
+ const obj = {};
390
+ event.data.forEach((data, index) => {
391
+ const name = event.data.names?.[index];
392
+ obj[name ?? `${index}`] = data.toJSON();
393
+ });
394
+ return obj;
395
+ }
396
+ function dispatchErrorToString(client, error) {
397
+ let message = error.toString();
398
+ if (error.isModule) {
399
+ const decoded = client.registry.findMetaError(error.asModule);
400
+ const { docs, name, section } = decoded;
401
+ message = `${section}.${name}: ${docs.join(" ")}`;
402
+ }
403
+ return message;
404
+ }
405
+ var ExtrinsicError2 = class extends Error {
406
+ constructor(errorCode, details, batchInterruptedIndex) {
407
+ super(errorCode);
408
+ this.errorCode = errorCode;
409
+ this.details = details;
410
+ this.batchInterruptedIndex = batchInterruptedIndex;
411
+ }
412
+ toString() {
413
+ if (this.batchInterruptedIndex !== void 0) {
414
+ return `${this.errorCode} ${this.details ?? ""} (Batch interrupted at index ${this.batchInterruptedIndex})`;
415
+ }
416
+ return `${this.errorCode} ${this.details ?? ""}`;
417
+ }
418
+ };
419
+ function dispatchErrorToExtrinsicError(client, error, batchInterruptedIndex) {
420
+ if (error.isModule) {
421
+ const decoded = client.registry.findMetaError(error.asModule);
422
+ const { docs, name, section } = decoded;
423
+ return new ExtrinsicError2(
424
+ `${section}.${name}`,
425
+ docs.join(" "),
426
+ batchInterruptedIndex
427
+ );
428
+ }
429
+ return new ExtrinsicError2(error.toString(), void 0, batchInterruptedIndex);
430
+ }
431
+ function checkForExtrinsicSuccess(events, client) {
432
+ return new Promise((resolve, reject) => {
433
+ for (const { event } of events) {
434
+ if (client.events.system.ExtrinsicSuccess.is(event)) {
435
+ resolve();
436
+ } else if (client.events.system.ExtrinsicFailed.is(event)) {
437
+ const [dispatchError] = event.data;
438
+ let errorInfo = dispatchError.toString();
439
+ if (dispatchError.isModule) {
440
+ const decoded = client.registry.findMetaError(dispatchError.asModule);
441
+ errorInfo = `${decoded.section}.${decoded.name}`;
442
+ }
443
+ reject(
444
+ new Error(
445
+ `${event.section}.${event.method}:: ExtrinsicFailed:: ${errorInfo}`
446
+ )
447
+ );
448
+ }
449
+ }
450
+ });
451
+ }
452
+ var JsonExt = class {
453
+ static stringify(obj, space) {
454
+ return JSON.stringify(
455
+ obj,
456
+ (_, v) => typeof v === "bigint" ? `${v}n` : v,
457
+ space
458
+ );
459
+ }
460
+ static parse(str) {
461
+ return JSON.parse(str, (_, v) => {
462
+ if (typeof v === "string" && v.endsWith("n")) {
463
+ return BigInt(v.slice(0, -1));
464
+ }
465
+ return v;
466
+ });
467
+ }
468
+ };
469
+
439
470
  // src/AccountRegistry.ts
440
471
  var AccountRegistry = class _AccountRegistry {
441
472
  namedAccounts = /* @__PURE__ */ new Map();
@@ -848,6 +879,14 @@ var Accountset = class {
848
879
  );
849
880
  }
850
881
  }
882
+ async submitterBalance(blockHash) {
883
+ const client = await this.client;
884
+ const api = blockHash ? await client.at(blockHash) : client;
885
+ const accountData = await api.query.system.account(
886
+ this.txSubmitterPair.address
887
+ );
888
+ return accountData.data.free.toBigInt();
889
+ }
851
890
  async balance(blockHash) {
852
891
  const client = await this.client;
853
892
  const api = blockHash ? await client.at(blockHash) : client;
@@ -1110,18 +1149,18 @@ var Accountset = class {
1110
1149
  return new TxSubmitter(client, tx, this.txSubmitterPair);
1111
1150
  }
1112
1151
  /**
1113
- * Create a mining bid. This will create a bid for each account in the given range from the seed account as funding.
1152
+ * Create but don't submit a mining bid transaction.
1153
+ * @param options
1114
1154
  */
1115
- async createMiningBids(options) {
1116
- const accounts = this.getAccountsInRange(options.subaccountRange);
1155
+ async createMiningBidTx(options) {
1117
1156
  const client = await this.client;
1118
- let tip = options.tip ?? 0n;
1157
+ const { bidAmount, subaccounts, sendRewardsToSeed } = options;
1119
1158
  const batch = client.tx.utility.batch(
1120
- accounts.map((x) => {
1159
+ subaccounts.map((x) => {
1121
1160
  const keys = this.keys();
1122
- const rewards = options.sendRewardsToSeed ? { Account: this.seedAddress } : { Owner: null };
1161
+ const rewards = sendRewardsToSeed ? { Account: this.seedAddress } : { Owner: null };
1123
1162
  return client.tx.miningSlot.bid(
1124
- options.bidAmount,
1163
+ bidAmount,
1125
1164
  rewards,
1126
1165
  {
1127
1166
  grandpa: keys.gran.rawPublicKey,
@@ -1135,7 +1174,19 @@ var Accountset = class {
1135
1174
  if (this.isProxy) {
1136
1175
  tx = client.tx.proxy.proxy(this.seedAddress, "MiningBid", batch);
1137
1176
  }
1138
- const submitter = new TxSubmitter(client, tx, this.txSubmitterPair);
1177
+ return new TxSubmitter(client, tx, this.txSubmitterPair);
1178
+ }
1179
+ /**
1180
+ * Create a mining bid. This will create a bid for each account in the given range from the seed account as funding.
1181
+ */
1182
+ async createMiningBids(options) {
1183
+ const accounts = this.getAccountsInRange(options.subaccountRange);
1184
+ const client = await this.client;
1185
+ const submitter = await this.createMiningBidTx({
1186
+ ...options,
1187
+ subaccounts: accounts
1188
+ });
1189
+ const { tip = 0n } = options;
1139
1190
  const txFee = await submitter.feeEstimate(tip);
1140
1191
  let minBalance = options.bidAmount * BigInt(accounts.length);
1141
1192
  let totalFees = tip + 1n + txFee;
@@ -1579,27 +1630,24 @@ var VaultMonitor = class {
1579
1630
  }
1580
1631
  };
1581
1632
 
1582
- // src/CohortBidder.ts
1583
- var CohortBidder = class _CohortBidder {
1584
- constructor(accountset, cohortId, subaccounts, options) {
1585
- this.accountset = accountset;
1633
+ // src/CohortBidderHistory.ts
1634
+ var CohortBidderHistory = class _CohortBidderHistory {
1635
+ constructor(cohortId, subaccounts) {
1586
1636
  this.cohortId = cohortId;
1587
1637
  this.subaccounts = subaccounts;
1588
- this.options = options;
1638
+ this.maxSeatsInPlay = this.subaccounts.length;
1589
1639
  this.subaccounts.forEach((x) => {
1590
- this.allAddresses.add(x.address);
1640
+ this.myAddresses.add(x.address);
1591
1641
  });
1592
1642
  }
1593
- get client() {
1594
- return this.accountset.client;
1595
- }
1643
+ bidHistory = [];
1596
1644
  stats = {
1597
1645
  // number of seats won
1598
- seats: 0,
1646
+ seatsWon: 0,
1599
1647
  // sum of argons bid in successful bids
1600
1648
  totalArgonsBid: 0n,
1601
1649
  // total number of bids placed (includes 1 per seat)
1602
- bids: 0,
1650
+ bidsAttempted: 0,
1603
1651
  // fees including the tip
1604
1652
  fees: 0n,
1605
1653
  // Max bid per seat
@@ -1611,16 +1659,157 @@ var CohortBidder = class _CohortBidder {
1611
1659
  // The cohort expected argons per block
1612
1660
  cohortArgonsPerBlock: 0n,
1613
1661
  // The last block that bids are synced to
1614
- lastBlock: 0
1662
+ lastBlockNumber: 0
1615
1663
  };
1664
+ lastBids = [];
1665
+ myAddresses = /* @__PURE__ */ new Set();
1666
+ maxSeatsInPlay = 0;
1667
+ async init(client) {
1668
+ if (!this.stats.argonotsPerSeat) {
1669
+ const startingStats = await _CohortBidderHistory.getStartingData(client);
1670
+ Object.assign(this.stats, startingStats);
1671
+ }
1672
+ }
1673
+ maybeReducingSeats(maxSeats, reason, historyEntry) {
1674
+ if (this.maxSeatsInPlay > maxSeats) {
1675
+ historyEntry.maxSeatsReductionReason = reason;
1676
+ }
1677
+ this.maxSeatsInPlay = maxSeats;
1678
+ historyEntry.maxSeatsInPlay = maxSeats;
1679
+ }
1680
+ trackChange(next, blockNumber, tick, isLastEntry = false) {
1681
+ let winningBids = 0;
1682
+ let totalArgonsBid = 0n;
1683
+ const nextEntrants = [];
1684
+ for (const x of next) {
1685
+ const bid = x.bid.toBigInt();
1686
+ const address = x.accountId.toHuman();
1687
+ nextEntrants.push({ address, bid });
1688
+ if (this.myAddresses.has(address)) {
1689
+ winningBids++;
1690
+ totalArgonsBid += bid;
1691
+ }
1692
+ }
1693
+ this.stats.seatsWon = winningBids;
1694
+ this.stats.totalArgonsBid = totalArgonsBid;
1695
+ this.stats.lastBlockNumber = Math.max(
1696
+ blockNumber,
1697
+ this.stats.lastBlockNumber
1698
+ );
1699
+ const historyEntry = {
1700
+ cohortId: this.cohortId,
1701
+ blockNumber,
1702
+ tick,
1703
+ bidChanges: [],
1704
+ winningSeats: winningBids,
1705
+ maxSeatsInPlay: this.maxSeatsInPlay
1706
+ };
1707
+ const hasDiffs = JsonExt.stringify(nextEntrants) !== JsonExt.stringify(this.lastBids);
1708
+ if (!isLastEntry || hasDiffs) {
1709
+ this.bidHistory.unshift(historyEntry);
1710
+ }
1711
+ if (hasDiffs) {
1712
+ nextEntrants.forEach(({ address, bid }, i) => {
1713
+ const prevBidIndex = this.lastBids.findIndex(
1714
+ (y) => y.address === address
1715
+ );
1716
+ const entry = {
1717
+ address,
1718
+ bidAmount: bid,
1719
+ bidPosition: i,
1720
+ prevPosition: prevBidIndex === -1 ? null : prevBidIndex
1721
+ };
1722
+ if (prevBidIndex !== -1) {
1723
+ const prevBidAmount = this.lastBids[prevBidIndex].bid;
1724
+ if (prevBidAmount !== bid) {
1725
+ entry.prevBidAmount = prevBidAmount;
1726
+ }
1727
+ }
1728
+ historyEntry.bidChanges.push(entry);
1729
+ });
1730
+ this.lastBids.forEach(({ address, bid }, i) => {
1731
+ const nextBid = nextEntrants.some((y) => y.address === address);
1732
+ if (!nextBid) {
1733
+ historyEntry.bidChanges.push({
1734
+ address,
1735
+ bidAmount: bid,
1736
+ bidPosition: null,
1737
+ prevPosition: i
1738
+ });
1739
+ }
1740
+ });
1741
+ this.lastBids = nextEntrants;
1742
+ }
1743
+ return historyEntry;
1744
+ }
1745
+ onBidResult(historyEntry, param) {
1746
+ const {
1747
+ txFeePlusTip,
1748
+ bidPerSeat,
1749
+ bidsAttempted,
1750
+ successfulBids,
1751
+ blockNumber,
1752
+ bidError
1753
+ } = param;
1754
+ this.stats.fees += txFeePlusTip;
1755
+ this.stats.bidsAttempted += bidsAttempted;
1756
+ if (bidPerSeat > this.stats.maxBidPerSeat) {
1757
+ this.stats.maxBidPerSeat = bidPerSeat;
1758
+ }
1759
+ if (blockNumber !== void 0) {
1760
+ this.stats.lastBlockNumber = Math.max(
1761
+ blockNumber,
1762
+ this.stats.lastBlockNumber
1763
+ );
1764
+ }
1765
+ historyEntry.myBidsPlaced.failureReason = bidError;
1766
+ historyEntry.myBidsPlaced.successfulBids = successfulBids;
1767
+ historyEntry.myBidsPlaced.txFeePlusTip = txFeePlusTip;
1768
+ }
1769
+ static async getStartingData(api) {
1770
+ const argonotPrice = await api.query.priceIndex.current();
1771
+ let argonotUsdPrice = 0;
1772
+ if (argonotPrice.isSome) {
1773
+ argonotUsdPrice = convertFixedU128ToBigNumber(
1774
+ argonotPrice.unwrap().argonotUsdPrice.toBigInt()
1775
+ ).toNumber();
1776
+ }
1777
+ const argonotsPerSeat = await api.query.miningSlot.argonotsPerMiningSeat().then((x) => x.toBigInt());
1778
+ const cohortArgonsPerBlock = await api.query.blockRewards.argonsPerBlock().then((x) => x.toBigInt());
1779
+ return { argonotsPerSeat, argonotUsdPrice, cohortArgonsPerBlock };
1780
+ }
1781
+ };
1782
+
1783
+ // src/CohortBidder.ts
1784
+ var CohortBidder = class {
1785
+ constructor(accountset, cohortId, subaccounts, options) {
1786
+ this.accountset = accountset;
1787
+ this.cohortId = cohortId;
1788
+ this.subaccounts = subaccounts;
1789
+ this.options = options;
1790
+ this.history = new CohortBidderHistory(cohortId, subaccounts);
1791
+ this.subaccounts.forEach((x) => {
1792
+ this.myAddresses.add(x.address);
1793
+ });
1794
+ }
1795
+ get client() {
1796
+ return this.accountset.client;
1797
+ }
1798
+ get stats() {
1799
+ return this.history.stats;
1800
+ }
1801
+ get bidHistory() {
1802
+ return this.history.bidHistory;
1803
+ }
1616
1804
  unsubscribe;
1617
1805
  pendingRequest;
1618
1806
  retryTimeout;
1619
1807
  isStopped = false;
1620
1808
  needsRebid = false;
1621
1809
  lastBidTime = 0;
1810
+ history;
1622
1811
  millisPerTick;
1623
- allAddresses = /* @__PURE__ */ new Set();
1812
+ myAddresses = /* @__PURE__ */ new Set();
1624
1813
  async stop() {
1625
1814
  if (this.isStopped) return this.stats;
1626
1815
  this.isStopped = true;
@@ -1630,70 +1819,59 @@ var CohortBidder = class _CohortBidder {
1630
1819
  this.unsubscribe();
1631
1820
  }
1632
1821
  const client = await this.client;
1633
- const [nextCohort, nextCohortId, blockNumber] = await new Promise(async (resolve) => {
1634
- const unsub = await client.queryMulti(
1635
- [
1636
- client.query.miningSlot.nextSlotCohort,
1637
- client.query.miningSlot.nextCohortId,
1638
- client.query.miningSlot.isNextSlotBiddingOpen,
1639
- client.query.system.number
1640
- ],
1641
- ([nextCohort2, nextCohortId2, isBiddingStillOpen, blockNumber2]) => {
1642
- if (nextCohortId2.toNumber() !== this.cohortId || isBiddingStillOpen.isFalse) {
1643
- unsub();
1644
- resolve([nextCohort2, nextCohortId2, blockNumber2]);
1822
+ const [nextCohortId, isBiddingOpen] = await client.queryMulti([
1823
+ client.query.miningSlot.nextCohortId,
1824
+ client.query.miningSlot.isNextSlotBiddingOpen
1825
+ ]);
1826
+ if (nextCohortId.toNumber() === this.cohortId && isBiddingOpen.isTrue) {
1827
+ console.log("Bidding is still open, waiting for it to close");
1828
+ await new Promise(async (resolve) => {
1829
+ const unsub = await client.query.miningSlot.isNextSlotBiddingOpen(
1830
+ (isOpen) => {
1831
+ if (isOpen.isFalse) {
1832
+ unsub();
1833
+ resolve();
1834
+ }
1645
1835
  }
1646
- }
1647
- );
1648
- });
1649
- void await this.pendingRequest;
1650
- if (nextCohortId.toNumber() === this.cohortId) {
1651
- console.log("Bidder updating stats with bid queue");
1652
- this.updateStats(nextCohort);
1653
- } else {
1654
- const bestBlock = await client.rpc.chain.getBlockHash();
1655
- const api = await client.at(bestBlock);
1656
- const wonIndices = await api.query.miningSlot.accountIndexLookup.multi([...this.allAddresses]).then((x) => x.filter((x2) => x2.isSome).map((x2) => x2.value));
1657
- const wonSeats = await api.query.miningSlot.activeMinersByIndex.multi(wonIndices).then(
1658
- (x) => x.filter(
1659
- (x2) => x2.isSome && x2.value.cohortId.toNumber() === this.cohortId
1660
- ).map((x2) => x2.value)
1661
- );
1662
- console.log("Bidder updating stats with finalized cohort");
1663
- this.updateStats(wonSeats);
1836
+ );
1837
+ });
1664
1838
  }
1665
- this.stats.lastBlock = Math.max(
1666
- blockNumber.toNumber(),
1667
- this.stats.lastBlock
1668
- );
1839
+ void await this.pendingRequest;
1840
+ let header = await client.rpc.chain.getHeader();
1841
+ while (true) {
1842
+ const api2 = await client.at(header.hash);
1843
+ const cohortId = await api2.query.miningSlot.nextCohortId();
1844
+ if (cohortId.toNumber() === this.cohortId) {
1845
+ break;
1846
+ }
1847
+ header = await client.rpc.chain.getHeader(header.parentHash);
1848
+ }
1849
+ const api = await client.at(header.hash);
1850
+ const tick = await api.query.ticks.currentTick().then((x) => x.toNumber());
1851
+ const cohort = await api.query.miningSlot.nextSlotCohort();
1852
+ this.history.trackChange(cohort, header.number.toNumber(), tick, true);
1853
+ console.log("Bidder stopped", {
1854
+ cohortId: this.cohortId,
1855
+ blockNumber: header.number.toNumber(),
1856
+ tick,
1857
+ cohort: cohort.map((x) => ({
1858
+ address: x.accountId.toHuman(),
1859
+ bid: x.bid.toBigInt()
1860
+ }))
1861
+ });
1669
1862
  return this.stats;
1670
1863
  }
1671
- static async getStartingData(api) {
1672
- const argonotPrice = await api.query.priceIndex.current();
1673
- let argonotUsdPrice = 0;
1674
- if (argonotPrice.isSome) {
1675
- argonotUsdPrice = convertFixedU128ToBigNumber(
1676
- argonotPrice.unwrap().argonotUsdPrice.toBigInt()
1677
- ).toNumber();
1678
- }
1679
- const argonotsPerSeat = await api.query.miningSlot.argonotsPerMiningSeat().then((x) => x.toBigInt());
1680
- const cohortArgonsPerBlock = await api.query.blockRewards.argonsPerBlock().then((x) => x.toBigInt());
1681
- return { argonotsPerSeat, argonotUsdPrice, cohortArgonsPerBlock };
1682
- }
1683
1864
  async start() {
1684
1865
  console.log(`Starting cohort ${this.cohortId} bidder`, {
1685
1866
  maxBid: formatArgons(this.options.maxBid),
1686
1867
  minBid: formatArgons(this.options.minBid),
1687
1868
  bidIncrement: formatArgons(this.options.bidIncrement),
1688
- maxBalance: formatArgons(this.options.maxBalance),
1869
+ maxBudget: formatArgons(this.options.maxBudget),
1689
1870
  bidDelay: this.options.bidDelay,
1690
1871
  subaccounts: this.subaccounts
1691
1872
  });
1692
1873
  const client = await this.client;
1693
- if (!this.stats.argonotsPerSeat) {
1694
- const startingStats = await _CohortBidder.getStartingData(client);
1695
- Object.assign(this.stats, startingStats);
1696
- }
1874
+ await this.history.init(client);
1697
1875
  this.millisPerTick ??= await client.query.ticks.genesisTicker().then((x) => x.tickDurationMillis.toNumber());
1698
1876
  this.unsubscribe = await client.queryMulti(
1699
1877
  [
@@ -1707,24 +1885,27 @@ var CohortBidder = class _CohortBidder {
1707
1885
  }
1708
1886
  );
1709
1887
  }
1710
- updateStats(next) {
1711
- let seats = 0;
1712
- let totalArgonsBid = 0n;
1713
- for (const x of next) {
1714
- if (this.allAddresses.has(x.accountId.toHuman())) {
1715
- seats++;
1716
- totalArgonsBid += x.bid.toBigInt();
1717
- }
1718
- }
1719
- this.stats.seats = seats;
1720
- this.stats.totalArgonsBid = totalArgonsBid;
1721
- }
1722
1888
  async checkSeats(next) {
1723
- if (this.isStopped || this.pendingRequest) return;
1889
+ if (this.isStopped) return;
1890
+ clearTimeout(this.retryTimeout);
1891
+ const client = await this.client;
1892
+ const bestBlock = await client.rpc.chain.getBlockHash();
1893
+ const api = await client.at(bestBlock);
1894
+ const blockNumber = await api.query.system.number().then((x) => x.toNumber());
1895
+ if (this.bidHistory[0]?.blockNumber >= blockNumber) {
1896
+ return;
1897
+ }
1898
+ const tick = await api.query.ticks.currentTick().then((x) => x.toNumber());
1899
+ const historyEntry = this.history.trackChange(next, blockNumber, tick);
1900
+ if (this.pendingRequest) return;
1724
1901
  const ticksSinceLastBid = Math.floor(
1725
1902
  (Date.now() - this.lastBidTime) / this.millisPerTick
1726
1903
  );
1727
1904
  if (ticksSinceLastBid < this.options.bidDelay) {
1905
+ this.retryTimeout = setTimeout(
1906
+ () => void this.checkCurrentSeats(),
1907
+ this.millisPerTick
1908
+ );
1728
1909
  return;
1729
1910
  }
1730
1911
  console.log(
@@ -1732,12 +1913,19 @@ var CohortBidder = class _CohortBidder {
1732
1913
  this.cohortId,
1733
1914
  this.subaccounts.map((x) => x.index)
1734
1915
  );
1735
- this.updateStats(next);
1736
- this.needsRebid = this.subaccounts.some(
1737
- (x) => !next.some((y) => y.accountId.toHuman() === x.address)
1738
- );
1916
+ const winningBids = historyEntry.winningSeats;
1917
+ this.needsRebid = winningBids < this.subaccounts.length;
1739
1918
  if (!this.needsRebid) return;
1740
- const lowestBid = next.at(-1)?.bid.toBigInt() ?? -this.options.bidIncrement;
1919
+ const winningAddresses = new Set(next.map((x) => x.accountId.toHuman()));
1920
+ let lowestBid = -this.options.bidIncrement;
1921
+ if (next.length) {
1922
+ for (let i = next.length - 1; i >= 0; i--) {
1923
+ if (!this.myAddresses.has(next[i].accountId.toHuman())) {
1924
+ lowestBid = next.at(i).bid.toBigInt();
1925
+ break;
1926
+ }
1927
+ }
1928
+ }
1741
1929
  const MIN_INCREMENT = 10000n;
1742
1930
  let nextBid = lowestBid + this.options.bidIncrement;
1743
1931
  if (nextBid < this.options.minBid) {
@@ -1745,83 +1933,119 @@ var CohortBidder = class _CohortBidder {
1745
1933
  }
1746
1934
  if (nextBid > this.options.maxBid) {
1747
1935
  nextBid = this.options.maxBid;
1748
- if (nextBid - lowestBid < MIN_INCREMENT) {
1749
- console.log(
1750
- `Can't make any more bids for ${this.cohortId} with given constraints.`,
1751
- {
1752
- lowestCurrentBid: formatArgons(lowestBid),
1753
- nextAttemptedBid: formatArgons(nextBid),
1754
- maxBid: formatArgons(this.options.maxBid)
1755
- }
1756
- );
1757
- return;
1936
+ }
1937
+ const fakeTx = await this.accountset.createMiningBidTx({
1938
+ subaccounts: this.subaccounts,
1939
+ bidAmount: nextBid,
1940
+ sendRewardsToSeed: true
1941
+ });
1942
+ let availableBalanceForBids = await api.query.system.account(this.accountset.txSubmitterPair.address).then((x) => x.data.free.toBigInt());
1943
+ for (const bid of next) {
1944
+ if (this.myAddresses.has(bid.accountId.toHuman())) {
1945
+ availableBalanceForBids += bid.bid.toBigInt();
1758
1946
  }
1759
1947
  }
1948
+ const tip = this.options.tipPerTransaction ?? 0n;
1949
+ const feeEstimate = await fakeTx.feeEstimate(tip);
1950
+ const feePlusTip = feeEstimate + tip;
1951
+ let budgetForSeats = this.options.maxBudget - feePlusTip;
1952
+ if (budgetForSeats > availableBalanceForBids) {
1953
+ budgetForSeats = availableBalanceForBids - feePlusTip;
1954
+ }
1760
1955
  if (nextBid < lowestBid) {
1761
1956
  console.log(
1762
1957
  `Can't bid ${formatArgons(nextBid)}. Current lowest bid is ${formatArgons(
1763
1958
  lowestBid
1764
1959
  )}.`
1765
1960
  );
1961
+ this.history.maybeReducingSeats(
1962
+ winningBids,
1963
+ "MaxBidTooLow" /* MaxBidTooLow */,
1964
+ historyEntry
1965
+ );
1766
1966
  return;
1767
1967
  }
1768
- const seatsInBudget = nextBid === 0n ? this.subaccounts.length : Number(this.options.maxBalance / nextBid);
1769
- if (seatsInBudget <= 0) {
1968
+ if (nextBid - lowestBid < MIN_INCREMENT) {
1770
1969
  console.log(
1771
- `Can't afford any seats at ${formatArgons(nextBid)}. Would exceed our max balance of ${formatArgons(this.options.maxBalance)}.`
1970
+ `Can't make any more bids for ${this.cohortId} with given constraints.`,
1971
+ {
1972
+ lowestCurrentBid: formatArgons(lowestBid),
1973
+ nextAttemptedBid: formatArgons(nextBid),
1974
+ maxBid: formatArgons(this.options.maxBid)
1975
+ }
1976
+ );
1977
+ this.history.maybeReducingSeats(
1978
+ winningBids,
1979
+ "MaxBidTooLow" /* MaxBidTooLow */,
1980
+ historyEntry
1772
1981
  );
1773
1982
  return;
1774
1983
  }
1775
- if (this.subaccounts.length > seatsInBudget) {
1776
- const toKeep = [];
1777
- for (const account of this.subaccounts) {
1778
- if (toKeep.length >= seatsInBudget) break;
1779
- if (account.isRebid) {
1780
- toKeep.push(account);
1781
- }
1782
- }
1783
- for (const account of this.subaccounts) {
1784
- if (toKeep.length >= seatsInBudget) break;
1785
- if (!account.isRebid) {
1786
- toKeep.push(account);
1787
- }
1788
- }
1789
- const removedIndices = this.subaccounts.filter((x) => !toKeep.some((y) => y.index === x.index)).map((x) => x.index);
1790
- this.subaccounts = toKeep;
1791
- console.log("Had to remove some subaccounts to fit in budget:", {
1792
- removedIndices,
1793
- seatsInBudget,
1794
- budget: formatArgons(this.options.maxBalance)
1984
+ const seatsInBudget = nextBid === 0n ? this.subaccounts.length : Number(budgetForSeats / nextBid);
1985
+ let accountsToUse = [...this.subaccounts];
1986
+ if (accountsToUse.length > seatsInBudget) {
1987
+ const reason = availableBalanceForBids - feePlusTip < nextBid * BigInt(seatsInBudget) ? "InsufficientFunds" /* InsufficientFunds */ : "MaxBudgetTooLow" /* MaxBudgetTooLow */;
1988
+ this.history.maybeReducingSeats(seatsInBudget, reason, historyEntry);
1989
+ accountsToUse.sort((a, b) => {
1990
+ const isWinningA = winningAddresses.has(a.address);
1991
+ const isWinningB = winningAddresses.has(b.address);
1992
+ if (isWinningA && !isWinningB) return -1;
1993
+ if (!isWinningA && isWinningB) return 1;
1994
+ if (a.isRebid && !b.isRebid) return -1;
1995
+ if (!a.isRebid && b.isRebid) return 1;
1996
+ return a.index - b.index;
1795
1997
  });
1998
+ accountsToUse.length = seatsInBudget;
1999
+ }
2000
+ if (accountsToUse.length > winningBids) {
2001
+ historyEntry.myBidsPlaced = {
2002
+ bids: accountsToUse.length,
2003
+ bidPerSeat: nextBid,
2004
+ txFeePlusTip: feePlusTip,
2005
+ successfulBids: 0
2006
+ };
2007
+ this.pendingRequest = this.bid(nextBid, accountsToUse, historyEntry);
2008
+ } else if (historyEntry.bidChanges.length === 0) {
2009
+ this.history.bidHistory.shift();
1796
2010
  }
1797
- this.pendingRequest = this.bid(
1798
- nextBid,
1799
- this.subaccounts.map((x) => x.index)
1800
- );
1801
2011
  this.needsRebid = false;
1802
2012
  }
1803
- async bid(bidPerSeat, subaccountRange) {
1804
- if (!subaccountRange.length) return;
2013
+ async bid(bidPerSeat, subaccounts, historyEntry) {
1805
2014
  const prevLastBidTime = this.lastBidTime;
1806
2015
  try {
1807
2016
  this.lastBidTime = Date.now();
1808
- const result = await this.accountset.createMiningBids({
1809
- subaccountRange,
2017
+ const submitter = await this.accountset.createMiningBidTx({
2018
+ subaccounts,
1810
2019
  bidAmount: bidPerSeat,
1811
2020
  sendRewardsToSeed: true
1812
2021
  });
1813
- if (result.blockHash) {
2022
+ const tip = this.options.tipPerTransaction ?? 0n;
2023
+ const txResult = await submitter.submit({
2024
+ tip,
2025
+ useLatestNonce: true
2026
+ });
2027
+ const bidError = await txResult.inBlockPromise.then(() => void 0).catch((x) => x);
2028
+ let blockNumber;
2029
+ if (txResult.includedInBlock) {
1814
2030
  const client = await this.client;
1815
- const api = await client.at(result.blockHash);
1816
- this.stats.lastBlock = await api.query.system.number().then((x) => x.toNumber());
2031
+ const api = await client.at(txResult.includedInBlock);
2032
+ blockNumber = await api.query.system.number().then((x) => x.toNumber());
1817
2033
  }
1818
- this.stats.fees += result.finalFee ?? 0n;
1819
- this.stats.bids += subaccountRange.length;
1820
- if (bidPerSeat > this.stats.maxBidPerSeat) {
1821
- this.stats.maxBidPerSeat = bidPerSeat;
1822
- }
1823
- console.log("Done creating bids for cohort", this.cohortId);
1824
- if (result.bidError) throw result.bidError;
2034
+ const successfulBids = txResult.batchInterruptedIndex ?? subaccounts.length;
2035
+ this.history.onBidResult(historyEntry, {
2036
+ blockNumber,
2037
+ successfulBids,
2038
+ bidPerSeat,
2039
+ txFeePlusTip: txResult.finalFee ?? 0n,
2040
+ bidsAttempted: subaccounts.length,
2041
+ bidError
2042
+ });
2043
+ console.log("Done creating bids for cohort", {
2044
+ successfulBids,
2045
+ bidPerSeat,
2046
+ blockNumber
2047
+ });
2048
+ if (bidError) throw bidError;
1825
2049
  } catch (err) {
1826
2050
  this.lastBidTime = prevLastBidTime;
1827
2051
  console.error(`Error bidding for cohort ${this.cohortId}:`, err);
@@ -2499,8 +2723,8 @@ function vaultCli() {
2499
2723
  ).action(async ({ tip, argons, vaultId, ratio }) => {
2500
2724
  const accountset = await accountsetFromCli(program);
2501
2725
  const client = await accountset.client;
2502
- const resolvedTip = tip ? BigInt(tip * 1e6) : 0n;
2503
- const microgons = BigInt(argons * 1e6);
2726
+ const resolvedTip = tip ? BigInt(tip * MICROGONS_PER_ARGON) : 0n;
2727
+ const microgons = BigInt(argons * MICROGONS_PER_ARGON);
2504
2728
  const rawVault = (await client.query.vaults.vaultsById(vaultId)).unwrap();
2505
2729
  if (rawVault.operatorAccountId.toHuman() !== accountset.seedAddress) {
2506
2730
  console.error("Vault does not belong to this account");
@@ -2560,8 +2784,8 @@ function vaultCli() {
2560
2784
  }
2561
2785
  const accountset = await accountsetFromCli(program);
2562
2786
  const client = await accountset.client;
2563
- const resolvedTip = tip ? BigInt(tip * 1e6) : 0n;
2564
- const microgons = BigInt(argons * 1e6);
2787
+ const resolvedTip = tip ? BigInt(tip * MICROGONS_PER_ARGON) : 0n;
2788
+ const microgons = BigInt(argons * MICROGONS_PER_ARGON);
2565
2789
  const bitcoinLocks = new BitcoinLocks(Promise.resolve(client));
2566
2790
  const existentialDeposit = client.consts.balances.existentialDeposit.toBigInt();
2567
2791
  const tickDuration = (await client.query.ticks.genesisTicker()).tickDurationMillis.toNumber();
@@ -2766,7 +2990,7 @@ function miningCli() {
2766
2990
  const balance = await accountset.balance();
2767
2991
  const feeWiggleRoom = BigInt(25e3);
2768
2992
  const amountAvailable = balance - feeWiggleRoom;
2769
- let maxBidAmount = maxBid ? BigInt(maxBid * 1e6) : void 0;
2993
+ let maxBidAmount = maxBid ? BigInt(maxBid * MICROGONS_PER_ARGON) : void 0;
2770
2994
  let maxBalanceToUse = amountAvailable;
2771
2995
  if (maxBalance !== void 0) {
2772
2996
  if (maxBalance.endsWith("%")) {
@@ -2778,7 +3002,7 @@ function miningCli() {
2778
3002
  maxBalanceToUse = amountToBid;
2779
3003
  } else {
2780
3004
  maxBalanceToUse = BigInt(
2781
- Math.floor(parseFloat(maxBalance) * 1e6)
3005
+ Math.floor(parseFloat(maxBalance) * MICROGONS_PER_ARGON)
2782
3006
  );
2783
3007
  }
2784
3008
  maxBidAmount ??= maxBalanceToUse / BigInt(seatsToWin);
@@ -2800,9 +3024,11 @@ function miningCli() {
2800
3024
  subaccountRange,
2801
3025
  {
2802
3026
  maxBid: maxBidAmount,
2803
- minBid: BigInt((minBid ?? 0) * 1e6),
2804
- bidIncrement: BigInt(Math.floor(bidIncrement * 1e6)),
2805
- maxBalance: maxBalanceToUse,
3027
+ minBid: BigInt((minBid ?? 0) * MICROGONS_PER_ARGON),
3028
+ bidIncrement: BigInt(
3029
+ Math.floor(bidIncrement * MICROGONS_PER_ARGON)
3030
+ ),
3031
+ maxBudget: maxBalanceToUse,
2806
3032
  bidDelay
2807
3033
  }
2808
3034
  );
@@ -2834,7 +3060,10 @@ function miningCli() {
2834
3060
  );
2835
3061
  const tx = client.tx.utility.batchAll([
2836
3062
  client.tx.proxy.addProxy(address, "MiningBid", 0),
2837
- client.tx.balances.transferAllowDeath(address, BigInt(feeArgons * 1e6))
3063
+ client.tx.balances.transferAllowDeath(
3064
+ address,
3065
+ BigInt(feeArgons * MICROGONS_PER_ARGON)
3066
+ )
2838
3067
  ]);
2839
3068
  let keypair;
2840
3069
  try {
@@ -2883,8 +3112,8 @@ function liquidityCli() {
2883
3112
  parseFloat
2884
3113
  ).action(async ({ tip, argons, vaultId }) => {
2885
3114
  const accountset = await accountsetFromCli(program);
2886
- const resolvedTip = tip ? BigInt(tip * 1e6) : 0n;
2887
- const microgons = BigInt(argons * 1e6);
3115
+ const resolvedTip = tip ? BigInt(tip * MICROGONS_PER_ARGON) : 0n;
3116
+ const microgons = BigInt(argons * MICROGONS_PER_ARGON);
2888
3117
  const bidPool = new BidPool(
2889
3118
  accountset.client,
2890
3119
  accountset.txSubmitterPair
@@ -2909,7 +3138,7 @@ function liquidityCli() {
2909
3138
  "The tip to include with the transaction",
2910
3139
  parseFloat
2911
3140
  ).action(async ({ maxArgons, minPctSharing, tip }) => {
2912
- const maxAmountPerSlot = BigInt(maxArgons * 1e6);
3141
+ const maxAmountPerSlot = BigInt(maxArgons * MICROGONS_PER_ARGON);
2913
3142
  const accountset = await accountsetFromCli(program);
2914
3143
  const vaults = new VaultMonitor(
2915
3144
  accountset,
@@ -2922,7 +3151,7 @@ function liquidityCli() {
2922
3151
  accountset.client,
2923
3152
  accountset.txSubmitterPair
2924
3153
  );
2925
- const resolvedTip = tip ? BigInt(tip * 1e6) : 0n;
3154
+ const resolvedTip = tip ? BigInt(tip * MICROGONS_PER_ARGON) : 0n;
2926
3155
  console.log("Waiting for liquidity pool space...");
2927
3156
  vaults.events.on(
2928
3157
  "liquidity-pool-space-above",
@@ -2961,7 +3190,7 @@ function bitcoinCli() {
2961
3190
  ).description("Watch for bitcoin space available").action(async ({ argons }) => {
2962
3191
  const accountset = await accountsetFromCli(program);
2963
3192
  const bot = new VaultMonitor(accountset, {
2964
- bitcoinSpaceAvailable: argons ? BigInt(argons * 1e6) : 1n
3193
+ bitcoinSpaceAvailable: argons ? BigInt(argons * MICROGONS_PER_ARGON) : 1n
2965
3194
  });
2966
3195
  bot.events.on("bitcoin-space-above", async (vaultId, amount) => {
2967
3196
  const vault = bot.vaultsById[vaultId];
@@ -2990,13 +3219,13 @@ function bitcoinCli() {
2990
3219
  parseFloat,
2991
3220
  0
2992
3221
  ).action(async ({ argons, bitcoinXpub, maxLockFee, tip }) => {
2993
- const amountToLock = BigInt(argons * 1e6);
3222
+ const amountToLock = BigInt(argons * MICROGONS_PER_ARGON);
2994
3223
  const accountset = await accountsetFromCli(program);
2995
3224
  await BitcoinLocks.waitForSpace(accountset, {
2996
3225
  argonAmount: amountToLock,
2997
3226
  bitcoinXpub,
2998
- maxLockFee: maxLockFee !== void 0 ? BigInt(maxLockFee * 1e6) : void 0,
2999
- tip: BigInt(tip * 1e6)
3227
+ maxLockFee: maxLockFee !== void 0 ? BigInt(maxLockFee * MICROGONS_PER_ARGON) : void 0,
3228
+ tip: BigInt(tip * MICROGONS_PER_ARGON)
3000
3229
  }).then(({ vaultId, satoshis, txFee, btcFee }) => {
3001
3230
  console.log(
3002
3231
  `Locked ${satoshis} satoshis in vault ${vaultId}. Tx fee=${formatArgons(
@@ -3021,8 +3250,13 @@ async function keyringFromFile(opts) {
3021
3250
  }
3022
3251
  const path = opts.filePath.replace("~", os.homedir());
3023
3252
  const json = JSON.parse(await readFile(path, "utf-8"));
3253
+ let passphrase = opts.passphrase;
3254
+ if (opts.passphraseFile) {
3255
+ const passphrasePath = opts.passphraseFile.replace("~", os.homedir());
3256
+ passphrase = await readFile(passphrasePath, "utf-8");
3257
+ }
3024
3258
  const mainAccount = new import_api.Keyring().createFromJson(json);
3025
- mainAccount.decodePkcs8(opts.passphrase);
3259
+ mainAccount.decodePkcs8(passphrase);
3026
3260
  return mainAccount;
3027
3261
  }
3028
3262
  async function saveKeyringPair(opts) {
@@ -3057,6 +3291,11 @@ function buildCli() {
3057
3291
  "--account-passphrase <password>",
3058
3292
  "The password for your seed file"
3059
3293
  ).env("ACCOUNT_PASSPHRASE")
3294
+ ).addOption(
3295
+ new import_extra_typings6.Option(
3296
+ "--account-passphrase-file <path>",
3297
+ "The path to a password for your seed file"
3298
+ )
3060
3299
  ).addOption(
3061
3300
  new import_extra_typings6.Option(
3062
3301
  "-s, --subaccounts <range>",
@@ -3073,7 +3312,8 @@ async function accountsetFromCli(program, proxyForAddress) {
3073
3312
  if (opts.accountFilePath) {
3074
3313
  keypair = await keyringFromFile({
3075
3314
  filePath: opts.accountFilePath,
3076
- passphrase: opts.accountPassphrase
3315
+ passphrase: opts.accountPassphrase,
3316
+ passphraseFile: opts.accountPassphraseFile
3077
3317
  });
3078
3318
  }
3079
3319
  if (!keypair) {