@argonprotocol/mainchain 1.3.5 → 1.3.7

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.
@@ -96,7 +96,7 @@ function getConfig() {
96
96
  return {
97
97
  debug: config.debug ?? getEnvVar("DEBUG") === "true",
98
98
  keysVersion: config.keysVersion ?? (getEnvVar("KEYS_VERSION") ? parseInt(getEnvVar("KEYS_VERSION")) : void 0),
99
- keysMnemonic: config.keysMnemonic ?? getEnvVar("KEYS_MNEMONIC"),
99
+ keySeedOrMnemonic: config.keySeedOrMnemonic ?? getEnvVar("KEYS_MNEMONIC"),
100
100
  subaccountRange: config.subaccountRange ?? getEnvVar("SUBACCOUNT_RANGE") ?? "0-9"
101
101
  };
102
102
  }
@@ -259,8 +259,19 @@ var TxResult = class {
259
259
 
260
260
  // src/utils.ts
261
261
  import BigNumber, * as BN from "bignumber.js";
262
+ import { ed25519DeriveHard, keyExtractSuri, mnemonicToMiniSecret } from "@polkadot/util-crypto";
263
+ import { u8aToHex } from "@polkadot/util";
262
264
  var { ROUND_FLOOR } = BN;
263
265
  var MICROGONS_PER_ARGON = 1e6;
266
+ function miniSecretFromUri(uri, password) {
267
+ const { phrase, path } = keyExtractSuri(uri);
268
+ let mini = mnemonicToMiniSecret(phrase, password);
269
+ for (const j of path) {
270
+ if (!j.isHard) throw new Error("ed25519 soft derivation not supported");
271
+ mini = ed25519DeriveHard(mini, j.chainCode);
272
+ }
273
+ return u8aToHex(mini);
274
+ }
264
275
  function formatArgons(microgons) {
265
276
  if (microgons === void 0 || microgons === null) return "na";
266
277
  const isNegative = microgons < 0;
@@ -404,7 +415,7 @@ var JsonExt = class {
404
415
  }
405
416
  static parse(str) {
406
417
  return JSON.parse(str, (_, v) => {
407
- if (typeof v === "string" && v.match(/^\d+n$/)) {
418
+ if (typeof v === "string" && v.match(/^-?\d+n$/)) {
408
419
  return BigInt(v.slice(0, -1));
409
420
  }
410
421
  if (typeof v === "object" && v !== null && v.type === "Buffer" && Array.isArray(v.data)) {
@@ -637,9 +648,13 @@ BLOCK #${header.number}, ${header.hash.toHuman()}`);
637
648
  };
638
649
 
639
650
  // src/FrameCalculator.ts
640
- var FrameCalculator = class {
651
+ var FrameCalculator = class _FrameCalculator {
641
652
  miningConfig;
642
653
  genesisTick;
654
+ tickMillis;
655
+ async load(client) {
656
+ return await this.getConfig(client);
657
+ }
643
658
  async getForTick(client, tick) {
644
659
  const { ticksBetweenFrames, biddingStartTick } = await this.getConfig(client);
645
660
  const ticksSinceMiningStart = tick - biddingStartTick;
@@ -647,9 +662,10 @@ var FrameCalculator = class {
647
662
  }
648
663
  async getTickRangeForFrame(client, frameId) {
649
664
  const { ticksBetweenFrames, biddingStartTick } = await this.getConfig(client);
650
- const startingTick = biddingStartTick + Math.floor(frameId * ticksBetweenFrames);
651
- const endingTick = startingTick + ticksBetweenFrames - 1;
652
- return [startingTick, endingTick];
665
+ return _FrameCalculator.calculateTickRangeForFrame(frameId, {
666
+ ticksBetweenFrames,
667
+ biddingStartTick
668
+ });
653
669
  }
654
670
  async getForHeader(client, header) {
655
671
  if (header.number.toNumber() === 0) return 0;
@@ -657,18 +673,30 @@ var FrameCalculator = class {
657
673
  if (tick === void 0) return void 0;
658
674
  return this.getForTick(client, tick);
659
675
  }
676
+ static frameToDateRange(frameId, config2) {
677
+ const [start, end] = _FrameCalculator.calculateTickRangeForFrame(frameId, config2);
678
+ return [new Date(start * config2.tickMillis), new Date(end * config2.tickMillis)];
679
+ }
680
+ static calculateTickRangeForFrame(frameId, config2) {
681
+ const { ticksBetweenFrames, biddingStartTick } = config2;
682
+ const startingTick = biddingStartTick + Math.floor(frameId * ticksBetweenFrames);
683
+ const endingTick = startingTick + ticksBetweenFrames - 1;
684
+ return [startingTick, endingTick];
685
+ }
660
686
  async getConfig(client) {
661
687
  this.miningConfig ??= await client.query.miningSlot.miningConfig().then((x) => ({
662
688
  ticksBetweenSlots: x.ticksBetweenSlots.toNumber(),
663
689
  slotBiddingStartAfterTicks: x.slotBiddingStartAfterTicks.toNumber()
664
690
  }));
665
691
  this.genesisTick ??= await client.query.ticks.genesisTick().then((x) => x.toNumber());
692
+ this.tickMillis ??= await client.query.ticks.genesisTicker().then((x) => x.tickDurationMillis.toNumber());
666
693
  const config2 = this.miningConfig;
667
694
  const genesisTick = this.genesisTick;
668
695
  return {
669
696
  ticksBetweenFrames: config2.ticksBetweenSlots,
670
697
  slotBiddingStartAfterTicks: config2.slotBiddingStartAfterTicks,
671
698
  genesisTick,
699
+ tickMillis: this.tickMillis,
672
700
  biddingStartTick: genesisTick + config2.slotBiddingStartAfterTicks
673
701
  };
674
702
  }
@@ -795,7 +823,7 @@ var AccountMiners = class _AccountMiners {
795
823
  };
796
824
 
797
825
  // src/Accountset.ts
798
- import { u8aToHex } from "@polkadot/util";
826
+ import { u8aToHex as u8aToHex2 } from "@polkadot/util";
799
827
  var Accountset = class {
800
828
  txSubmitterPair;
801
829
  isProxy = false;
@@ -809,7 +837,7 @@ var Accountset = class {
809
837
  get namedAccounts() {
810
838
  return this.accountRegistry.namedAccounts;
811
839
  }
812
- sessionKeyMnemonic;
840
+ sessionKeySeed;
813
841
  constructor(options) {
814
842
  if ("seedAccount" in options) {
815
843
  this.txSubmitterPair = options.seedAccount;
@@ -820,7 +848,7 @@ var Accountset = class {
820
848
  this.txSubmitterPair = options.txSubmitter;
821
849
  this.seedAddress = options.seedAddress;
822
850
  }
823
- this.sessionKeyMnemonic = options.sessionKeyMnemonic;
851
+ this.sessionKeySeed = options.sessionKeySeedOrMnemonic;
824
852
  this.accountRegistry = options.accountRegistry ?? AccountRegistry.factory(options.name);
825
853
  this.client = options.client;
826
854
  const defaultRange = options.subaccountRange ?? getDefaultSubaccountRange();
@@ -901,7 +929,6 @@ var Accountset = class {
901
929
  ];
902
930
  const bidAmountsByFrame = {};
903
931
  if (frameIds.length) {
904
- console.log("Looking up cohorts for frames", frameIds);
905
932
  const cohorts = await api.query.miningSlot.minersByCohort.multi(frameIds);
906
933
  for (let i = 0; i < frameIds.length; i++) {
907
934
  const cohort = cohorts[i];
@@ -1059,12 +1086,12 @@ var Accountset = class {
1059
1086
  keys(keysVersion) {
1060
1087
  const config2 = getConfig();
1061
1088
  let version = keysVersion ?? config2.keysVersion ?? 0;
1062
- const seedMnemonic = this.sessionKeyMnemonic ?? config2.keysMnemonic;
1063
- if (!seedMnemonic) {
1089
+ const seed = this.sessionKeySeed ?? config2.keySeedOrMnemonic;
1090
+ if (!seed) {
1064
1091
  throw new Error("KEYS_MNEMONIC environment variable not set. Cannot derive keys.");
1065
1092
  }
1066
- const blockSealKey = `${seedMnemonic}//block-seal//${version}`;
1067
- const granKey = `${seedMnemonic}//grandpa//${version}`;
1093
+ const blockSealKey = `${seed}//block-seal//${version}`;
1094
+ const granKey = `${seed}//grandpa//${version}`;
1068
1095
  const blockSealAccount = new Keyring().createFromUri(blockSealKey, {
1069
1096
  type: "ed25519"
1070
1097
  });
@@ -1074,12 +1101,12 @@ var Accountset = class {
1074
1101
  return {
1075
1102
  seal: {
1076
1103
  privateKey: blockSealKey,
1077
- publicKey: u8aToHex(blockSealAccount.publicKey),
1104
+ publicKey: u8aToHex2(blockSealAccount.publicKey),
1078
1105
  rawPublicKey: blockSealAccount.publicKey
1079
1106
  },
1080
1107
  gran: {
1081
1108
  privateKey: granKey,
1082
- publicKey: u8aToHex(grandpaAccount.publicKey),
1109
+ publicKey: u8aToHex2(grandpaAccount.publicKey),
1083
1110
  rawPublicKey: grandpaAccount.publicKey
1084
1111
  }
1085
1112
  };
@@ -1656,31 +1683,37 @@ var VaultMonitor = class {
1656
1683
 
1657
1684
  // src/CohortBidder.ts
1658
1685
  var CohortBidder = class {
1659
- constructor(accountset, cohortStartingFrameId, subaccounts, options) {
1686
+ constructor(accountset, cohortStartingFrameId, subaccounts, options, callbacks) {
1660
1687
  this.accountset = accountset;
1661
1688
  this.cohortStartingFrameId = cohortStartingFrameId;
1662
1689
  this.subaccounts = subaccounts;
1663
1690
  this.options = options;
1691
+ this.callbacks = callbacks;
1664
1692
  this.subaccounts.forEach((x) => {
1665
1693
  this.myAddresses.add(x.address);
1666
1694
  });
1667
1695
  }
1668
- get client() {
1696
+ get clientPromise() {
1669
1697
  return this.accountset.client;
1670
1698
  }
1671
1699
  txFees = 0n;
1700
+ bidsAttempted = 0;
1672
1701
  winningBids = [];
1702
+ myAddresses = /* @__PURE__ */ new Set();
1703
+ currentBids = {
1704
+ bids: [],
1705
+ mostRecentBidTick: 0,
1706
+ atTick: 0,
1707
+ atBlockNumber: 0
1708
+ };
1673
1709
  unsubscribe;
1674
1710
  pendingRequest;
1675
- retryTimeout;
1676
1711
  isStopped = false;
1677
- needsRebid = false;
1678
- lastBidTime = 0;
1679
1712
  millisPerTick;
1680
1713
  minIncrement = 10000n;
1681
1714
  nextCohortSize;
1682
- lastBidBlockNumber = 0;
1683
- myAddresses = /* @__PURE__ */ new Set();
1715
+ lastBidTick = 0;
1716
+ evaluateInterval;
1684
1717
  async start() {
1685
1718
  console.log(`Starting cohort ${this.cohortStartingFrameId} bidder`, {
1686
1719
  maxBid: formatArgons(this.options.maxBid),
@@ -1690,7 +1723,7 @@ var CohortBidder = class {
1690
1723
  bidDelay: this.options.bidDelay,
1691
1724
  subaccounts: this.subaccounts
1692
1725
  });
1693
- const client = await this.client;
1726
+ const client = await this.clientPromise;
1694
1727
  this.minIncrement = client.consts.miningSlot.bidIncrements.toBigInt();
1695
1728
  this.nextCohortSize = await client.query.miningSlot.nextCohortSize().then((x) => x.toNumber());
1696
1729
  if (this.subaccounts.length > this.nextCohortSize) {
@@ -1700,14 +1733,22 @@ var CohortBidder = class {
1700
1733
  this.subaccounts.length = this.nextCohortSize;
1701
1734
  }
1702
1735
  this.millisPerTick = await client.query.ticks.genesisTicker().then((x) => x.tickDurationMillis.toNumber());
1736
+ let didStart = false;
1703
1737
  this.unsubscribe = await client.queryMulti(
1704
1738
  [
1705
1739
  client.query.miningSlot.bidsForNextSlotCohort,
1706
- client.query.miningSlot.nextFrameId
1740
+ client.query.miningSlot.nextFrameId,
1741
+ client.query.ticks.currentTick,
1742
+ client.query.system.number
1707
1743
  ],
1708
- async ([bids, nextFrameId]) => {
1744
+ async ([rawBids, nextFrameId, currentTick, blockNumber]) => {
1709
1745
  if (nextFrameId.toNumber() === this.cohortStartingFrameId) {
1710
- await this.checkWinningBids(bids);
1746
+ this.updateBidList(rawBids, blockNumber.toNumber(), currentTick.toNumber());
1747
+ if (!didStart) {
1748
+ didStart = true;
1749
+ this.scheduleEvaluation();
1750
+ void this.checkWinningBids();
1751
+ }
1711
1752
  }
1712
1753
  }
1713
1754
  );
@@ -1715,12 +1756,12 @@ var CohortBidder = class {
1715
1756
  async stop() {
1716
1757
  if (this.isStopped) return this.winningBids;
1717
1758
  this.isStopped = true;
1759
+ clearInterval(this.evaluateInterval);
1718
1760
  console.log("Stopping bidder for cohort", this.cohortStartingFrameId);
1719
- clearTimeout(this.retryTimeout);
1720
1761
  if (this.unsubscribe) {
1721
1762
  this.unsubscribe();
1722
1763
  }
1723
- const client = await this.client;
1764
+ const client = await this.clientPromise;
1724
1765
  const [nextFrameId, isBiddingOpen] = await client.queryMulti([
1725
1766
  client.query.miningSlot.nextFrameId,
1726
1767
  client.query.miningSlot.isNextSlotBiddingOpen
@@ -1737,58 +1778,63 @@ var CohortBidder = class {
1737
1778
  });
1738
1779
  }
1739
1780
  void await this.pendingRequest;
1740
- let header = await client.rpc.chain.getHeader();
1741
- let api = await client.at(header.hash);
1742
- while (true) {
1743
- const cohortStartingFrameId = await api.query.miningSlot.nextFrameId();
1744
- if (cohortStartingFrameId.toNumber() === this.cohortStartingFrameId) {
1745
- break;
1746
- }
1747
- header = await client.rpc.chain.getHeader(header.parentHash);
1748
- api = await client.at(header.hash);
1781
+ const currentFrameId = await client.query.miningSlot.nextFrameId();
1782
+ let blockNumber;
1783
+ if (currentFrameId.toNumber() > this.cohortStartingFrameId) {
1784
+ blockNumber = await client.query.miningSlot.frameStartBlockNumbers().then((x) => x[0]?.toNumber()) - 1;
1785
+ } else {
1786
+ blockNumber = await client.query.system.number().then((x) => x.toNumber());
1749
1787
  }
1750
- const bids = await api.query.miningSlot.bidsForNextSlotCohort();
1751
- this.updateSeatsWon(bids);
1788
+ const blockHash = await client.rpc.chain.getBlockHash(blockNumber);
1789
+ const api = await client.at(blockHash);
1790
+ const rawBids = await api.query.miningSlot.bidsForNextSlotCohort();
1791
+ const currentTick = await api.query.ticks.currentTick().then((x) => x.toNumber());
1792
+ this.updateBidList(rawBids, blockNumber, currentTick);
1752
1793
  console.log("Bidder stopped", {
1753
1794
  cohortStartingFrameId: this.cohortStartingFrameId,
1754
- blockNumber: header.number.toNumber(),
1755
- bids: this.winningBids
1795
+ blockNumber,
1796
+ winningBids: this.winningBids
1756
1797
  });
1757
1798
  return this.winningBids;
1758
1799
  }
1759
- async checkWinningBids(bids) {
1800
+ async checkWinningBids() {
1760
1801
  if (this.isStopped) return;
1761
- clearTimeout(this.retryTimeout);
1762
- this.updateSeatsWon(bids);
1763
- const winningBids = this.winningBids.length;
1764
- this.needsRebid = winningBids < this.subaccounts.length;
1765
- const client = await this.client;
1766
- const bestBlock = await client.rpc.chain.getBlockHash();
1767
- const api = await client.at(bestBlock);
1768
- const blockNumber = await api.query.system.number().then((x) => x.toNumber());
1769
- if (this.lastBidBlockNumber >= blockNumber) return;
1770
- if (this.pendingRequest) return;
1771
- const ticksSinceLastBid = Math.floor((Date.now() - this.lastBidTime) / this.millisPerTick);
1772
- if (ticksSinceLastBid < this.options.bidDelay && this.needsRebid) {
1773
- this.retryTimeout = setTimeout(() => void this.checkCurrentSeats(), this.millisPerTick);
1802
+ if (this.pendingRequest) {
1803
+ console.log("Current bid is still in progress, skipping this check");
1804
+ return;
1805
+ }
1806
+ if (this.currentBids.mostRecentBidTick < this.lastBidTick) {
1807
+ console.log(`Waiting for bids more recent than our last attempt.`, {
1808
+ ownAttemptedBidTick: this.lastBidTick,
1809
+ liveBidsTick: this.currentBids.mostRecentBidTick
1810
+ });
1811
+ return;
1812
+ }
1813
+ const bids = [...this.currentBids.bids];
1814
+ const bidsAtTick = this.currentBids.atTick;
1815
+ const blockNumber = this.currentBids.atBlockNumber;
1816
+ const winningBids = bids.filter((x) => this.myAddresses.has(x.address));
1817
+ if (winningBids.length >= this.subaccounts.length) {
1818
+ console.log(`No updates needed. Winning all remaining seats (${winningBids.length}).`);
1774
1819
  return;
1775
1820
  }
1776
- if (!this.needsRebid) return;
1777
1821
  console.log(
1778
- "Checking bids for cohort",
1779
- this.cohortStartingFrameId,
1780
- this.subaccounts.map((x) => x.index)
1822
+ `Checking bids for cohort ${this.cohortStartingFrameId}, Still trying for seats: ${this.subaccounts.length}`
1781
1823
  );
1782
- const winningAddresses = new Set(bids.map((x) => x.accountId.toHuman()));
1783
- let lowestBid = -this.options.bidIncrement;
1784
- if (bids.length) {
1785
- for (let i = bids.length - 1; i >= 0; i--) {
1786
- if (!this.myAddresses.has(bids[i].accountId.toHuman())) {
1787
- lowestBid = bids.at(i).bid.toBigInt();
1788
- break;
1824
+ const winningAddresses = new Set(winningBids.map((x) => x.address));
1825
+ let lowestBid;
1826
+ let myAllocatedBids = 0n;
1827
+ for (const bid of bids) {
1828
+ lowestBid ??= bid.bidMicrogons;
1829
+ if (this.myAddresses.has(bid.address)) {
1830
+ myAllocatedBids += bid.bidMicrogons;
1831
+ } else {
1832
+ if (bid.bidMicrogons < lowestBid) {
1833
+ lowestBid = bid.bidMicrogons;
1789
1834
  }
1790
1835
  }
1791
1836
  }
1837
+ lowestBid ??= -this.options.bidIncrement;
1792
1838
  let nextBid = lowestBid + this.options.bidIncrement;
1793
1839
  if (nextBid < this.options.minBid) {
1794
1840
  nextBid = this.options.minBid;
@@ -1800,39 +1846,59 @@ var CohortBidder = class {
1800
1846
  subaccounts: this.subaccounts,
1801
1847
  bidAmount: nextBid
1802
1848
  });
1803
- let availableBalanceForBids = await api.query.system.account(this.accountset.txSubmitterPair.address).then((x) => x.data.free.toBigInt());
1804
- for (const bid of bids) {
1805
- if (this.myAddresses.has(bid.accountId.toHuman())) {
1806
- availableBalanceForBids += bid.bid.toBigInt();
1807
- }
1808
- }
1849
+ let availableBalanceForBids = await this.accountset.submitterBalance();
1850
+ availableBalanceForBids += myAllocatedBids;
1809
1851
  const tip = this.options.tipPerTransaction ?? 0n;
1810
1852
  const feeEstimate = await fakeTx.feeEstimate(tip);
1811
- const feePlusTip = feeEstimate + tip;
1812
- let budgetForSeats = this.options.maxBudget - feePlusTip;
1853
+ const estimatedFeePlusTip = feeEstimate + tip;
1854
+ let budgetForSeats = this.options.maxBudget - estimatedFeePlusTip;
1813
1855
  if (budgetForSeats > availableBalanceForBids) {
1814
- budgetForSeats = availableBalanceForBids - feePlusTip;
1856
+ budgetForSeats = availableBalanceForBids - estimatedFeePlusTip;
1815
1857
  }
1816
1858
  if (nextBid < lowestBid) {
1817
1859
  console.log(
1818
- `Can't bid ${formatArgons(nextBid)}. Current lowest bid is ${formatArgons(lowestBid)}.`
1860
+ `Next bid within parameters is ${formatArgons(nextBid)}, but it's not enough. Current lowest bid is ${formatArgons(lowestBid)}.`
1819
1861
  );
1862
+ this.safeRecordParamsAdjusted({
1863
+ tick: bidsAtTick,
1864
+ blockNumber,
1865
+ maxSeats: 0,
1866
+ winningBidCount: winningBids.length,
1867
+ reason: "max-bid-too-low",
1868
+ availableBalanceForBids
1869
+ });
1820
1870
  return;
1821
1871
  }
1822
1872
  if (nextBid - lowestBid < Number(this.minIncrement)) {
1823
1873
  console.log(
1824
- `Can't make any more bids for ${this.cohortStartingFrameId} with given constraints.`,
1874
+ `Can't make any more bids for ${this.cohortStartingFrameId} with given constraints (next bid below min increment).`,
1825
1875
  {
1826
1876
  lowestCurrentBid: formatArgons(lowestBid),
1827
1877
  nextAttemptedBid: formatArgons(nextBid),
1828
1878
  maxBid: formatArgons(this.options.maxBid)
1829
1879
  }
1830
1880
  );
1881
+ this.safeRecordParamsAdjusted({
1882
+ tick: bidsAtTick,
1883
+ blockNumber,
1884
+ maxSeats: 0,
1885
+ winningBidCount: winningBids.length,
1886
+ reason: "max-bid-too-low",
1887
+ availableBalanceForBids
1888
+ });
1831
1889
  return;
1832
1890
  }
1833
1891
  const seatsInBudget = nextBid === 0n ? this.subaccounts.length : Number(budgetForSeats / nextBid);
1834
1892
  let accountsToUse = [...this.subaccounts];
1835
1893
  if (accountsToUse.length > seatsInBudget) {
1894
+ this.safeRecordParamsAdjusted({
1895
+ tick: bidsAtTick,
1896
+ blockNumber,
1897
+ maxSeats: this.subaccounts.length,
1898
+ winningBidCount: winningBids.length,
1899
+ reason: availableBalanceForBids - estimatedFeePlusTip < nextBid * BigInt(seatsInBudget) ? "insufficient-balance" : "max-budget-too-low",
1900
+ availableBalanceForBids
1901
+ });
1836
1902
  accountsToUse.sort((a, b) => {
1837
1903
  const isWinningA = winningAddresses.has(a.address);
1838
1904
  const isWinningB = winningAddresses.has(b.address);
@@ -1844,18 +1910,16 @@ var CohortBidder = class {
1844
1910
  });
1845
1911
  accountsToUse.length = seatsInBudget;
1846
1912
  }
1847
- if (accountsToUse.length > winningBids) {
1848
- this.pendingRequest = this.bid(nextBid, accountsToUse);
1913
+ if (accountsToUse.length > winningBids.length) {
1914
+ this.pendingRequest = this.submitBids(nextBid, accountsToUse);
1849
1915
  }
1850
- this.needsRebid = false;
1851
1916
  }
1852
- async bid(bidPerSeat, subaccounts) {
1853
- const prevLastBidTime = this.lastBidTime;
1917
+ async submitBids(microgonsPerSeat, subaccounts) {
1854
1918
  try {
1855
- this.lastBidTime = Date.now();
1919
+ this.bidsAttempted += subaccounts.length;
1856
1920
  const submitter = await this.accountset.createMiningBidTx({
1857
1921
  subaccounts,
1858
- bidAmount: bidPerSeat
1922
+ bidAmount: microgonsPerSeat
1859
1923
  });
1860
1924
  const tip = this.options.tipPerTransaction ?? 0n;
1861
1925
  const txResult = await submitter.submit({
@@ -1863,50 +1927,109 @@ var CohortBidder = class {
1863
1927
  useLatestNonce: true
1864
1928
  });
1865
1929
  const bidError = await txResult.inBlockPromise.then(() => void 0).catch((x) => x);
1866
- let blockNumber;
1867
- if (txResult.includedInBlock) {
1868
- const client = await this.client;
1869
- const api = await client.at(txResult.includedInBlock);
1870
- blockNumber = await api.query.system.number().then((x) => x.toNumber());
1930
+ const client = await this.clientPromise;
1931
+ let api = txResult.includedInBlock ? await client.at(txResult.includedInBlock) : client;
1932
+ this.lastBidTick = await api.query.ticks.currentTick().then((x) => x.toNumber());
1933
+ const blockNumber = await api.query.system.number().then((x) => x.toNumber());
1934
+ const bidAtTick = this.lastBidTick;
1935
+ try {
1936
+ this.callbacks?.onBidsSubmitted?.({
1937
+ tick: bidAtTick,
1938
+ blockNumber,
1939
+ microgonsPerSeat,
1940
+ txFeePlusTip: txResult.finalFee ?? 0n,
1941
+ submittedCount: subaccounts.length
1942
+ });
1943
+ } catch (error) {
1944
+ console.error("Error in onBidsSubmitted callback:", error);
1871
1945
  }
1872
1946
  const successfulBids = txResult.batchInterruptedIndex ?? subaccounts.length;
1873
1947
  this.txFees += txResult.finalFee ?? 0n;
1874
- if (blockNumber !== void 0) {
1875
- this.lastBidBlockNumber = Math.max(blockNumber, this.lastBidBlockNumber);
1876
- }
1877
- console.log("Done creating bids for cohort", {
1948
+ console.log("Result of bids for cohort", {
1878
1949
  successfulBids,
1879
- bidPerSeat,
1880
- blockNumber
1950
+ bidsPlaced: subaccounts.length,
1951
+ bidPerSeat: formatArgons(microgonsPerSeat),
1952
+ bidAtTick
1881
1953
  });
1882
- if (bidError) throw bidError;
1954
+ if (bidError) {
1955
+ try {
1956
+ this.callbacks?.onBidsRejected?.({
1957
+ tick: bidAtTick,
1958
+ blockNumber,
1959
+ microgonsPerSeat,
1960
+ submittedCount: subaccounts.length,
1961
+ rejectedCount: subaccounts.length - successfulBids,
1962
+ bidError
1963
+ });
1964
+ } catch (error) {
1965
+ console.error("Error in onBidsRejected callback:", error);
1966
+ }
1967
+ throw bidError;
1968
+ }
1883
1969
  } catch (err) {
1884
- this.lastBidTime = prevLastBidTime;
1885
1970
  console.error(`Error bidding for cohort ${this.cohortStartingFrameId}:`, err);
1886
- clearTimeout(this.retryTimeout);
1887
- this.retryTimeout = setTimeout(() => void this.checkCurrentSeats(), 1e3);
1888
1971
  } finally {
1889
1972
  this.pendingRequest = void 0;
1890
- }
1891
- if (this.needsRebid) {
1892
- this.needsRebid = false;
1893
- await this.checkCurrentSeats();
1973
+ this.scheduleEvaluation();
1894
1974
  }
1895
1975
  }
1896
- updateSeatsWon(next) {
1897
- this.winningBids.length = 0;
1898
- for (const x of next) {
1899
- const bid = x.bid.toBigInt();
1900
- const address = x.accountId.toHuman();
1901
- if (this.myAddresses.has(address)) {
1902
- this.winningBids.push({ address, bid });
1976
+ scheduleEvaluation() {
1977
+ if (this.isStopped) return;
1978
+ const millisPerTick = this.millisPerTick;
1979
+ const delayTicks = Math.max(this.options.bidDelay, 1);
1980
+ const delay = delayTicks * millisPerTick;
1981
+ if (this.evaluateInterval) clearInterval(this.evaluateInterval);
1982
+ console.log(`Scheduling next evaluation in ${delay}ms`);
1983
+ this.evaluateInterval = setInterval(() => this.checkWinningBids().catch(console.error), delay);
1984
+ }
1985
+ updateBidList(rawBids, blockNumber, tick) {
1986
+ try {
1987
+ let mostRecentBidTick = 0;
1988
+ let hasDiffs = this.currentBids.bids.length !== rawBids.length;
1989
+ const bids = [];
1990
+ for (let i = 0; i < rawBids.length; i += 1) {
1991
+ const rawBid = rawBids[i];
1992
+ const bidAtTick = rawBid.bidAtTick.toNumber();
1993
+ if (bidAtTick > mostRecentBidTick) {
1994
+ mostRecentBidTick = bidAtTick;
1995
+ }
1996
+ const address = rawBid.accountId.toHuman();
1997
+ const bidMicrogons = rawBid.bid.toBigInt();
1998
+ if (!hasDiffs) {
1999
+ const existing = this.currentBids.bids[i];
2000
+ hasDiffs = existing?.address !== address || existing?.bidMicrogons !== bidMicrogons;
2001
+ }
2002
+ bids.push({
2003
+ address,
2004
+ bidMicrogons,
2005
+ bidAtTick
2006
+ });
1903
2007
  }
2008
+ if (blockNumber > this.currentBids.atBlockNumber && hasDiffs) {
2009
+ this.currentBids.bids = bids;
2010
+ this.currentBids.mostRecentBidTick = mostRecentBidTick;
2011
+ this.currentBids.atTick = tick;
2012
+ this.currentBids.atBlockNumber = blockNumber;
2013
+ this.winningBids = bids.filter((x) => this.myAddresses.has(x.address));
2014
+ console.log("Now winning bids:", this.winningBids.length);
2015
+ if (this.callbacks?.onBidsUpdated) {
2016
+ this.callbacks.onBidsUpdated({
2017
+ bids: this.winningBids,
2018
+ atBlockNumber: blockNumber,
2019
+ tick: mostRecentBidTick
2020
+ });
2021
+ }
2022
+ }
2023
+ } catch (err) {
2024
+ console.error("Error processing updated bids list:", err);
1904
2025
  }
1905
2026
  }
1906
- async checkCurrentSeats() {
1907
- const client = await this.client;
1908
- const bids = await client.query.miningSlot.bidsForNextSlotCohort();
1909
- await this.checkWinningBids(bids);
2027
+ safeRecordParamsAdjusted(args) {
2028
+ try {
2029
+ this.callbacks?.onBidParamsAdjusted?.(args);
2030
+ } catch (err) {
2031
+ console.error("Error in onBidParamsAdjusted callback:", err);
2032
+ }
1910
2033
  }
1911
2034
  };
1912
2035
 
@@ -2244,7 +2367,7 @@ Raising Funds (Frame ${this.nextFrameId + 1}):`);
2244
2367
  };
2245
2368
 
2246
2369
  // src/BitcoinLocks.ts
2247
- import { hexToU8a as hexToU8a2, u8aToHex as u8aToHex2 } from "@polkadot/util";
2370
+ import { hexToU8a as hexToU8a2, u8aToHex as u8aToHex3 } from "@polkadot/util";
2248
2371
  var SATS_PER_BTC = 100000000n;
2249
2372
  var BitcoinLocks = class _BitcoinLocks {
2250
2373
  constructor(client) {
@@ -2283,7 +2406,7 @@ var BitcoinLocks = class _BitcoinLocks {
2283
2406
  const client = await this.client;
2284
2407
  const bitcoinNetwork = await client.query.bitcoinUtxos.bitcoinNetwork();
2285
2408
  return {
2286
- releaseExpirationBlocks: client.consts.bitcoinLocks.lockReleaseCosignDeadlineBlocks.toNumber(),
2409
+ lockReleaseCosignDeadlineFrames: client.consts.bitcoinLocks.lockReleaseCosignDeadlineFrames.toNumber(),
2287
2410
  pendingConfirmationExpirationBlocks: client.consts.bitcoinUtxos.maxPendingConfirmationBlocks.toNumber(),
2288
2411
  tickDurationMillis: await client.query.ticks.genesisTicker().then((x) => x.tickDurationMillis.toNumber()),
2289
2412
  bitcoinNetwork
@@ -2313,8 +2436,8 @@ var BitcoinLocks = class _BitcoinLocks {
2313
2436
  return;
2314
2437
  }
2315
2438
  const ref = refRaw.unwrap();
2316
- const txid = u8aToHex2(ref.txid);
2317
- const bitcoinTxid = u8aToHex2(ref.txid.reverse());
2439
+ const txid = u8aToHex3(ref.txid);
2440
+ const bitcoinTxid = u8aToHex3(ref.txid.reverse());
2318
2441
  const vout = ref.outputIndex.toNumber();
2319
2442
  return { txid, vout, bitcoinTxid };
2320
2443
  }
@@ -2324,19 +2447,18 @@ var BitcoinLocks = class _BitcoinLocks {
2324
2447
  const blockHash = await client.rpc.chain.getBlockHash(atHeight);
2325
2448
  client = await client.at(blockHash);
2326
2449
  }
2327
- const locksPendingRelease = await client.query.bitcoinLocks.locksPendingReleaseByUtxoId();
2328
- for (const [id, request] of locksPendingRelease.entries()) {
2329
- if (id.toNumber() === utxoId) {
2330
- return {
2331
- toScriptPubkey: request.toScriptPubkey.toHex(),
2332
- bitcoinNetworkFee: request.bitcoinNetworkFee.toBigInt(),
2333
- dueBlockHeight: request.cosignDueBlock.toNumber(),
2334
- vaultId: request.vaultId.toNumber(),
2335
- redemptionPrice: request.redemptionPrice.toBigInt()
2336
- };
2337
- }
2450
+ const requestMaybe = await client.query.bitcoinLocks.lockReleaseRequestsByUtxoId(utxoId);
2451
+ if (!requestMaybe.isSome) {
2452
+ return void 0;
2338
2453
  }
2339
- return void 0;
2454
+ const request = requestMaybe.unwrap();
2455
+ return {
2456
+ toScriptPubkey: request.toScriptPubkey.toHex(),
2457
+ bitcoinNetworkFee: request.bitcoinNetworkFee.toBigInt(),
2458
+ dueFrame: request.cosignDueFrame.toNumber(),
2459
+ vaultId: request.vaultId.toNumber(),
2460
+ redemptionPrice: request.redemptionPrice.toBigInt()
2461
+ };
2340
2462
  }
2341
2463
  async submitVaultSignature(args) {
2342
2464
  const { utxoId, vaultSignature, argonKeyring, txProgressCallback } = args;
@@ -2346,7 +2468,7 @@ var BitcoinLocks = class _BitcoinLocks {
2346
2468
  `Invalid vault signature length: ${vaultSignature.byteLength}. Must be 70-73 bytes.`
2347
2469
  );
2348
2470
  }
2349
- const signature = u8aToHex2(vaultSignature);
2471
+ const signature = u8aToHex3(vaultSignature);
2350
2472
  const tx = client.tx.bitcoinLocks.cosignRelease(utxoId, signature);
2351
2473
  const submitter = new TxSubmitter(client, tx, argonKeyring);
2352
2474
  return await submitter.submit({ txProgressCallback });
@@ -2506,7 +2628,8 @@ var BitcoinLocks = class _BitcoinLocks {
2506
2628
  argonKeyring
2507
2629
  );
2508
2630
  const marketPrice = await this.getMarketRate(BigInt(satoshis));
2509
- const securityFee = vault.calculateBitcoinFee(marketPrice);
2631
+ const isVaultOwner = argonKeyring.address === vault.operatorAccountId;
2632
+ const securityFee = isVaultOwner ? 0n : vault.calculateBitcoinFee(marketPrice);
2510
2633
  const { canAfford, availableBalance, txFee } = await submitter.canAfford({
2511
2634
  tip,
2512
2635
  unavailableBalance: securityFee + (args.reducedBalanceBy ?? 0n),
@@ -2519,17 +2642,8 @@ var BitcoinLocks = class _BitcoinLocks {
2519
2642
  }
2520
2643
  return { tx, securityFee, txFee };
2521
2644
  }
2522
- async initializeLock(args) {
2523
- const { argonKeyring, tip = 0n, txProgressCallback } = args;
2645
+ async getBitcoinLockFromTxResult(txResult) {
2524
2646
  const client = await this.client;
2525
- const { tx, securityFee } = await this.createInitializeLockTx(args);
2526
- const submitter = new TxSubmitter(client, tx, argonKeyring);
2527
- const txResult = await submitter.submit({
2528
- waitForBlock: true,
2529
- logResults: true,
2530
- tip,
2531
- txProgressCallback
2532
- });
2533
2647
  const blockHash = await txResult.inBlockPromise;
2534
2648
  const blockHeight = await client.at(blockHash).then((x) => x.query.system.number()).then((x) => x.toNumber());
2535
2649
  const utxoId = await this.getUtxoIdFromEvents(txResult.events) ?? 0;
@@ -2540,7 +2654,26 @@ var BitcoinLocks = class _BitcoinLocks {
2540
2654
  if (!lock) {
2541
2655
  throw new Error(`Lock with ID ${utxoId} not found after initialization`);
2542
2656
  }
2543
- return { lock, createdAtHeight: blockHeight, txResult, securityFee };
2657
+ return { lock, createdAtHeight: blockHeight, txResult };
2658
+ }
2659
+ async initializeLock(args) {
2660
+ const { argonKeyring, tip = 0n, txProgressCallback } = args;
2661
+ const client = await this.client;
2662
+ const { tx, securityFee } = await this.createInitializeLockTx(args);
2663
+ const submitter = new TxSubmitter(client, tx, argonKeyring);
2664
+ const txResult = await submitter.submit({
2665
+ waitForBlock: true,
2666
+ logResults: true,
2667
+ tip,
2668
+ txProgressCallback
2669
+ });
2670
+ const { lock, createdAtHeight } = await this.getBitcoinLockFromTxResult(txResult);
2671
+ return {
2672
+ lock,
2673
+ createdAtHeight,
2674
+ txResult,
2675
+ securityFee
2676
+ };
2544
2677
  }
2545
2678
  async requiredSatoshisForArgonLiquidity(argonAmount) {
2546
2679
  const marketRatePerBitcoin = await this.getMarketRate(SATS_PER_BTC);
@@ -2731,7 +2864,7 @@ function createKeyringPair(opts) {
2731
2864
  }
2732
2865
 
2733
2866
  // src/index.ts
2734
- import { u8aToHex as u8aToHex3, hexToU8a as hexToU8a3, u8aEq } from "@polkadot/util";
2867
+ import { u8aToHex as u8aToHex4, hexToU8a as hexToU8a3, u8aEq } from "@polkadot/util";
2735
2868
  import { GenericEvent as GenericEvent2, GenericBlock, GenericAddress } from "@polkadot/types/generic";
2736
2869
  import {
2737
2870
  BTreeMap,
@@ -2777,6 +2910,7 @@ export {
2777
2910
  TxSubmitter,
2778
2911
  TxResult,
2779
2912
  MICROGONS_PER_ARGON,
2913
+ miniSecretFromUri,
2780
2914
  formatArgons,
2781
2915
  formatPercent,
2782
2916
  filterUndefined,
@@ -2816,7 +2950,7 @@ export {
2816
2950
  mnemonicGenerate,
2817
2951
  waitForLoad,
2818
2952
  getClient,
2819
- u8aToHex3 as u8aToHex,
2953
+ u8aToHex4 as u8aToHex,
2820
2954
  hexToU8a3 as hexToU8a,
2821
2955
  u8aEq,
2822
2956
  GenericEvent2 as GenericEvent,
@@ -2845,4 +2979,4 @@ export {
2845
2979
  u64,
2846
2980
  u8
2847
2981
  };
2848
- //# sourceMappingURL=chunk-GZ2TLGCG.js.map
2982
+ //# sourceMappingURL=chunk-PXZPYJ4P.js.map