@argonprotocol/mainchain 1.3.6 → 1.3.8

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.
package/browser/index.js CHANGED
@@ -11,12 +11,11 @@ import { Keyring, HttpProvider, WsProvider, ApiPromise } from '@polkadot/api';
11
11
  export { Keyring } from '@polkadot/api';
12
12
  import { mnemonicGenerate, cryptoWaitReady } from '@polkadot/util-crypto';
13
13
  export { decodeAddress, mnemonicGenerate } from '@polkadot/util-crypto';
14
- import * as BigNumber from 'bignumber.js';
15
- import BigNumber__default from 'bignumber.js';
16
- import { u8aToHex, hexToU8a } from '@polkadot/util';
17
- export { hexToU8a, u8aEq, u8aToHex } from '@polkadot/util';
18
- import { printTable, Table } from 'console-table-printer';
14
+ import * as BigNumber2 from 'bignumber.js';
15
+ import BigNumber2__default from 'bignumber.js';
19
16
  import bs58check from 'bs58check';
17
+ import { hexToU8a, u8aToHex } from '@polkadot/util';
18
+ export { hexToU8a, u8aEq, u8aToHex } from '@polkadot/util';
20
19
  export { GenericAddress, GenericBlock, GenericEvent } from '@polkadot/types/generic';
21
20
  export { BTreeMap, Bool, Bytes, Compact, Enum, Null, Option, Range, Result, Struct, Text, Tuple, U256, U8aFixed, Vec, bool, i128, u128, u16, u32, u64, u8 } from '@polkadot/types-codec';
22
21
 
@@ -79,33 +78,11 @@ var WageProtector = class _WageProtector {
79
78
  }
80
79
  };
81
80
 
82
- // src/config.ts
83
- var config = {};
84
- function getEnvVar(key) {
85
- if (typeof process !== "undefined" && process.env) {
86
- return process.env[key];
87
- }
88
- return void 0;
89
- }
90
- function setConfig(newConfig) {
91
- config = { ...config, ...newConfig };
92
- }
93
- function getConfig() {
94
- return {
95
- debug: config.debug ?? getEnvVar("DEBUG") === "true",
96
- keysVersion: config.keysVersion ?? (getEnvVar("KEYS_VERSION") ? parseInt(getEnvVar("KEYS_VERSION")) : void 0),
97
- keysMnemonic: config.keysMnemonic ?? getEnvVar("KEYS_MNEMONIC"),
98
- subaccountRange: config.subaccountRange ?? getEnvVar("SUBACCOUNT_RANGE") ?? "0-9"
99
- };
100
- }
101
-
102
81
  // src/TxSubmitter.ts
103
82
  function logExtrinsicResult(result) {
104
- if (getConfig().debug) {
105
- const json = result.status.toJSON();
106
- const status = Object.keys(json)[0];
107
- console.debug('Transaction update: "%s"', status, json[status]);
108
- }
83
+ const json = result.status.toJSON();
84
+ const status = Object.keys(json)[0];
85
+ console.debug('Transaction update: "%s"', status, json[status]);
109
86
  }
110
87
  var TxSubmitter = class {
111
88
  constructor(client, tx, pair) {
@@ -137,7 +114,7 @@ var TxSubmitter = class {
137
114
  const result = new TxResult(this.client, logResults);
138
115
  result.txProgressCallback = options.txProgressCallback;
139
116
  let toHuman = this.tx.toHuman().method;
140
- let txString = [];
117
+ const txString = [];
141
118
  let api = formatCall(toHuman);
142
119
  const args = [];
143
120
  if (api === "proxy.proxy") {
@@ -201,10 +178,8 @@ var TxResult = class {
201
178
  this.finalizedResolve = resolve;
202
179
  this.finalizedReject = reject;
203
180
  });
204
- this.inBlockPromise.catch(() => {
205
- });
206
- this.finalizedPromise.catch(() => {
207
- });
181
+ this.inBlockPromise.catch(() => null);
182
+ this.finalizedPromise.catch(() => null);
208
183
  }
209
184
  onResult(result) {
210
185
  this.status = result.status;
@@ -254,26 +229,17 @@ var TxResult = class {
254
229
  this.finalizedReject(error);
255
230
  }
256
231
  };
257
- var { ROUND_FLOOR } = BigNumber;
232
+ var { ROUND_FLOOR } = BigNumber2;
258
233
  var MICROGONS_PER_ARGON = 1e6;
259
234
  function formatArgons(microgons) {
260
235
  if (microgons === void 0 || microgons === null) return "na";
261
236
  const isNegative = microgons < 0;
262
- let format = BigNumber__default(microgons.toString()).abs().div(MICROGONS_PER_ARGON).toFormat(2, ROUND_FLOOR);
237
+ let format = BigNumber2__default(microgons.toString()).abs().div(MICROGONS_PER_ARGON).toFormat(2, ROUND_FLOOR);
263
238
  if (format.endsWith(".00")) {
264
239
  format = format.slice(0, -3);
265
240
  }
266
241
  return `${isNegative ? "-" : ""}\u20B3${format}`;
267
242
  }
268
- function formatPercent(x) {
269
- if (!x) return "na";
270
- return `${x.times(100).decimalPlaces(3)}%`;
271
- }
272
- function filterUndefined(obj) {
273
- return Object.fromEntries(
274
- Object.entries(obj).filter(([_, value]) => value !== void 0 && value !== null)
275
- );
276
- }
277
243
  async function gettersToObject(obj) {
278
244
  if (obj === null || obj === void 0 || typeof obj !== "object") return obj;
279
245
  const keys = [];
@@ -299,36 +265,6 @@ async function gettersToObject(obj) {
299
265
  }
300
266
  return result;
301
267
  }
302
- function toFixedNumber(value, decimals) {
303
- const factor = new BigNumber__default(10).pow(decimals);
304
- const bn = new BigNumber__default(value);
305
- const int = bn.times(factor).integerValue(BigNumber__default.ROUND_DOWN);
306
- return BigInt(int.toFixed(0));
307
- }
308
- function convertNumberToFixedU128(value) {
309
- return toFixedNumber(value, 18);
310
- }
311
- function convertFixedU128ToBigNumber(fixedU128) {
312
- const decimalFactor = new BigNumber__default(10).pow(new BigNumber__default(18));
313
- const rawValue = new BigNumber__default(fixedU128.toString());
314
- return rawValue.div(decimalFactor);
315
- }
316
- function convertPermillToBigNumber(permill) {
317
- const decimalFactor = new BigNumber__default(1e6);
318
- const rawValue = new BigNumber__default(permill.toString());
319
- return rawValue.div(decimalFactor);
320
- }
321
- function convertNumberToPermill(value) {
322
- return toFixedNumber(value, 6);
323
- }
324
- function eventDataToJson(event) {
325
- const obj = {};
326
- event.data.forEach((data, index) => {
327
- const name = event.data.names?.[index];
328
- obj[name ?? `${index}`] = data.toJSON();
329
- });
330
- return obj;
331
- }
332
268
  function dispatchErrorToString(client, error) {
333
269
  let message = error.toString();
334
270
  if (error.isModule) {
@@ -377,79 +313,18 @@ function checkForExtrinsicSuccess(events, client) {
377
313
  }
378
314
  });
379
315
  }
380
- var JsonExt = class {
381
- static stringify(obj, space) {
382
- return JSON.stringify(
383
- obj,
384
- (_, v) => {
385
- if (typeof v === "bigint") {
386
- return `${v}n`;
387
- }
388
- if (v instanceof Uint8Array) {
389
- return {
390
- type: "Buffer",
391
- data: Array.from(v)
392
- // Convert Uint8Array to an array of numbers
393
- };
394
- }
395
- return v;
396
- },
397
- space
398
- );
399
- }
400
- static parse(str) {
401
- return JSON.parse(str, (_, v) => {
402
- if (typeof v === "string" && v.match(/^\d+n$/)) {
403
- return BigInt(v.slice(0, -1));
404
- }
405
- if (typeof v === "object" && v !== null && v.type === "Buffer" && Array.isArray(v.data)) {
406
- return Uint8Array.from(v.data);
407
- }
408
- return v;
409
- });
410
- }
411
- };
412
- function createNanoEvents() {
413
- return new TypedEmitter();
414
- }
415
- var TypedEmitter = class {
416
- constructor() {
417
- __publicField(this, "events", {});
418
- }
419
- emit(event, ...args) {
420
- for (const cb of this.events[event] || []) {
421
- cb(...args);
422
- }
423
- }
424
- on(event, cb) {
425
- var _a;
426
- ((_a = this.events)[event] || (_a[event] = [])).push(cb);
427
- return () => {
428
- this.events[event] = this.events[event]?.filter((i) => cb !== i);
429
- };
430
- }
431
- };
432
316
 
433
- // src/AccountRegistry.ts
434
- var _AccountRegistry = class _AccountRegistry {
435
- constructor(name) {
436
- __publicField(this, "namedAccounts", /* @__PURE__ */ new Map());
437
- __publicField(this, "me", "me");
438
- if (name) {
439
- this.me = name;
440
- }
441
- }
442
- getName(address) {
443
- return this.namedAccounts.get(address);
444
- }
445
- register(address, name) {
446
- this.namedAccounts.set(address, name);
447
- }
448
- };
449
- __publicField(_AccountRegistry, "factory", (name) => new _AccountRegistry(name));
450
- var AccountRegistry = _AccountRegistry;
317
+ // src/keyringUtils.ts
318
+ function keyringFromSuri(suri, cryptoType = "sr25519") {
319
+ return new Keyring({ type: cryptoType }).createFromUri(suri);
320
+ }
321
+ function createKeyringPair(opts) {
322
+ const { cryptoType } = opts;
323
+ const seed = mnemonicGenerate();
324
+ return keyringFromSuri(seed, cryptoType);
325
+ }
451
326
 
452
- // src/BlockWatch.ts
327
+ // src/header.ts
453
328
  function getTickFromHeader(client, header) {
454
329
  for (const x of header.digest.logs) {
455
330
  if (x.isPreRuntime) {
@@ -472,845 +347,7 @@ function getAuthorFromHeader(client, header) {
472
347
  }
473
348
  return void 0;
474
349
  }
475
- var BlockWatch = class {
476
- constructor(mainchain, options = {}) {
477
- this.mainchain = mainchain;
478
- this.options = options;
479
- __publicField(this, "events", createNanoEvents());
480
- __publicField(this, "locksById", {});
481
- __publicField(this, "unsubscribe");
482
- var _a, _b;
483
- (_a = this.options).shouldLog ?? (_a.shouldLog = true);
484
- (_b = this.options).finalizedBlocks ?? (_b.finalizedBlocks = false);
485
- }
486
- stop() {
487
- if (this.unsubscribe) {
488
- this.unsubscribe();
489
- this.unsubscribe = void 0;
490
- }
491
- }
492
- async start() {
493
- await this.watchBlocks();
494
- }
495
- async watchBlocks() {
496
- const client = await this.mainchain;
497
- const onBlock = async (header) => {
498
- try {
499
- await this.processBlock(header);
500
- } catch (e) {
501
- console.error("Error processing block", e);
502
- }
503
- };
504
- if (this.options.finalizedBlocks) {
505
- this.unsubscribe = await client.rpc.chain.subscribeFinalizedHeads(onBlock);
506
- } else {
507
- this.unsubscribe = await client.rpc.chain.subscribeNewHeads(onBlock);
508
- }
509
- }
510
- async processBlock(header) {
511
- const client = await this.mainchain;
512
- if (this.options.shouldLog) {
513
- console.log(`-------------------------------------
514
- BLOCK #${header.number}, ${header.hash.toHuman()}`);
515
- }
516
- const blockHash = header.hash;
517
- const api = await client.at(blockHash);
518
- const isBlockVote = await api.query.blockSeal.isBlockFromVoteSeal();
519
- if (!isBlockVote) {
520
- console.warn("> Compute reactivated!");
521
- }
522
- const events = await api.query.system.events();
523
- const reloadVaults = /* @__PURE__ */ new Set();
524
- let block = void 0;
525
- for (const { event, phase } of events) {
526
- const data = eventDataToJson(event);
527
- if (data.vaultId) {
528
- const vaultId = data.vaultId;
529
- reloadVaults.add(vaultId);
530
- }
531
- let logEvent = false;
532
- if (event.section === "liquidityPools") {
533
- if (client.events.liquidityPools.BidPoolDistributed.is(event)) {
534
- const { bidPoolBurned, bidPoolDistributed } = event.data;
535
- data.burned = formatArgons(bidPoolBurned.toBigInt());
536
- data.distributed = formatArgons(bidPoolDistributed.toBigInt());
537
- logEvent = true;
538
- } else if (client.events.liquidityPools.NextBidPoolCapitalLocked.is(event)) {
539
- const { totalActivatedCapital } = event.data;
540
- data.totalActivatedCapital = formatArgons(totalActivatedCapital.toBigInt());
541
- logEvent = true;
542
- }
543
- } else if (event.section === "bitcoinLocks") {
544
- if (client.events.bitcoinLocks.BitcoinLockCreated.is(event)) {
545
- const { lockPrice, utxoId, accountId, vaultId } = event.data;
546
- this.locksById[utxoId.toNumber()] = {
547
- vaultId: vaultId.toNumber(),
548
- lockPrice: lockPrice.toBigInt()
549
- };
550
- data.lockPrice = formatArgons(lockPrice.toBigInt());
551
- data.accountId = accountId.toHuman();
552
- reloadVaults.add(vaultId.toNumber());
553
- }
554
- logEvent = true;
555
- } else if (event.section === "mint") {
556
- logEvent = true;
557
- if (client.events.mint.MiningMint.is(event)) {
558
- const { amount } = event.data;
559
- data.amount = formatArgons(amount.toBigInt());
560
- }
561
- } else if (event.section === "miningSlot") {
562
- logEvent = true;
563
- if (client.events.miningSlot.SlotBidderAdded.is(event)) {
564
- data.amount = formatArgons(event.data.bidAmount.toBigInt());
565
- this.events.emit("mining-bid", header, {
566
- amount: event.data.bidAmount.toBigInt(),
567
- accountId: event.data.accountId.toString()
568
- });
569
- } else if (client.events.miningSlot.SlotBidderDropped.is(event)) {
570
- this.events.emit("mining-bid-ousted", header, {
571
- accountId: event.data.accountId.toString(),
572
- preservedArgonotHold: event.data.preservedArgonotHold.toPrimitive()
573
- });
574
- }
575
- } else if (event.section === "bitcoinUtxos") {
576
- logEvent = true;
577
- if (client.events.bitcoinUtxos.UtxoVerified.is(event)) {
578
- const { utxoId } = event.data;
579
- const details = await this.getBitcoinLockDetails(utxoId.toNumber(), blockHash);
580
- this.events.emit("bitcoin-verified", header, {
581
- utxoId: utxoId.toNumber(),
582
- vaultId: details.vaultId,
583
- lockPrice: details.lockPrice
584
- });
585
- data.lockPrice = formatArgons(details.lockPrice);
586
- reloadVaults.add(details.vaultId);
587
- }
588
- } else if (event.section === "system") {
589
- if (client.events.system.ExtrinsicFailed.is(event)) {
590
- const { dispatchError } = event.data;
591
- if (dispatchError.isModule) {
592
- const decoded = api.registry.findMetaError(dispatchError.asModule);
593
- const { name, section } = decoded;
594
- block ?? (block = await client.rpc.chain.getBlock(header.hash));
595
- const extrinsicIndex = phase.asApplyExtrinsic.toNumber();
596
- const ext = block.block.extrinsics[extrinsicIndex];
597
- if (this.options.shouldLog) {
598
- console.log(
599
- `> [Failed Tx] ${section}.${name} -> ${ext.method.section}.${ext.method.method} (nonce=${ext.nonce})`,
600
- ext.toHuman()?.method?.args
601
- );
602
- }
603
- } else {
604
- if (this.options.shouldLog) {
605
- console.log(`x [Failed Tx] ${dispatchError.toJSON()}`);
606
- }
607
- }
608
- }
609
- }
610
- if (this.options.shouldLog && logEvent) {
611
- console.log(`> ${event.section}.${event.method}`, data);
612
- }
613
- this.events.emit("event", header, event);
614
- }
615
- if (reloadVaults.size) this.events.emit("vaults-updated", header, reloadVaults);
616
- const tick = getTickFromHeader(client, header);
617
- const author = getAuthorFromHeader(client, header);
618
- this.events.emit(
619
- "block",
620
- header,
621
- { tick, author },
622
- events.map((x) => x.event)
623
- );
624
- }
625
- async getBitcoinLockDetails(utxoId, blockHash) {
626
- const client = await this.mainchain;
627
- const api = await client.at(blockHash);
628
- if (!this.locksById[utxoId]) {
629
- const lock = await api.query.bitcoinLocks.locksByUtxoId(utxoId);
630
- this.locksById[utxoId] = {
631
- vaultId: lock.value.vaultId.toNumber(),
632
- lockPrice: lock.value.lockPrice.toBigInt()
633
- };
634
- }
635
- return this.locksById[utxoId];
636
- }
637
- };
638
-
639
- // src/FrameCalculator.ts
640
- var FrameCalculator = class _FrameCalculator {
641
- constructor() {
642
- __publicField(this, "miningConfig");
643
- __publicField(this, "genesisTick");
644
- __publicField(this, "tickMillis");
645
- }
646
- async load(client) {
647
- return await this.getConfig(client);
648
- }
649
- async getForTick(client, tick) {
650
- const { ticksBetweenFrames, biddingStartTick } = await this.getConfig(client);
651
- const ticksSinceMiningStart = tick - biddingStartTick;
652
- return Math.floor(ticksSinceMiningStart / ticksBetweenFrames);
653
- }
654
- async getTickRangeForFrame(client, frameId) {
655
- const { ticksBetweenFrames, biddingStartTick } = await this.getConfig(client);
656
- return _FrameCalculator.calculateTickRangeForFrame(frameId, {
657
- ticksBetweenFrames,
658
- biddingStartTick
659
- });
660
- }
661
- async getForHeader(client, header) {
662
- if (header.number.toNumber() === 0) return 0;
663
- const tick = getTickFromHeader(client, header);
664
- if (tick === void 0) return void 0;
665
- return this.getForTick(client, tick);
666
- }
667
- static frameToDateRange(frameId, config2) {
668
- const [start, end] = _FrameCalculator.calculateTickRangeForFrame(frameId, config2);
669
- return [new Date(start * config2.tickMillis), new Date(end * config2.tickMillis)];
670
- }
671
- static calculateTickRangeForFrame(frameId, config2) {
672
- const { ticksBetweenFrames, biddingStartTick } = config2;
673
- const startingTick = biddingStartTick + Math.floor(frameId * ticksBetweenFrames);
674
- const endingTick = startingTick + ticksBetweenFrames - 1;
675
- return [startingTick, endingTick];
676
- }
677
- async getConfig(client) {
678
- this.miningConfig ?? (this.miningConfig = await client.query.miningSlot.miningConfig().then((x) => ({
679
- ticksBetweenSlots: x.ticksBetweenSlots.toNumber(),
680
- slotBiddingStartAfterTicks: x.slotBiddingStartAfterTicks.toNumber()
681
- })));
682
- this.genesisTick ?? (this.genesisTick = await client.query.ticks.genesisTick().then((x) => x.toNumber()));
683
- this.tickMillis ?? (this.tickMillis = await client.query.ticks.genesisTicker().then((x) => x.tickDurationMillis.toNumber()));
684
- const config2 = this.miningConfig;
685
- const genesisTick = this.genesisTick;
686
- return {
687
- ticksBetweenFrames: config2.ticksBetweenSlots,
688
- slotBiddingStartAfterTicks: config2.slotBiddingStartAfterTicks,
689
- genesisTick,
690
- tickMillis: this.tickMillis,
691
- biddingStartTick: genesisTick + config2.slotBiddingStartAfterTicks
692
- };
693
- }
694
- };
695
-
696
- // src/AccountMiners.ts
697
- var AccountMiners = class _AccountMiners {
698
- constructor(accountset, registeredMiners, options = { shouldLog: false }) {
699
- this.accountset = accountset;
700
- this.options = options;
701
- __publicField(this, "events", createNanoEvents());
702
- __publicField(this, "frameCalculator");
703
- __publicField(this, "trackedAccountsByAddress", {});
704
- this.frameCalculator = new FrameCalculator();
705
- for (const miner of registeredMiners) {
706
- this.trackedAccountsByAddress[miner.address] = {
707
- startingFrameId: miner.seat.startingFrameId,
708
- subaccountIndex: miner.subaccountIndex
709
- };
710
- }
711
- }
712
- async watch() {
713
- const blockWatch = new BlockWatch(this.accountset.client, {
714
- shouldLog: this.options.shouldLog
715
- });
716
- blockWatch.events.on("block", this.onBlock.bind(this));
717
- await blockWatch.start();
718
- return blockWatch;
719
- }
720
- async onBlock(header, digests, events) {
721
- var _a;
722
- const { author, tick } = digests;
723
- if (author) {
724
- const voteAuthor = this.trackedAccountsByAddress[author];
725
- if (voteAuthor && this.options.shouldLog) {
726
- console.log("> Our vote author", this.accountset.accountRegistry.getName(author));
727
- }
728
- } else {
729
- console.warn("> No vote author found");
730
- }
731
- const client = await this.accountset.client;
732
- const currentFrameId = await this.frameCalculator.getForTick(client, tick);
733
- let newMiners;
734
- const dataByCohort = { duringFrameId: currentFrameId };
735
- for (const event of events) {
736
- if (client.events.miningSlot.NewMiners.is(event)) {
737
- newMiners = {
738
- frameId: event.data.frameId.toNumber(),
739
- addresses: event.data.newMiners.map((x) => x.accountId.toHuman())
740
- };
741
- }
742
- if (client.events.blockRewards.RewardCreated.is(event)) {
743
- const { rewards } = event.data;
744
- for (const reward of rewards) {
745
- const { argons, ownership } = reward;
746
- const entry = this.trackedAccountsByAddress[author];
747
- if (entry) {
748
- dataByCohort[_a = entry.startingFrameId] ?? (dataByCohort[_a] = {
749
- argonsMinted: 0n,
750
- argonsMined: 0n,
751
- argonotsMined: 0n
752
- });
753
- dataByCohort[entry.startingFrameId].argonotsMined += ownership.toBigInt();
754
- dataByCohort[entry.startingFrameId].argonsMined += argons.toBigInt();
755
- this.events.emit("mined", header, {
756
- author,
757
- argons: argons.toBigInt(),
758
- argonots: ownership.toBigInt(),
759
- forCohortWithStartingFrameId: entry.startingFrameId,
760
- duringFrameId: currentFrameId
761
- });
762
- }
763
- }
764
- }
765
- if (client.events.mint.MiningMint.is(event)) {
766
- const { perMiner } = event.data;
767
- const amountPerMiner = perMiner.toBigInt();
768
- if (amountPerMiner > 0n) {
769
- for (const [address, info] of Object.entries(this.trackedAccountsByAddress)) {
770
- const { startingFrameId } = info;
771
- dataByCohort[startingFrameId] ?? (dataByCohort[startingFrameId] = {
772
- argonsMinted: 0n,
773
- argonsMined: 0n,
774
- argonotsMined: 0n
775
- });
776
- dataByCohort[startingFrameId].argonsMinted += amountPerMiner;
777
- this.events.emit("minted", header, {
778
- accountId: address,
779
- argons: amountPerMiner,
780
- forCohortWithStartingFrameId: startingFrameId,
781
- duringFrameId: currentFrameId
782
- });
783
- }
784
- }
785
- }
786
- }
787
- if (newMiners) {
788
- this.newCohortMiners(newMiners.frameId, newMiners.addresses);
789
- }
790
- return dataByCohort;
791
- }
792
- newCohortMiners(frameId, addresses) {
793
- for (const [address, info] of Object.entries(this.trackedAccountsByAddress)) {
794
- if (info.startingFrameId === frameId - 10) {
795
- delete this.trackedAccountsByAddress[address];
796
- }
797
- }
798
- for (const address of addresses) {
799
- const entry = this.accountset.subAccountsByAddress[address];
800
- if (entry) {
801
- this.trackedAccountsByAddress[address] = {
802
- startingFrameId: frameId,
803
- subaccountIndex: entry.index
804
- };
805
- }
806
- }
807
- }
808
- static async loadAt(accountset, options = {}) {
809
- const seats = await accountset.miningSeats(options.blockHash);
810
- const registered = seats.filter((x) => x.seat !== void 0);
811
- return new _AccountMiners(accountset, registered, {
812
- shouldLog: options.shouldLog ?? false
813
- });
814
- }
815
- };
816
- var Accountset = class {
817
- constructor(options) {
818
- __publicField(this, "txSubmitterPair");
819
- __publicField(this, "isProxy", false);
820
- __publicField(this, "seedAddress");
821
- __publicField(this, "subAccountsByAddress", {});
822
- __publicField(this, "accountRegistry");
823
- __publicField(this, "client");
824
- __publicField(this, "sessionKeyMnemonic");
825
- if ("seedAccount" in options) {
826
- this.txSubmitterPair = options.seedAccount;
827
- this.seedAddress = options.seedAccount.address;
828
- this.isProxy = false;
829
- } else {
830
- this.isProxy = options.isProxy;
831
- this.txSubmitterPair = options.txSubmitter;
832
- this.seedAddress = options.seedAddress;
833
- }
834
- this.sessionKeyMnemonic = options.sessionKeyMnemonic;
835
- this.accountRegistry = options.accountRegistry ?? AccountRegistry.factory(options.name);
836
- this.client = options.client;
837
- const defaultRange = options.subaccountRange ?? getDefaultSubaccountRange();
838
- this.accountRegistry.register(this.seedAddress, `${this.accountRegistry.me}//seed`);
839
- for (const i of defaultRange) {
840
- const pair = this.txSubmitterPair.derive(`//${i}`);
841
- this.subAccountsByAddress[pair.address] = { pair, index: i };
842
- this.accountRegistry.register(pair.address, `${this.accountRegistry.me}//${i}`);
843
- }
844
- }
845
- get addresses() {
846
- return [this.seedAddress, ...Object.keys(this.subAccountsByAddress)];
847
- }
848
- get namedAccounts() {
849
- return this.accountRegistry.namedAccounts;
850
- }
851
- async submitterBalance(blockHash) {
852
- const client = await this.client;
853
- const api = blockHash ? await client.at(blockHash) : client;
854
- const accountData = await api.query.system.account(this.txSubmitterPair.address);
855
- return accountData.data.free.toBigInt();
856
- }
857
- async balance(blockHash) {
858
- const client = await this.client;
859
- const api = blockHash ? await client.at(blockHash) : client;
860
- const accountData = await api.query.system.account(this.seedAddress);
861
- return accountData.data.free.toBigInt();
862
- }
863
- async totalArgonsAt(blockHash) {
864
- const client = await this.client;
865
- const api = blockHash ? await client.at(blockHash) : client;
866
- const addresses = this.addresses;
867
- const results = await api.query.system.account.multi(addresses);
868
- return results.map((account, i) => {
869
- const address = addresses[i];
870
- return {
871
- address,
872
- amount: account.data.free.toBigInt(),
873
- index: this.subAccountsByAddress[address]?.index ?? Number.NaN
874
- };
875
- });
876
- }
877
- async totalArgonotsAt(blockHash) {
878
- const client = await this.client;
879
- const api = blockHash ? await client.at(blockHash) : client;
880
- const addresses = this.addresses;
881
- const results = await api.query.ownership.account.multi(addresses);
882
- return results.map((account, i) => {
883
- const address = addresses[i];
884
- return {
885
- address,
886
- amount: account.free.toBigInt(),
887
- index: this.subAccountsByAddress[address]?.index ?? Number.NaN
888
- };
889
- });
890
- }
891
- async getAvailableMinerAccounts(maxSeats) {
892
- const miningSeats = await this.miningSeats();
893
- const subaccountRange = [];
894
- for (const seat of miningSeats) {
895
- if (seat.hasWinningBid) {
896
- continue;
897
- }
898
- if (seat.isLastDay || seat.seat === void 0) {
899
- subaccountRange.push({
900
- index: seat.subaccountIndex,
901
- isRebid: seat.seat !== void 0,
902
- address: seat.address
903
- });
904
- if (subaccountRange.length >= maxSeats) {
905
- break;
906
- }
907
- }
908
- }
909
- return subaccountRange;
910
- }
911
- async loadRegisteredMiners(api) {
912
- const addresses = Object.keys(this.subAccountsByAddress);
913
- const rawIndices = await api.query.miningSlot.accountIndexLookup.multi(addresses);
914
- const frameIds = [
915
- ...new Set(
916
- rawIndices.map((x) => x.isNone ? void 0 : x.value[0].toNumber()).filter((x) => x !== void 0)
917
- )
918
- ];
919
- const bidAmountsByFrame = {};
920
- if (frameIds.length) {
921
- console.log("Looking up cohorts for frames", frameIds);
922
- const cohorts = await api.query.miningSlot.minersByCohort.multi(frameIds);
923
- for (let i = 0; i < frameIds.length; i++) {
924
- const cohort = cohorts[i];
925
- const frameId = frameIds[i];
926
- bidAmountsByFrame[frameId] = cohort.map((x) => x.bid.toBigInt());
927
- }
928
- }
929
- const addressToMiningIndex = {};
930
- for (let i = 0; i < addresses.length; i++) {
931
- const address = addresses[i];
932
- if (rawIndices[i].isNone) continue;
933
- const [frameIdRaw, indexRaw] = rawIndices[i].value;
934
- const frameId = frameIdRaw.toNumber();
935
- const index = indexRaw.toNumber();
936
- const bidAmount = bidAmountsByFrame[frameId]?.[index];
937
- addressToMiningIndex[address] = {
938
- startingFrameId: frameId,
939
- index,
940
- bidAmount: bidAmount ?? 0n
941
- };
942
- }
943
- const nextFrameId = await api.query.miningSlot.nextFrameId();
944
- return addresses.map((address) => {
945
- const cohort = addressToMiningIndex[address];
946
- let isLastDay = false;
947
- if (cohort !== void 0) {
948
- isLastDay = nextFrameId.toNumber() - cohort.startingFrameId === 10;
949
- }
950
- return {
951
- address,
952
- seat: cohort,
953
- isLastDay,
954
- subaccountIndex: this.subAccountsByAddress[address]?.index ?? Number.NaN
955
- };
956
- });
957
- }
958
- async miningSeats(blockHash) {
959
- const client = await this.client;
960
- const api = blockHash ? await client.at(blockHash) : client;
961
- const miners = await this.loadRegisteredMiners(api);
962
- const nextCohort = await api.query.miningSlot.bidsForNextSlotCohort();
963
- return miners.map((miner) => {
964
- const bid = nextCohort.find((x) => x.accountId.toHuman() === miner.address);
965
- return {
966
- ...miner,
967
- hasWinningBid: !!bid,
968
- bidAmount: bid?.bid.toBigInt() ?? miner.seat?.bidAmount ?? 0n
969
- };
970
- });
971
- }
972
- async bids(blockHash) {
973
- const client = await this.client;
974
- const api = blockHash ? await client.at(blockHash) : client;
975
- const addresses = Object.keys(this.subAccountsByAddress);
976
- const nextCohort = await api.query.miningSlot.bidsForNextSlotCohort();
977
- const registrationsByAddress = Object.fromEntries(
978
- nextCohort.map((x, i) => [x.accountId.toHuman(), { ...x, index: i }])
979
- );
980
- return addresses.map((address) => {
981
- const entry = registrationsByAddress[address];
982
- return {
983
- address,
984
- bidPlace: entry?.index,
985
- bidAmount: entry?.bid?.toBigInt(),
986
- index: this.subAccountsByAddress[address]?.index ?? Number.NaN
987
- };
988
- });
989
- }
990
- async consolidate(subaccounts) {
991
- const client = await this.client;
992
- const accounts = this.getAccountsInRange(subaccounts);
993
- const results = [];
994
- await Promise.allSettled(
995
- accounts.map(({ pair, index }) => {
996
- if (!pair) {
997
- results.push({
998
- index,
999
- failedError: new Error(`No keypair for //${index}`)
1000
- });
1001
- return Promise.resolve();
1002
- }
1003
- return new Promise((resolve) => {
1004
- client.tx.utility.batchAll([
1005
- client.tx.balances.transferAll(this.seedAddress, true),
1006
- client.tx.ownership.transferAll(this.seedAddress, true)
1007
- ]).signAndSend(pair, (cb) => {
1008
- logExtrinsicResult(cb);
1009
- if (cb.dispatchError) {
1010
- const error = dispatchErrorToString(client, cb.dispatchError);
1011
- results.push({
1012
- index,
1013
- failedError: new Error(`Error consolidating //${index}: ${error}`)
1014
- });
1015
- resolve();
1016
- }
1017
- if (cb.isInBlock) {
1018
- results.push({ index, inBlock: cb.status.asInBlock.toHex() });
1019
- resolve();
1020
- }
1021
- }).catch((e) => {
1022
- results.push({ index, failedError: e });
1023
- resolve();
1024
- });
1025
- });
1026
- })
1027
- );
1028
- return results;
1029
- }
1030
- status(opts) {
1031
- const { argons, argonots, accountSubset, bids, seats } = opts;
1032
- const accounts = [
1033
- {
1034
- index: "main",
1035
- address: this.seedAddress,
1036
- argons: formatArgons(argons.find((x) => x.address === this.seedAddress)?.amount ?? 0n),
1037
- argonots: formatArgons(argonots.find((x) => x.address === this.seedAddress)?.amount ?? 0n)
1038
- }
1039
- ];
1040
- for (const [address, { index }] of Object.entries(this.subAccountsByAddress)) {
1041
- const argonAmount = argons.find((x) => x.address === address)?.amount ?? 0n;
1042
- const argonotAmount = argonots.find((x) => x.address === address)?.amount ?? 0n;
1043
- const bid = bids.find((x) => x.address === address);
1044
- const seat = seats.find((x) => x.address === address)?.seat;
1045
- const entry = {
1046
- index: ` //${index}`,
1047
- address,
1048
- argons: formatArgons(argonAmount),
1049
- argonots: formatArgons(argonotAmount),
1050
- seat,
1051
- bidPlace: bid?.bidPlace,
1052
- bidAmount: bid?.bidAmount ?? 0n
1053
- };
1054
- if (accountSubset) {
1055
- entry.isWorkingOn = accountSubset.some((x) => x.address === address);
1056
- }
1057
- accounts.push(entry);
1058
- }
1059
- return accounts;
1060
- }
1061
- async registerKeys(url) {
1062
- const client = await getClient(url.replace("ws:", "http:"));
1063
- const keys = this.keys();
1064
- for (const [name, key] of Object.entries(keys)) {
1065
- console.log("Registering key", name, key.publicKey);
1066
- const result = await client.rpc.author.insertKey(name, key.privateKey, key.publicKey);
1067
- const saved = await client.rpc.author.hasKey(key.publicKey, name);
1068
- if (!saved) {
1069
- console.error("Failed to register key", name, key.publicKey);
1070
- throw new Error(`Failed to register ${name} key ${key.publicKey}`);
1071
- }
1072
- console.log(`Registered ${name} key`, result.toHuman());
1073
- }
1074
- await client.disconnect();
1075
- }
1076
- keys(keysVersion) {
1077
- const config2 = getConfig();
1078
- let version = keysVersion ?? config2.keysVersion ?? 0;
1079
- const seedMnemonic = this.sessionKeyMnemonic ?? config2.keysMnemonic;
1080
- if (!seedMnemonic) {
1081
- throw new Error("KEYS_MNEMONIC environment variable not set. Cannot derive keys.");
1082
- }
1083
- const blockSealKey = `${seedMnemonic}//block-seal//${version}`;
1084
- const granKey = `${seedMnemonic}//grandpa//${version}`;
1085
- const blockSealAccount = new Keyring().createFromUri(blockSealKey, {
1086
- type: "ed25519"
1087
- });
1088
- const grandpaAccount = new Keyring().createFromUri(granKey, {
1089
- type: "ed25519"
1090
- });
1091
- return {
1092
- seal: {
1093
- privateKey: blockSealKey,
1094
- publicKey: u8aToHex(blockSealAccount.publicKey),
1095
- rawPublicKey: blockSealAccount.publicKey
1096
- },
1097
- gran: {
1098
- privateKey: granKey,
1099
- publicKey: u8aToHex(grandpaAccount.publicKey),
1100
- rawPublicKey: grandpaAccount.publicKey
1101
- }
1102
- };
1103
- }
1104
- async tx(tx) {
1105
- const client = await this.client;
1106
- return new TxSubmitter(client, tx, this.txSubmitterPair);
1107
- }
1108
- /**
1109
- * Create but don't submit a mining bid transaction.
1110
- * @param options
1111
- */
1112
- async createMiningBidTx(options) {
1113
- const client = await this.client;
1114
- const { bidAmount, subaccounts } = options;
1115
- const batch = client.tx.utility.batch(
1116
- subaccounts.map((x) => {
1117
- const keys = this.keys();
1118
- return client.tx.miningSlot.bid(
1119
- bidAmount,
1120
- {
1121
- grandpa: keys.gran.rawPublicKey,
1122
- blockSealAuthority: keys.seal.rawPublicKey
1123
- },
1124
- x.address
1125
- );
1126
- })
1127
- );
1128
- let tx = batch;
1129
- if (this.isProxy) {
1130
- tx = client.tx.proxy.proxy(this.seedAddress, "MiningBid", batch);
1131
- }
1132
- return new TxSubmitter(client, tx, this.txSubmitterPair);
1133
- }
1134
- /**
1135
- * Create a mining bid. This will create a bid for each account in the given range from the seed account as funding.
1136
- */
1137
- async createMiningBids(options) {
1138
- const accounts = this.getAccountsInRange(options.subaccountRange);
1139
- const client = await this.client;
1140
- const submitter = await this.createMiningBidTx({
1141
- ...options,
1142
- subaccounts: accounts
1143
- });
1144
- const { tip = 0n } = options;
1145
- const txFee = await submitter.feeEstimate(tip);
1146
- let minBalance = options.bidAmount * BigInt(accounts.length);
1147
- let totalFees = tip + 1n + txFee;
1148
- const seedBalance = await client.query.system.account(this.seedAddress).then((x) => x.data.free.toBigInt());
1149
- if (!this.isProxy) {
1150
- minBalance += totalFees;
1151
- }
1152
- if (seedBalance < minBalance) {
1153
- throw new Error(
1154
- `Insufficient balance to create mining bids. Seed account has ${formatArgons(
1155
- seedBalance
1156
- )} but needs ${formatArgons(minBalance)}`
1157
- );
1158
- }
1159
- if (this.isProxy) {
1160
- const { canAfford, availableBalance } = await submitter.canAfford({
1161
- tip
1162
- });
1163
- if (!canAfford) {
1164
- throw new Error(
1165
- `Insufficient balance to pay proxy fees. Proxy account has ${formatArgons(
1166
- availableBalance
1167
- )} but needs ${formatArgons(totalFees)}`
1168
- );
1169
- }
1170
- }
1171
- console.log("Creating bids", {
1172
- perSeatBid: options.bidAmount,
1173
- subaccounts: options.subaccountRange,
1174
- txFee
1175
- });
1176
- const txResult = await submitter.submit({
1177
- tip,
1178
- useLatestNonce: true
1179
- });
1180
- const bidError = await txResult.inBlockPromise.then(() => void 0).catch((x) => x);
1181
- return {
1182
- finalFee: txResult.finalFee,
1183
- bidError,
1184
- blockHash: txResult.includedInBlock,
1185
- successfulBids: txResult.batchInterruptedIndex !== void 0 ? txResult.batchInterruptedIndex : accounts.length
1186
- };
1187
- }
1188
- getAccountsInRange(range) {
1189
- const entries = new Set(range ?? getDefaultSubaccountRange());
1190
- return Object.entries(this.subAccountsByAddress).filter(([_, account]) => {
1191
- return entries.has(account.index);
1192
- }).map(([address, { pair, index }]) => ({ pair, index, address }));
1193
- }
1194
- async watchBlocks(shouldLog = false) {
1195
- const accountMiners = await AccountMiners.loadAt(this, { shouldLog });
1196
- await accountMiners.watch();
1197
- return accountMiners;
1198
- }
1199
- };
1200
- function getDefaultSubaccountRange() {
1201
- try {
1202
- const config2 = getConfig();
1203
- return parseSubaccountRange(config2.subaccountRange ?? "0-9");
1204
- } catch {
1205
- console.error(
1206
- "Failed to parse SUBACCOUNT_RANGE configuration. Defaulting to 0-9. Please check the format of the subaccountRange config value."
1207
- );
1208
- return Array.from({ length: 10 }, (_, i) => i);
1209
- }
1210
- }
1211
- function parseSubaccountRange(range) {
1212
- if (!range) {
1213
- return void 0;
1214
- }
1215
- const indices = [];
1216
- for (const entry of range.split(",")) {
1217
- if (entry.includes("-")) {
1218
- const [start, end] = entry.split("-").map((x) => parseInt(x, 10));
1219
- for (let i = start; i <= end; i++) {
1220
- indices.push(i);
1221
- }
1222
- continue;
1223
- }
1224
- const record = parseInt(entry.trim(), 10);
1225
- if (Number.isNaN(record) || !Number.isInteger(record)) {
1226
- throw new Error(`Invalid range entry: ${entry}`);
1227
- }
1228
- if (Number.isInteger(record)) {
1229
- indices.push(record);
1230
- }
1231
- }
1232
- return indices;
1233
- }
1234
- var MiningBids = class {
1235
- constructor(client, shouldLog = true) {
1236
- this.client = client;
1237
- this.shouldLog = shouldLog;
1238
- __publicField(this, "nextCohort", []);
1239
- }
1240
- async maxCohortSize() {
1241
- const client = await this.client;
1242
- return client.query.miningSlot.nextCohortSize().then((x) => x.toNumber());
1243
- }
1244
- async onCohortChange(options) {
1245
- const { onBiddingStart, onBiddingEnd } = options;
1246
- const client = await this.client;
1247
- let openCohortStartingFrameId = 0;
1248
- const unsubscribe = await client.queryMulti(
1249
- [
1250
- client.query.miningSlot.isNextSlotBiddingOpen,
1251
- client.query.miningSlot.nextFrameId
1252
- ],
1253
- async ([isBiddingOpen, rawNextCohortStartingFrameId]) => {
1254
- const nextFrameId = rawNextCohortStartingFrameId.toNumber();
1255
- if (isBiddingOpen.isTrue) {
1256
- if (openCohortStartingFrameId !== 0) {
1257
- await onBiddingEnd?.(openCohortStartingFrameId);
1258
- }
1259
- openCohortStartingFrameId = nextFrameId;
1260
- await onBiddingStart?.(nextFrameId);
1261
- } else {
1262
- await onBiddingEnd?.(nextFrameId);
1263
- openCohortStartingFrameId = 0;
1264
- }
1265
- }
1266
- );
1267
- return { unsubscribe };
1268
- }
1269
- async watch(accountNames, blockHash, printFn) {
1270
- const client = await this.client;
1271
- const api = blockHash ? await client.at(blockHash) : client;
1272
- const unsubscribe = await api.query.miningSlot.bidsForNextSlotCohort(async (next) => {
1273
- this.nextCohort = await Promise.all(next.map((x) => this.toBid(accountNames, x)));
1274
- if (!this.shouldLog) return;
1275
- console.clear();
1276
- const block = await client.query.system.number();
1277
- if (!printFn) {
1278
- console.log("At block", block.toNumber());
1279
- this.print();
1280
- } else {
1281
- printFn(block.toNumber());
1282
- }
1283
- });
1284
- return { unsubscribe };
1285
- }
1286
- async loadAt(accountNames, blockHash) {
1287
- const client = await this.client;
1288
- const api = blockHash ? await client.at(blockHash) : client;
1289
- const nextCohort = await api.query.miningSlot.bidsForNextSlotCohort();
1290
- this.nextCohort = await Promise.all(nextCohort.map((x) => this.toBid(accountNames, x)));
1291
- }
1292
- async toBid(accountNames, bid) {
1293
- return {
1294
- accountId: bid.accountId.toString(),
1295
- isOurs: accountNames.get(bid.accountId.toString()) ?? "n",
1296
- bidAmount: bid.bid.toBigInt()
1297
- };
1298
- }
1299
- print() {
1300
- const bids = this.nextCohort.map((bid) => {
1301
- return {
1302
- account: bid.accountId,
1303
- isOurs: bid.isOurs,
1304
- bidAmount: formatArgons(bid.bidAmount)
1305
- };
1306
- });
1307
- if (bids.length) {
1308
- console.log("\n\nMining Bids:");
1309
- printTable(bids);
1310
- }
1311
- }
1312
- };
1313
- var { ROUND_FLOOR: ROUND_FLOOR2 } = BigNumber;
350
+ var { ROUND_FLOOR: ROUND_FLOOR2 } = BigNumber2;
1314
351
  var Vault = class _Vault {
1315
352
  constructor(id, vault, tickDuration) {
1316
353
  this.tickDuration = tickDuration;
@@ -1335,8 +372,9 @@ var Vault = class _Vault {
1335
372
  }
1336
373
  load(vault) {
1337
374
  this.securitization = vault.securitization.toBigInt();
1338
- this.securitizationRatio = convertFixedU128ToBigNumber(
1339
- vault.securitizationRatio.toBigInt()
375
+ this.securitizationRatio = fromFixedNumber(
376
+ vault.securitizationRatio.toBigInt(),
377
+ FIXED_U128_DECIMALS
1340
378
  ).toNumber();
1341
379
  this.argonsLocked = vault.argonsLocked.toBigInt();
1342
380
  this.argonsPendingActivation = vault.argonsPendingActivation.toBigInt();
@@ -1347,12 +385,14 @@ var Vault = class _Vault {
1347
385
  }
1348
386
  }
1349
387
  this.terms = {
1350
- bitcoinAnnualPercentRate: convertFixedU128ToBigNumber(
1351
- vault.terms.bitcoinAnnualPercentRate.toBigInt()
388
+ bitcoinAnnualPercentRate: fromFixedNumber(
389
+ vault.terms.bitcoinAnnualPercentRate.toBigInt(),
390
+ FIXED_U128_DECIMALS
1352
391
  ),
1353
392
  bitcoinBaseFee: vault.terms.bitcoinBaseFee.toBigInt(),
1354
- liquidityPoolProfitSharing: convertPermillToBigNumber(
1355
- vault.terms.liquidityPoolProfitSharing.toBigInt()
393
+ liquidityPoolProfitSharing: fromFixedNumber(
394
+ vault.terms.liquidityPoolProfitSharing.toBigInt(),
395
+ PERMILL_DECIMALS
1356
396
  )
1357
397
  };
1358
398
  this.operatorAccountId = vault.operatorAccountId.toString();
@@ -1361,12 +401,14 @@ var Vault = class _Vault {
1361
401
  const [tickApply, terms] = vault.pendingTerms.value;
1362
402
  this.pendingTermsChangeTick = tickApply.toNumber();
1363
403
  this.pendingTerms = {
1364
- bitcoinAnnualPercentRate: convertFixedU128ToBigNumber(
1365
- terms.bitcoinAnnualPercentRate.toBigInt()
404
+ bitcoinAnnualPercentRate: fromFixedNumber(
405
+ terms.bitcoinAnnualPercentRate.toBigInt(),
406
+ FIXED_U128_DECIMALS
1366
407
  ),
1367
408
  bitcoinBaseFee: terms.bitcoinBaseFee.toBigInt(),
1368
- liquidityPoolProfitSharing: convertPermillToBigNumber(
1369
- vault.terms.liquidityPoolProfitSharing.toBigInt()
409
+ liquidityPoolProfitSharing: fromFixedNumber(
410
+ vault.terms.liquidityPoolProfitSharing.toBigInt(),
411
+ PERMILL_DECIMALS
1370
412
  )
1371
413
  };
1372
414
  }
@@ -1380,20 +422,20 @@ var Vault = class _Vault {
1380
422
  return [...this.argonsScheduledForRelease.values()].reduce((acc, val) => acc + val, 0n);
1381
423
  }
1382
424
  securitizationRatioBN() {
1383
- return new BigNumber__default(this.securitizationRatio);
425
+ return new BigNumber2__default(this.securitizationRatio);
1384
426
  }
1385
427
  recoverySecuritization() {
1386
- const reserved = new BigNumber__default(1).div(this.securitizationRatioBN());
428
+ const reserved = new BigNumber2__default(1).div(this.securitizationRatioBN());
1387
429
  return this.securitization - BigInt(reserved.multipliedBy(this.securitization.toString()).toFixed(0, ROUND_FLOOR2));
1388
430
  }
1389
431
  minimumSecuritization() {
1390
432
  return BigInt(
1391
- this.securitizationRatioBN().multipliedBy(this.argonsLocked.toString()).decimalPlaces(0, BigNumber__default.ROUND_CEIL).toString()
433
+ this.securitizationRatioBN().multipliedBy(this.argonsLocked.toString()).decimalPlaces(0, BigNumber2__default.ROUND_CEIL).toString()
1392
434
  );
1393
435
  }
1394
436
  activatedSecuritization() {
1395
437
  const activated = this.argonsLocked - this.argonsPendingActivation;
1396
- const maxRatio = BigNumber__default(Math.min(this.securitizationRatio, 2));
438
+ const maxRatio = BigNumber2__default(Math.min(this.securitizationRatio, 2));
1397
439
  return BigInt(maxRatio.multipliedBy(activated.toString()).toFixed(0, ROUND_FLOOR2));
1398
440
  }
1399
441
  /**
@@ -1404,7 +446,7 @@ var Vault = class _Vault {
1404
446
  return activated / 10n;
1405
447
  }
1406
448
  calculateBitcoinFee(amount) {
1407
- const fee = this.terms.bitcoinAnnualPercentRate.multipliedBy(Number(amount)).integerValue(BigNumber__default.ROUND_CEIL);
449
+ const fee = this.terms.bitcoinAnnualPercentRate.multipliedBy(Number(amount)).integerValue(BigNumber2__default.ROUND_CEIL);
1408
450
  return BigInt(fee.toString()) + this.terms.bitcoinBaseFee;
1409
451
  }
1410
452
  static async get(client, vaultId, tickDurationMillis) {
@@ -1415,7 +457,7 @@ var Vault = class _Vault {
1415
457
  const tickDuration = tickDurationMillis ?? await client.query.ticks.genesisTicker().then((x) => x.tickDurationMillis.toNumber());
1416
458
  return new _Vault(vaultId, rawVault.unwrap(), tickDuration);
1417
459
  }
1418
- static async create(client, keypair, args, config2 = {}) {
460
+ static async create(client, keypair, args, config = {}) {
1419
461
  const {
1420
462
  securitization,
1421
463
  securitizationRatio,
@@ -1436,18 +478,21 @@ var Vault = class _Vault {
1436
478
  xpubBytes = bytes;
1437
479
  }
1438
480
  }
1439
- let vaultParams = {
481
+ const vaultParams = {
1440
482
  terms: {
1441
483
  // convert to fixed u128
1442
- bitcoinAnnualPercentRate: toFixedNumber(annualPercentRate, 18),
484
+ bitcoinAnnualPercentRate: toFixedNumber(annualPercentRate, FIXED_U128_DECIMALS),
1443
485
  bitcoinBaseFee: BigInt(baseFee),
1444
- liquidityPoolProfitSharing: toFixedNumber(args.liquidityPoolProfitSharing, 6)
486
+ liquidityPoolProfitSharing: toFixedNumber(
487
+ args.liquidityPoolProfitSharing,
488
+ PERMILL_DECIMALS
489
+ )
1445
490
  },
1446
- securitizationRatio: toFixedNumber(securitizationRatio, 18),
491
+ securitizationRatio: toFixedNumber(securitizationRatio, FIXED_U128_DECIMALS),
1447
492
  securitization: BigInt(securitization),
1448
493
  bitcoinXpubkey: xpubBytes
1449
494
  };
1450
- let tx = new TxSubmitter(client, client.tx.vaults.create(vaultParams), keypair);
495
+ const tx = new TxSubmitter(client, client.tx.vaults.create(vaultParams), keypair);
1451
496
  if (doNotExceedBalance) {
1452
497
  const finalTip = tip ?? 0n;
1453
498
  let txFee = await tx.feeEstimate(finalTip);
@@ -1484,880 +529,39 @@ var Vault = class _Vault {
1484
529
  if (rawVault.isNone) {
1485
530
  throw new Error("Vault creation failed, vault not found");
1486
531
  }
1487
- const tickDuration = config2.tickDurationMillis ?? await client.query.ticks.genesisTicker().then((x) => x.tickDurationMillis.toNumber());
532
+ const tickDuration = config.tickDurationMillis ?? await client.query.ticks.genesisTicker().then((x) => x.tickDurationMillis.toNumber());
1488
533
  const vault = new _Vault(vaultId, rawVault.unwrap(), tickDuration);
1489
534
  return { vault, txResult: result };
1490
535
  }
1491
536
  };
1492
- var VaultMonitor = class {
1493
- constructor(accountset, alerts = {}, options = {}) {
1494
- this.accountset = accountset;
1495
- this.alerts = alerts;
1496
- this.options = options;
1497
- __publicField(this, "events", createNanoEvents());
1498
- __publicField(this, "vaultsById", {});
1499
- __publicField(this, "blockWatch");
1500
- __publicField(this, "mainchain");
1501
- __publicField(this, "activatedCapitalByVault", {});
1502
- __publicField(this, "lastPrintedBids");
1503
- __publicField(this, "miningBids");
1504
- __publicField(this, "tickDuration", 0);
1505
- __publicField(this, "vaultOnlyWatchMode", false);
1506
- __publicField(this, "shouldLog", true);
1507
- this.mainchain = accountset.client;
1508
- if (options.vaultOnlyWatchMode !== void 0) {
1509
- this.vaultOnlyWatchMode = options.vaultOnlyWatchMode;
1510
- }
1511
- if (options.shouldLog !== void 0) {
1512
- this.shouldLog = options.shouldLog;
1513
- }
1514
- this.miningBids = new MiningBids(this.mainchain, this.shouldLog);
1515
- this.blockWatch = new BlockWatch(this.mainchain, {
1516
- shouldLog: this.shouldLog
1517
- });
1518
- this.blockWatch.events.on(
1519
- "vaults-updated",
1520
- (header, vaultIds) => this.onVaultsUpdated(header.hash, vaultIds)
1521
- );
1522
- this.blockWatch.events.on("mining-bid", async (header, _bid) => {
1523
- await this.miningBids.loadAt(this.accountset.namedAccounts, header.hash);
1524
- this.printBids(header.hash);
1525
- });
1526
- this.blockWatch.events.on("mining-bid-ousted", async (header) => {
1527
- await this.miningBids.loadAt(this.accountset.namedAccounts, header.hash);
1528
- this.printBids(header.hash);
1529
- });
1530
- }
1531
- stop() {
1532
- this.blockWatch.stop();
1533
- }
1534
- async monitor(justPrint = false) {
1535
- const client = await this.mainchain;
1536
- this.tickDuration = (await client.query.ticks.genesisTicker()).tickDurationMillis.toNumber();
1537
- const blockHeader = await client.rpc.chain.getHeader();
1538
- const blockHash = new Uint8Array(blockHeader.hash);
1539
- console.log(
1540
- `${justPrint ? "Run" : "Started"} at block ${blockHeader.number} - ${blockHeader.hash.toHuman()}`
1541
- );
1542
- await this.miningBids.loadAt(this.accountset.namedAccounts, blockHash);
1543
- const vaults = await client.query.vaults.vaultsById.entries();
1544
- for (const [storageKey, rawVault] of vaults) {
1545
- const vaultId = storageKey.args[0].toNumber();
1546
- this.updateVault(vaultId, rawVault);
1547
- }
1548
- await client.query.liquidityPools.capitalRaising((x) => {
1549
- var _a;
1550
- this.activatedCapitalByVault = {};
1551
- for (const entry of x) {
1552
- const vaultId = entry.vaultId.toNumber();
1553
- this.activatedCapitalByVault[vaultId] = entry.activatedCapital.toBigInt();
1554
- }
1555
- for (const [vaultId, vault] of Object.entries(this.vaultsById)) {
1556
- const id = Number(vaultId);
1557
- (_a = this.activatedCapitalByVault)[id] ?? (_a[id] = 0n);
1558
- this.checkMiningBondAlerts(id, vault);
1559
- }
1560
- });
1561
- this.printVaults();
1562
- if (!this.vaultOnlyWatchMode && this.shouldLog) {
1563
- this.miningBids.print();
1564
- }
1565
- if (!justPrint) await this.blockWatch.start();
1566
- }
1567
- printVaults() {
1568
- if (!this.shouldLog) return;
1569
- const vaults = [];
1570
- for (const [vaultId, vault] of Object.entries(this.vaultsById)) {
1571
- vaults.push({
1572
- id: vaultId,
1573
- btcSpace: `${formatArgons(vault.availableBitcoinSpace())} (${formatArgons(vault.argonsPendingActivation)} pending)`,
1574
- btcDeal: `${formatArgons(vault.terms.bitcoinBaseFee)} + ${formatPercent(vault.terms.bitcoinAnnualPercentRate)}`,
1575
- securitization: `${formatArgons(vault.securitization)} at ${vault.securitizationRatio}x`,
1576
- securActivated: `${formatArgons(vault.activatedSecuritizationPerSlot())}/slot`,
1577
- liquidPoolDeal: `${formatPercent(vault.terms.liquidityPoolProfitSharing)} sharing`,
1578
- operator: `${this.accountset.namedAccounts.has(vault.operatorAccountId) ? ` (${this.accountset.namedAccounts.get(vault.operatorAccountId)})` : vault.operatorAccountId}`,
1579
- state: vault.isClosed ? "closed" : vault.openedDate < /* @__PURE__ */ new Date() ? "open" : "pending"
1580
- });
1581
- }
1582
- if (vaults.length) {
1583
- if (this.vaultOnlyWatchMode) {
1584
- console.clear();
1585
- }
1586
- console.log("\n\nVaults:");
1587
- printTable(vaults);
1588
- }
1589
- }
1590
- async recheckAfterActive(vaultId) {
1591
- const activationDate = this.vaultsById[vaultId].openedDate;
1592
- if (this.shouldLog) {
1593
- console.log(`Waiting for vault ${vaultId} to activate ${activationDate}`);
1594
- }
1595
- await new Promise((resolve) => setTimeout(resolve, activationDate.getTime() - Date.now()));
1596
- const client = await this.mainchain;
1597
- let isReady = false;
1598
- while (!isReady) {
1599
- const rawVault = await client.query.vaults.vaultsById(vaultId);
1600
- if (!rawVault.isSome) return;
1601
- const vault = new Vault(vaultId, rawVault.value, this.tickDuration);
1602
- this.vaultsById[vaultId] = vault;
1603
- if (vault.isClosed) return;
1604
- if (vault.openedDate < /* @__PURE__ */ new Date()) {
1605
- isReady = true;
1606
- break;
1607
- }
1608
- await new Promise((resolve) => setTimeout(resolve, 100));
1609
- }
1610
- this.checkAlerts(vaultId, this.vaultsById[vaultId]);
1611
- }
1612
- async onVaultsUpdated(blockHash, vaultIds) {
1613
- await this.reloadVaultsAt([...vaultIds], blockHash).catch((err) => {
1614
- console.error(`Failed to reload vault ${[...vaultIds]} at block ${blockHash}:`, err);
1615
- });
1616
- this.printVaults();
1617
- }
1618
- async reloadVaultsAt(vaultIds, blockHash) {
1619
- const client = await this.mainchain;
1620
- const api = await client.at(blockHash);
1621
- const vaults = await api.query.vaults.vaultsById.multi(vaultIds);
1622
- for (let i = 0; i < vaultIds.length; i += 1) {
1623
- this.updateVault(vaultIds[i], vaults[i]);
1624
- }
1625
- }
1626
- updateVault(vaultId, rawVault) {
1627
- if (rawVault.isNone) return;
1628
- const vault = new Vault(vaultId, rawVault.value, this.tickDuration);
1629
- this.vaultsById[vaultId] = vault;
1630
- if (vault.openedDate > /* @__PURE__ */ new Date()) {
1631
- void this.recheckAfterActive(vaultId);
1632
- } else {
1633
- this.checkAlerts(vaultId, vault);
1634
- }
1635
- }
1636
- checkAlerts(vaultId, vault) {
1637
- if (this.alerts.bitcoinSpaceAvailable !== void 0) {
1638
- const availableBitcoinSpace = vault.availableBitcoinSpace();
1639
- if (availableBitcoinSpace >= this.alerts.bitcoinSpaceAvailable) {
1640
- console.warn(
1641
- `Vault ${vaultId} has available bitcoins above ${formatArgons(this.alerts.bitcoinSpaceAvailable)}`
1642
- );
1643
- this.events.emit("bitcoin-space-above", vaultId, availableBitcoinSpace);
1644
- }
1645
- }
1646
- }
1647
- checkMiningBondAlerts(vaultId, vault) {
1648
- if (this.alerts.liquidityPoolSpaceAvailable === void 0) return;
1649
- const activatedSecuritization = vault.activatedSecuritizationPerSlot();
1650
- const capitalization = this.activatedCapitalByVault[vaultId] ?? 0n;
1651
- const available = activatedSecuritization - capitalization;
1652
- if (available >= this.alerts.liquidityPoolSpaceAvailable) {
1653
- this.events.emit("liquidity-pool-space-above", vaultId, available);
1654
- }
1655
- }
1656
- printBids(blockHash) {
1657
- if (!this.shouldLog) return;
1658
- if (this.lastPrintedBids === blockHash) return;
1659
- this.miningBids.print();
1660
- this.lastPrintedBids = blockHash;
1661
- }
1662
- };
1663
-
1664
- // src/CohortBidder.ts
1665
- var CohortBidder = class {
1666
- constructor(accountset, cohortStartingFrameId, subaccounts, options, callbacks) {
1667
- this.accountset = accountset;
1668
- this.cohortStartingFrameId = cohortStartingFrameId;
1669
- this.subaccounts = subaccounts;
1670
- this.options = options;
1671
- this.callbacks = callbacks;
1672
- __publicField(this, "txFees", 0n);
1673
- __publicField(this, "bidsAttempted", 0);
1674
- __publicField(this, "winningBids", []);
1675
- __publicField(this, "myAddresses", /* @__PURE__ */ new Set());
1676
- __publicField(this, "currentBids", {
1677
- bids: [],
1678
- mostRecentBidTick: 0,
1679
- atTick: 0,
1680
- atBlockNumber: 0
1681
- });
1682
- __publicField(this, "unsubscribe");
1683
- __publicField(this, "pendingRequest");
1684
- __publicField(this, "isStopped", false);
1685
- __publicField(this, "millisPerTick");
1686
- __publicField(this, "minIncrement", 10000n);
1687
- __publicField(this, "nextCohortSize");
1688
- __publicField(this, "lastBidTick", 0);
1689
- __publicField(this, "evaluateInterval");
1690
- this.subaccounts.forEach((x) => {
1691
- this.myAddresses.add(x.address);
1692
- });
1693
- }
1694
- get clientPromise() {
1695
- return this.accountset.client;
1696
- }
1697
- async start() {
1698
- console.log(`Starting cohort ${this.cohortStartingFrameId} bidder`, {
1699
- maxBid: formatArgons(this.options.maxBid),
1700
- minBid: formatArgons(this.options.minBid),
1701
- bidIncrement: formatArgons(this.options.bidIncrement),
1702
- maxBudget: formatArgons(this.options.maxBudget),
1703
- bidDelay: this.options.bidDelay,
1704
- subaccounts: this.subaccounts
1705
- });
1706
- const client = await this.clientPromise;
1707
- this.minIncrement = client.consts.miningSlot.bidIncrements.toBigInt();
1708
- this.nextCohortSize = await client.query.miningSlot.nextCohortSize().then((x) => x.toNumber());
1709
- if (this.subaccounts.length > this.nextCohortSize) {
1710
- console.info(
1711
- `Cohort size ${this.nextCohortSize} is less than provided subaccounts ${this.subaccounts.length}.`
1712
- );
1713
- this.subaccounts.length = this.nextCohortSize;
1714
- }
1715
- this.millisPerTick = await client.query.ticks.genesisTicker().then((x) => x.tickDurationMillis.toNumber());
1716
- let didStart = false;
1717
- this.unsubscribe = await client.queryMulti(
1718
- [
1719
- client.query.miningSlot.bidsForNextSlotCohort,
1720
- client.query.miningSlot.nextFrameId,
1721
- client.query.ticks.currentTick,
1722
- client.query.system.number
1723
- ],
1724
- async ([rawBids, nextFrameId, currentTick, blockNumber]) => {
1725
- if (nextFrameId.toNumber() === this.cohortStartingFrameId) {
1726
- this.updateBidList(rawBids, blockNumber.toNumber(), currentTick.toNumber());
1727
- if (!didStart) {
1728
- didStart = true;
1729
- this.scheduleEvaluation();
1730
- void this.checkWinningBids();
1731
- }
1732
- }
1733
- }
1734
- );
1735
- }
1736
- async stop() {
1737
- if (this.isStopped) return this.winningBids;
1738
- this.isStopped = true;
1739
- clearInterval(this.evaluateInterval);
1740
- console.log("Stopping bidder for cohort", this.cohortStartingFrameId);
1741
- if (this.unsubscribe) {
1742
- this.unsubscribe();
1743
- }
1744
- const client = await this.clientPromise;
1745
- const [nextFrameId, isBiddingOpen] = await client.queryMulti([
1746
- client.query.miningSlot.nextFrameId,
1747
- client.query.miningSlot.isNextSlotBiddingOpen
1748
- ]);
1749
- if (nextFrameId.toNumber() === this.cohortStartingFrameId && isBiddingOpen.isTrue) {
1750
- console.log("Bidding is still open, waiting for it to close");
1751
- await new Promise(async (resolve) => {
1752
- const unsub = await client.query.miningSlot.isNextSlotBiddingOpen((isOpen) => {
1753
- if (isOpen.isFalse) {
1754
- unsub();
1755
- resolve();
1756
- }
1757
- });
1758
- });
1759
- }
1760
- void await this.pendingRequest;
1761
- const currentFrameId = await client.query.miningSlot.nextFrameId();
1762
- let blockNumber;
1763
- if (currentFrameId.toNumber() > this.cohortStartingFrameId) {
1764
- blockNumber = await client.query.miningSlot.frameStartBlockNumbers().then((x) => x[0]?.toNumber()) - 1;
1765
- } else {
1766
- blockNumber = await client.query.system.number().then((x) => x.toNumber());
1767
- }
1768
- const blockHash = await client.query.system.blockHash(blockNumber);
1769
- const api = await client.at(blockHash);
1770
- const rawBids = await api.query.miningSlot.bidsForNextSlotCohort();
1771
- const currentTick = await api.query.ticks.currentTick().then((x) => x.toNumber());
1772
- this.updateBidList(rawBids, blockNumber, currentTick);
1773
- console.log("Bidder stopped", {
1774
- cohortStartingFrameId: this.cohortStartingFrameId,
1775
- blockNumber,
1776
- winningBids: this.winningBids
1777
- });
1778
- return this.winningBids;
1779
- }
1780
- async checkWinningBids() {
1781
- if (this.isStopped) return;
1782
- if (this.pendingRequest) {
1783
- console.log("Current bid is still in progress, skipping this check");
1784
- return;
1785
- }
1786
- if (this.currentBids.mostRecentBidTick < this.lastBidTick) {
1787
- console.log(`Waiting for bids more recent than our last attempt.`, {
1788
- ownAttemptedBidTick: this.lastBidTick,
1789
- liveBidsTick: this.currentBids.mostRecentBidTick
1790
- });
1791
- return;
1792
- }
1793
- const bids = [...this.currentBids.bids];
1794
- const bidsAtTick = this.currentBids.atTick;
1795
- const blockNumber = this.currentBids.atBlockNumber;
1796
- const winningBids = bids.filter((x) => this.myAddresses.has(x.address));
1797
- if (winningBids.length >= this.subaccounts.length) {
1798
- console.log(`No updates needed. Winning all remaining seats (${winningBids.length}).`);
1799
- return;
1800
- }
1801
- console.log(
1802
- `Checking bids for cohort ${this.cohortStartingFrameId}, Still trying for seats: ${this.subaccounts.length}`
1803
- );
1804
- const winningAddresses = new Set(winningBids.map((x) => x.address));
1805
- let lowestBid;
1806
- let myAllocatedBids = 0n;
1807
- for (const bid of bids) {
1808
- lowestBid ?? (lowestBid = bid.bidMicrogons);
1809
- if (this.myAddresses.has(bid.address)) {
1810
- myAllocatedBids += bid.bidMicrogons;
1811
- } else {
1812
- if (bid.bidMicrogons < lowestBid) {
1813
- lowestBid = bid.bidMicrogons;
1814
- }
1815
- }
1816
- }
1817
- lowestBid ?? (lowestBid = -this.options.bidIncrement);
1818
- let nextBid = lowestBid + this.options.bidIncrement;
1819
- if (nextBid < this.options.minBid) {
1820
- nextBid = this.options.minBid;
1821
- }
1822
- if (nextBid > this.options.maxBid) {
1823
- nextBid = this.options.maxBid;
1824
- }
1825
- const fakeTx = await this.accountset.createMiningBidTx({
1826
- subaccounts: this.subaccounts,
1827
- bidAmount: nextBid
1828
- });
1829
- let availableBalanceForBids = await this.accountset.submitterBalance();
1830
- availableBalanceForBids += myAllocatedBids;
1831
- const tip = this.options.tipPerTransaction ?? 0n;
1832
- const feeEstimate = await fakeTx.feeEstimate(tip);
1833
- const estimatedFeePlusTip = feeEstimate + tip;
1834
- let budgetForSeats = this.options.maxBudget - estimatedFeePlusTip;
1835
- if (budgetForSeats > availableBalanceForBids) {
1836
- budgetForSeats = availableBalanceForBids - estimatedFeePlusTip;
1837
- }
1838
- if (nextBid < lowestBid) {
1839
- console.log(
1840
- `Next bid within parameters is ${formatArgons(nextBid)}, but it's not enough. Current lowest bid is ${formatArgons(lowestBid)}.`
1841
- );
1842
- this.safeRecordParamsAdjusted({
1843
- tick: bidsAtTick,
1844
- blockNumber,
1845
- maxSeats: 0,
1846
- winningBidCount: winningBids.length,
1847
- reason: "max-bid-too-low",
1848
- availableBalanceForBids
1849
- });
1850
- return;
1851
- }
1852
- if (nextBid - lowestBid < Number(this.minIncrement)) {
1853
- console.log(
1854
- `Can't make any more bids for ${this.cohortStartingFrameId} with given constraints (next bid below min increment).`,
1855
- {
1856
- lowestCurrentBid: formatArgons(lowestBid),
1857
- nextAttemptedBid: formatArgons(nextBid),
1858
- maxBid: formatArgons(this.options.maxBid)
1859
- }
1860
- );
1861
- this.safeRecordParamsAdjusted({
1862
- tick: bidsAtTick,
1863
- blockNumber,
1864
- maxSeats: 0,
1865
- winningBidCount: winningBids.length,
1866
- reason: "max-bid-too-low",
1867
- availableBalanceForBids
1868
- });
1869
- return;
1870
- }
1871
- const seatsInBudget = nextBid === 0n ? this.subaccounts.length : Number(budgetForSeats / nextBid);
1872
- let accountsToUse = [...this.subaccounts];
1873
- if (accountsToUse.length > seatsInBudget) {
1874
- this.safeRecordParamsAdjusted({
1875
- tick: bidsAtTick,
1876
- blockNumber,
1877
- maxSeats: this.subaccounts.length,
1878
- winningBidCount: winningBids.length,
1879
- reason: availableBalanceForBids - estimatedFeePlusTip < nextBid * BigInt(seatsInBudget) ? "insufficient-balance" : "max-budget-too-low",
1880
- availableBalanceForBids
1881
- });
1882
- accountsToUse.sort((a, b) => {
1883
- const isWinningA = winningAddresses.has(a.address);
1884
- const isWinningB = winningAddresses.has(b.address);
1885
- if (isWinningA && !isWinningB) return -1;
1886
- if (!isWinningA && isWinningB) return 1;
1887
- if (a.isRebid && !b.isRebid) return -1;
1888
- if (!a.isRebid && b.isRebid) return 1;
1889
- return a.index - b.index;
1890
- });
1891
- accountsToUse.length = seatsInBudget;
1892
- }
1893
- if (accountsToUse.length > winningBids.length) {
1894
- this.pendingRequest = this.submitBids(nextBid, accountsToUse);
1895
- }
1896
- }
1897
- async submitBids(microgonsPerSeat, subaccounts) {
1898
- try {
1899
- this.bidsAttempted += subaccounts.length;
1900
- const submitter = await this.accountset.createMiningBidTx({
1901
- subaccounts,
1902
- bidAmount: microgonsPerSeat
1903
- });
1904
- const tip = this.options.tipPerTransaction ?? 0n;
1905
- const txResult = await submitter.submit({
1906
- tip,
1907
- useLatestNonce: true
1908
- });
1909
- const bidError = await txResult.inBlockPromise.then(() => void 0).catch((x) => x);
1910
- const client = await this.clientPromise;
1911
- let api = txResult.includedInBlock ? await client.at(txResult.includedInBlock) : client;
1912
- this.lastBidTick = await api.query.ticks.currentTick().then((x) => x.toNumber());
1913
- const blockNumber = await api.query.system.number().then((x) => x.toNumber());
1914
- const bidAtTick = this.lastBidTick;
1915
- try {
1916
- this.callbacks?.onBidsSubmitted?.({
1917
- tick: bidAtTick,
1918
- blockNumber,
1919
- microgonsPerSeat,
1920
- txFeePlusTip: txResult.finalFee ?? 0n,
1921
- submittedCount: subaccounts.length
1922
- });
1923
- } catch (error) {
1924
- console.error("Error in onBidsSubmitted callback:", error);
1925
- }
1926
- const successfulBids = txResult.batchInterruptedIndex ?? subaccounts.length;
1927
- this.txFees += txResult.finalFee ?? 0n;
1928
- console.log("Result of bids for cohort", {
1929
- successfulBids,
1930
- bidsPlaced: subaccounts.length,
1931
- bidPerSeat: formatArgons(microgonsPerSeat),
1932
- bidAtTick
1933
- });
1934
- if (bidError) {
1935
- try {
1936
- this.callbacks?.onBidsRejected?.({
1937
- tick: bidAtTick,
1938
- blockNumber,
1939
- microgonsPerSeat,
1940
- submittedCount: subaccounts.length,
1941
- rejectedCount: subaccounts.length - successfulBids,
1942
- bidError
1943
- });
1944
- } catch (error) {
1945
- console.error("Error in onBidsRejected callback:", error);
1946
- }
1947
- throw bidError;
1948
- }
1949
- } catch (err) {
1950
- console.error(`Error bidding for cohort ${this.cohortStartingFrameId}:`, err);
1951
- } finally {
1952
- this.pendingRequest = void 0;
1953
- this.scheduleEvaluation();
1954
- }
1955
- }
1956
- scheduleEvaluation() {
1957
- const millisPerTick = this.millisPerTick;
1958
- const delayTicks = Math.max(this.options.bidDelay, 1);
1959
- const delay = delayTicks * millisPerTick;
1960
- if (this.evaluateInterval) clearInterval(this.evaluateInterval);
1961
- console.log(`Scheduling next evaluation in ${delay}ms`);
1962
- this.evaluateInterval = setInterval(() => this.checkWinningBids().catch(console.error), delay);
1963
- }
1964
- updateBidList(rawBids, blockNumber, tick) {
1965
- try {
1966
- let mostRecentBidTick = 0;
1967
- let hasDiffs = this.currentBids.bids.length !== rawBids.length;
1968
- const bids = [];
1969
- for (let i = 0; i < rawBids.length; i += 1) {
1970
- const rawBid = rawBids[i];
1971
- const bidAtTick = rawBid.bidAtTick.toNumber();
1972
- if (bidAtTick > mostRecentBidTick) {
1973
- mostRecentBidTick = bidAtTick;
1974
- }
1975
- const address = rawBid.accountId.toHuman();
1976
- const bidMicrogons = rawBid.bid.toBigInt();
1977
- if (!hasDiffs) {
1978
- const existing = this.currentBids.bids[i];
1979
- hasDiffs = existing?.address !== address || existing?.bidMicrogons !== bidMicrogons;
1980
- }
1981
- bids.push({
1982
- address,
1983
- bidMicrogons,
1984
- bidAtTick
1985
- });
1986
- }
1987
- if (blockNumber > this.currentBids.atBlockNumber && hasDiffs) {
1988
- this.currentBids.bids = bids;
1989
- this.currentBids.mostRecentBidTick = mostRecentBidTick;
1990
- this.currentBids.atTick = tick;
1991
- this.currentBids.atBlockNumber = blockNumber;
1992
- this.winningBids = bids.filter((x) => this.myAddresses.has(x.address));
1993
- console.log("Now winning bids:", this.winningBids.length);
1994
- if (this.callbacks?.onBidsUpdated) {
1995
- this.callbacks.onBidsUpdated({
1996
- bids: this.winningBids,
1997
- atBlockNumber: blockNumber,
1998
- tick: mostRecentBidTick
1999
- });
2000
- }
2001
- }
2002
- } catch (err) {
2003
- console.error("Error processing updated bids list:", err);
2004
- }
2005
- }
2006
- safeRecordParamsAdjusted(args) {
2007
- try {
2008
- this.callbacks?.onBidParamsAdjusted?.(args);
2009
- } catch (err) {
2010
- console.error("Error in onBidParamsAdjusted callback:", err);
2011
- }
2012
- }
2013
- };
2014
- var EMPTY_TABLE = {
2015
- headerBottom: { left: " ", mid: " ", other: "\u2500", right: " " },
2016
- headerTop: { left: " ", mid: " ", other: " ", right: " " },
2017
- rowSeparator: { left: " ", mid: " ", other: " ", right: " " },
2018
- tableBottom: { left: " ", mid: " ", other: " ", right: " " },
2019
- vertical: " "
2020
- };
2021
- var BidPool = class {
2022
- constructor(client, keypair, accountRegistry = AccountRegistry.factory()) {
2023
- this.client = client;
2024
- this.keypair = keypair;
2025
- this.accountRegistry = accountRegistry;
2026
- __publicField(this, "bidPoolAmount", 0n);
2027
- __publicField(this, "nextFrameId", 1);
2028
- __publicField(this, "poolVaultCapitalByFrame", {});
2029
- __publicField(this, "vaultSecuritization", []);
2030
- __publicField(this, "printTimeout");
2031
- __publicField(this, "blockWatch");
2032
- __publicField(this, "vaultsById", {});
2033
- __publicField(this, "tickDuration");
2034
- __publicField(this, "lastDistributedFrameId");
2035
- __publicField(this, "FrameSubscriptions", {});
2036
- this.blockWatch = new BlockWatch(client, { shouldLog: false });
2037
- }
2038
- async onVaultsUpdated(blockHash, vaultIdSet) {
2039
- const client = await this.client;
2040
- this.tickDuration ?? (this.tickDuration = (await client.query.ticks.genesisTicker()).tickDurationMillis.toNumber());
2041
- const api = await client.at(blockHash);
2042
- const vaultIds = [...vaultIdSet];
2043
- const rawVaults = await api.query.vaults.vaultsById.multi(vaultIds);
2044
- for (let i = 0; i < vaultIds.length; i += 1) {
2045
- const rawVault = rawVaults[i];
2046
- if (rawVault.isNone) continue;
2047
- const vaultId = vaultIds[i];
2048
- this.vaultsById[vaultId] = new Vault(vaultId, rawVault.unwrap(), this.tickDuration);
2049
- }
2050
- const vaults = Object.entries(this.vaultsById);
2051
- const newSecuritization = [];
2052
- for (const [vaultId, vault] of vaults) {
2053
- const amount = vault.activatedSecuritizationPerSlot();
2054
- newSecuritization.push({
2055
- vaultId: Number(vaultId),
2056
- bitcoinSpace: vault.availableBitcoinSpace(),
2057
- activatedSecuritization: amount,
2058
- vaultSharingPercent: vault.terms.liquidityPoolProfitSharing
2059
- });
2060
- }
2061
- newSecuritization.sort((a, b) => {
2062
- const diff2 = b.activatedSecuritization - a.activatedSecuritization;
2063
- if (diff2 !== 0n) return Number(diff2);
2064
- return a.vaultId - b.vaultId;
2065
- });
2066
- this.vaultSecuritization = newSecuritization;
2067
- this.printDebounce();
2068
- }
2069
- async getBidPool() {
2070
- const client = await this.client;
2071
- const balanceBytes = await client.rpc.state.call("MiningSlotApi_bid_pool", "");
2072
- const balance = client.createType("U128", balanceBytes);
2073
- return balance.toBigInt();
2074
- }
2075
- async loadAt(blockHash) {
2076
- const client = await this.client;
2077
- blockHash ?? (blockHash = new Uint8Array((await client.rpc.chain.getHeader()).hash));
2078
- const api = await client.at(blockHash);
2079
- const rawVaultIds = await api.query.vaults.vaultsById.keys();
2080
- const vaultIds = rawVaultIds.map((x) => x.args[0].toNumber());
2081
- this.bidPoolAmount = await this.getBidPool();
2082
- this.nextFrameId = (await api.query.miningSlot.nextFrameId()).toNumber();
2083
- const contributors = await api.query.liquidityPools.vaultPoolsByFrame.entries();
2084
- for (const [frameId, funds] of contributors) {
2085
- const FrameIdNumber = frameId.args[0].toNumber();
2086
- this.loadFrameData(FrameIdNumber, funds);
2087
- }
2088
- for (const entrant of await api.query.liquidityPools.capitalActive()) {
2089
- this.setVaultFrameData(entrant.frameId.toNumber(), entrant.vaultId.toNumber(), {
2090
- activatedCapital: entrant.activatedCapital.toBigInt()
2091
- });
2092
- }
2093
- for (const entrant of await api.query.liquidityPools.capitalRaising()) {
2094
- this.setVaultFrameData(entrant.frameId.toNumber(), entrant.vaultId.toNumber(), {
2095
- activatedCapital: entrant.activatedCapital.toBigInt()
2096
- });
2097
- }
2098
- await this.onVaultsUpdated(blockHash, new Set(vaultIds));
2099
- this.print();
2100
- }
2101
- async watch() {
2102
- await this.loadAt();
2103
- await this.blockWatch.start();
2104
- this.blockWatch.events.on("vaults-updated", (b, v) => this.onVaultsUpdated(b.hash, v));
2105
- const api = await this.client;
2106
- this.blockWatch.events.on("event", async (_, event) => {
2107
- if (api.events.liquidityPools.BidPoolDistributed.is(event)) {
2108
- const { frameId: rawFrameId } = event.data;
2109
- this.lastDistributedFrameId = rawFrameId.toNumber();
2110
- this.bidPoolAmount = await this.getBidPool();
2111
- this.FrameSubscriptions[rawFrameId.toNumber()]?.();
2112
- const entrant = await api.query.liquidityPools.vaultPoolsByFrame(rawFrameId);
2113
- this.loadFrameData(rawFrameId.toNumber(), entrant);
2114
- this.printDebounce();
2115
- }
2116
- if (api.events.liquidityPools.NextBidPoolCapitalLocked.is(event)) {
2117
- const { frameId } = event.data;
2118
- for (let inc = 0; inc < 2; inc++) {
2119
- const id = frameId.toNumber() + inc;
2120
- if (!this.FrameSubscriptions[id]) {
2121
- this.FrameSubscriptions[id] = await api.query.liquidityPools.vaultPoolsByFrame(
2122
- id,
2123
- async (entrant) => {
2124
- this.loadFrameData(id, entrant);
2125
- this.printDebounce();
2126
- }
2127
- );
2128
- }
2129
- }
2130
- }
2131
- });
2132
- const unsubscribe = await api.queryMulti(
2133
- [
2134
- api.query.miningSlot.bidsForNextSlotCohort,
2135
- api.query.miningSlot.nextFrameId,
2136
- api.query.liquidityPools.capitalActive,
2137
- api.query.liquidityPools.capitalRaising
2138
- ],
2139
- async ([_bids, nextFrameId, openVaultBidPoolCapital, nextPoolCapital]) => {
2140
- this.bidPoolAmount = await this.getBidPool();
2141
- this.nextFrameId = nextFrameId.toNumber();
2142
- for (const entrant of [...openVaultBidPoolCapital, ...nextPoolCapital]) {
2143
- this.setVaultFrameData(entrant.frameId.toNumber(), entrant.vaultId.toNumber(), {
2144
- activatedCapital: entrant.activatedCapital.toBigInt()
2145
- });
2146
- }
2147
- this.printDebounce();
2148
- }
2149
- );
2150
- return { unsubscribe };
2151
- }
2152
- async bondArgons(vaultId, amount, options) {
2153
- const client = await this.client;
2154
- const tx = client.tx.liquidityPools.bondArgons(vaultId, amount);
2155
- const txSubmitter = new TxSubmitter(client, tx, this.keypair);
2156
- const affordability = await txSubmitter.canAfford({
2157
- tip: options?.tip,
2158
- unavailableBalance: amount
2159
- });
2160
- if (!affordability.canAfford) {
2161
- console.warn("Insufficient balance to bond argons to liquidity pool", {
2162
- ...affordability,
2163
- argonsNeeded: amount
2164
- });
2165
- throw new Error("Insufficient balance to bond argons to liquidity pool");
2166
- }
2167
- const result = await txSubmitter.submit({
2168
- tip: options?.tip,
2169
- useLatestNonce: true
2170
- });
2171
- await result.inBlockPromise;
2172
- return result;
2173
- }
2174
- printDebounce() {
2175
- if (this.printTimeout) {
2176
- clearTimeout(this.printTimeout);
2177
- }
2178
- this.printTimeout = setTimeout(() => {
2179
- this.print();
2180
- }, 100);
2181
- }
2182
- getOperatorName(vaultId) {
2183
- const vault = this.vaultsById[vaultId];
2184
- return this.accountRegistry.getName(vault.operatorAccountId) ?? vault.operatorAccountId;
2185
- }
2186
- print() {
2187
- console.clear();
2188
- const lastDistributedFrameId = this.lastDistributedFrameId;
2189
- const distributedFrame = this.poolVaultCapitalByFrame[this.lastDistributedFrameId ?? -1] ?? {};
2190
- if (Object.keys(distributedFrame).length > 0) {
2191
- console.log(`
2192
-
2193
- Distributed (Frame ${lastDistributedFrameId})`);
2194
- const rows = [];
2195
- let maxWidth2 = 0;
2196
- for (const [key, entry] of Object.entries(distributedFrame)) {
2197
- const { table, width } = this.createBondCapitalTable(
2198
- entry.earnings ?? 0n,
2199
- entry.contributors ?? [],
2200
- `Earnings (shared = ${formatPercent(entry.vaultSharingPercent)})`
2201
- );
2202
- if (width > maxWidth2) {
2203
- maxWidth2 = width;
2204
- }
2205
- rows.push({
2206
- Vault: key,
2207
- Who: this.getOperatorName(Number(key)),
2208
- Balances: table
2209
- });
2210
- }
2211
- new Table({
2212
- columns: [
2213
- { name: "Vault", alignment: "left" },
2214
- { name: "Who", alignment: "left" },
2215
- {
2216
- name: "Balances",
2217
- title: "Contributor Balances",
2218
- alignment: "center",
2219
- minLen: maxWidth2
2220
- }
2221
- ],
2222
- rows
2223
- }).printTable();
2224
- }
2225
- console.log(
2226
- `
2227
-
2228
- Active Bid Pool: ${formatArgons(this.bidPoolAmount)} (Frame ${this.nextFrameId})`
2229
- );
2230
- const Frame = this.poolVaultCapitalByFrame[this.nextFrameId];
2231
- if (Object.keys(Frame ?? {}).length > 0) {
2232
- const rows = [];
2233
- let maxWidth2 = 0;
2234
- for (const [key, entry] of Object.entries(Frame)) {
2235
- const { table, width } = this.createBondCapitalTable(
2236
- entry.activatedCapital,
2237
- entry.contributors ?? []
2238
- );
2239
- if (width > maxWidth2) {
2240
- maxWidth2 = width;
2241
- }
2242
- rows.push({
2243
- Vault: key,
2244
- Who: this.getOperatorName(Number(key)),
2245
- "Pool Capital": table
2246
- });
2247
- }
2248
- new Table({
2249
- columns: [
2250
- { name: "Vault", alignment: "left" },
2251
- { name: "Who", alignment: "left" },
2252
- { name: "Pool Capital", alignment: "left", minLen: maxWidth2 }
2253
- ],
2254
- rows
2255
- }).printTable();
2256
- }
2257
- const raisingFunds = this.poolVaultCapitalByFrame[this.nextFrameId + 1] ?? [];
2258
- let maxWidth = 0;
2259
- const nextCapital = [];
2260
- for (const x of this.vaultSecuritization) {
2261
- const entry = raisingFunds[x.vaultId] ?? {};
2262
- const { table, width } = this.createBondCapitalTable(
2263
- x.activatedSecuritization,
2264
- entry.contributors ?? []
2265
- );
2266
- if (width > maxWidth) {
2267
- maxWidth = width;
2268
- }
2269
- nextCapital.push({
2270
- Vault: x.vaultId,
2271
- Owner: this.getOperatorName(x.vaultId),
2272
- "Bitcoin Space": formatArgons(x.bitcoinSpace),
2273
- "Activated Securitization": `${formatArgons(x.activatedSecuritization)} / slot`,
2274
- "Liquidity Pool": `${formatPercent(x.vaultSharingPercent)} profit sharing${table}`
2275
- });
2276
- }
2277
- if (nextCapital.length) {
2278
- console.log(`
2279
-
2280
- Raising Funds (Frame ${this.nextFrameId + 1}):`);
2281
- new Table({
2282
- columns: [
2283
- { name: "Vault", alignment: "left" },
2284
- { name: "Owner", alignment: "left" },
2285
- { name: "Bitcoin Space", alignment: "right" },
2286
- { name: "Activated Securitization", alignment: "right" },
2287
- { name: "Liquidity Pool", alignment: "left", minLen: maxWidth }
2288
- ],
2289
- rows: nextCapital
2290
- }).printTable();
2291
- }
2292
- }
2293
- setVaultFrameData(frameId, vaultId, data) {
2294
- var _a, _b;
2295
- this.poolVaultCapitalByFrame ?? (this.poolVaultCapitalByFrame = {});
2296
- (_a = this.poolVaultCapitalByFrame)[frameId] ?? (_a[frameId] = {});
2297
- (_b = this.poolVaultCapitalByFrame[frameId])[vaultId] ?? (_b[vaultId] = {
2298
- activatedCapital: data.activatedCapital ?? data.contributors?.reduce((a, b) => a + b.amount, 0n) ?? 0n
2299
- });
2300
- Object.assign(this.poolVaultCapitalByFrame[frameId][vaultId], filterUndefined(data));
2301
- }
2302
- createBondCapitalTable(total, contributors, title = "Total") {
2303
- const table = new Table({
2304
- style: EMPTY_TABLE,
2305
- columns: [
2306
- { name: "who", title, minLen: 10, alignment: "right" },
2307
- {
2308
- name: "amount",
2309
- title: formatArgons(total),
2310
- minLen: 7,
2311
- alignment: "left"
2312
- }
2313
- ]
2314
- });
2315
- for (const x of contributors) {
2316
- table.addRow({
2317
- who: this.accountRegistry.getName(x.address) ?? x.address,
2318
- amount: formatArgons(x.amount)
2319
- });
2320
- }
2321
- const str = table.render();
2322
- const width = str.indexOf("\n");
2323
- return { table: str, width };
2324
- }
2325
- loadFrameData(frameId, vaultFunds) {
2326
- for (const [vaultId, fund] of vaultFunds) {
2327
- const vaultIdNumber = vaultId.toNumber();
2328
- const contributors = fund.contributorBalances.map(([a, b]) => ({
2329
- address: a.toHuman(),
2330
- amount: b.toBigInt()
2331
- }));
2332
- if (fund.distributedProfits.isSome) {
2333
- if (frameId > (this.lastDistributedFrameId ?? 0)) {
2334
- this.lastDistributedFrameId = frameId;
2335
- }
2336
- }
2337
- this.setVaultFrameData(frameId, vaultIdNumber, {
2338
- earnings: fund.distributedProfits.isSome ? fund.distributedProfits.unwrap().toBigInt() : void 0,
2339
- vaultSharingPercent: convertPermillToBigNumber(fund.vaultSharingPercent.toBigInt()),
2340
- contributors
2341
- });
2342
- }
2343
- }
2344
- };
537
+ function toFixedNumber(value, decimals) {
538
+ const factor = new BigNumber2__default(10).pow(decimals);
539
+ const bn = new BigNumber2__default(value);
540
+ const int = bn.times(factor).integerValue(BigNumber2__default.ROUND_DOWN);
541
+ return BigInt(int.toFixed(0));
542
+ }
543
+ function fromFixedNumber(value, decimals = FIXED_U128_DECIMALS) {
544
+ const factor = new BigNumber2__default(10).pow(decimals);
545
+ const bn = new BigNumber2__default(value.toString());
546
+ return bn.div(factor);
547
+ }
548
+ var FIXED_U128_DECIMALS = 18;
549
+ var PERMILL_DECIMALS = 6;
2345
550
  var SATS_PER_BTC = 100000000n;
2346
- var BitcoinLocks = class _BitcoinLocks {
551
+ var BitcoinLocks = class {
2347
552
  constructor(client) {
2348
553
  this.client = client;
2349
554
  }
2350
555
  async getUtxoIdFromEvents(events) {
2351
- const client = await this.client;
2352
556
  for (const event of events) {
2353
- if (client.events.bitcoinLocks.BitcoinLockCreated.is(event)) {
557
+ if (this.client.events.bitcoinLocks.BitcoinLockCreated.is(event)) {
2354
558
  return event.data.utxoId.toNumber();
2355
559
  }
2356
560
  }
2357
561
  return void 0;
2358
562
  }
2359
563
  async getMarketRate(satoshis) {
2360
- const client = await this.client;
564
+ const client = this.client;
2361
565
  const sats = client.createType("U64", satoshis.toString());
2362
566
  const marketRate = await client.rpc.state.call("BitcoinApis_market_rate", sats.toHex(true));
2363
567
  const rate = client.createType("Option<U128>", marketRate);
@@ -2367,7 +571,7 @@ var BitcoinLocks = class _BitcoinLocks {
2367
571
  return rate.value.toBigInt();
2368
572
  }
2369
573
  async getRedemptionRate(satoshis) {
2370
- const client = await this.client;
574
+ const client = this.client;
2371
575
  const sats = client.createType("U64", satoshis.toString());
2372
576
  const marketRate = await client.rpc.state.call("BitcoinApis_redemption_rate", sats.toHex(true));
2373
577
  const rate = client.createType("Option<U128>", marketRate);
@@ -2377,7 +581,7 @@ var BitcoinLocks = class _BitcoinLocks {
2377
581
  return rate.value.toBigInt();
2378
582
  }
2379
583
  async getConfig() {
2380
- const client = await this.client;
584
+ const client = this.client;
2381
585
  const bitcoinNetwork = await client.query.bitcoinUtxos.bitcoinNetwork();
2382
586
  return {
2383
587
  lockReleaseCosignDeadlineFrames: client.consts.bitcoinLocks.lockReleaseCosignDeadlineFrames.toNumber(),
@@ -2387,24 +591,19 @@ var BitcoinLocks = class _BitcoinLocks {
2387
591
  };
2388
592
  }
2389
593
  async getBitcoinConfirmedBlockHeight() {
2390
- const client = await this.client;
2391
- return await client.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => x.value?.blockHeight.toNumber() ?? 0);
594
+ return await this.client.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => x.value?.blockHeight.toNumber() ?? 0);
2392
595
  }
2393
596
  /**
2394
597
  * Gets the UTXO reference by ID.
2395
598
  * @param utxoId - The UTXO ID to look up.
2396
- * @param atHeight - Optional block height to query the UTXO reference at a specific point in time.
599
+ * @param clientAtHeight - Optional client at the block height to query the UTXO reference at a specific point in time.
2397
600
  * @return An object containing the transaction ID and output index, or undefined if not found.
2398
601
  * @return.txid - The Bitcoin transaction ID of the UTXO.
2399
602
  * @return.vout - The output index of the UTXO in the transaction.
2400
603
  * @return.bitcoinTxid - The Bitcoin transaction ID of the UTXO formatted in little endian
2401
604
  */
2402
- async getUtxoRef(utxoId, atHeight) {
2403
- let client = await this.client;
2404
- if (atHeight !== void 0) {
2405
- const blockHash = await client.rpc.chain.getBlockHash(atHeight);
2406
- client = await client.at(blockHash);
2407
- }
605
+ async getUtxoRef(utxoId, clientAtHeight) {
606
+ const client = clientAtHeight ?? this.client;
2408
607
  const refRaw = await client.query.bitcoinUtxos.utxoIdToRef(utxoId);
2409
608
  if (!refRaw) {
2410
609
  return;
@@ -2415,12 +614,8 @@ var BitcoinLocks = class _BitcoinLocks {
2415
614
  const vout = ref.outputIndex.toNumber();
2416
615
  return { txid, vout, bitcoinTxid };
2417
616
  }
2418
- async getReleaseRequest(utxoId, atHeight) {
2419
- let client = await this.client;
2420
- if (atHeight !== void 0) {
2421
- const blockHash = await client.rpc.chain.getBlockHash(atHeight);
2422
- client = await client.at(blockHash);
2423
- }
617
+ async getReleaseRequest(utxoId, clientAtHeight) {
618
+ const client = clientAtHeight ?? this.client;
2424
619
  const requestMaybe = await client.query.bitcoinLocks.lockReleaseRequestsByUtxoId(utxoId);
2425
620
  if (!requestMaybe.isSome) {
2426
621
  return void 0;
@@ -2436,7 +631,7 @@ var BitcoinLocks = class _BitcoinLocks {
2436
631
  }
2437
632
  async submitVaultSignature(args) {
2438
633
  const { utxoId, vaultSignature, argonKeyring, txProgressCallback } = args;
2439
- const client = await this.client;
634
+ const client = this.client;
2440
635
  if (!vaultSignature || vaultSignature.byteLength < 70 || vaultSignature.byteLength > 73) {
2441
636
  throw new Error(
2442
637
  `Invalid vault signature length: ${vaultSignature.byteLength}. Must be 70-73 bytes.`
@@ -2448,8 +643,7 @@ var BitcoinLocks = class _BitcoinLocks {
2448
643
  return await submitter.submit({ txProgressCallback });
2449
644
  }
2450
645
  async getBitcoinLock(utxoId) {
2451
- const client = await this.client;
2452
- const utxoRaw = await client.query.bitcoinLocks.locksByUtxoId(utxoId);
646
+ const utxoRaw = await this.client.query.bitcoinLocks.locksByUtxoId(utxoId);
2453
647
  if (!utxoRaw.isSome) {
2454
648
  return;
2455
649
  }
@@ -2458,7 +652,8 @@ var BitcoinLocks = class _BitcoinLocks {
2458
652
  const wscriptHash = utxo.utxoScriptPubkey.asP2wsh.wscriptHash.toHex().replace("0x", "");
2459
653
  const p2wshScriptHashHex = `0x${p2shBytesPrefix}${wscriptHash}`;
2460
654
  const vaultId = utxo.vaultId.toNumber();
2461
- const lockPrice = utxo.lockPrice.toBigInt();
655
+ const peggedPrice = utxo.peggedPrice.toBigInt();
656
+ const liquidityPromised = utxo.liquidityPromised.toBigInt();
2462
657
  const ownerAccount = utxo.ownerAccount.toHuman();
2463
658
  const satoshis = utxo.satoshis.toBigInt();
2464
659
  const vaultPubkey = utxo.vaultPubkey.toHex();
@@ -2482,7 +677,8 @@ var BitcoinLocks = class _BitcoinLocks {
2482
677
  utxoId,
2483
678
  p2wshScriptHashHex,
2484
679
  vaultId,
2485
- lockPrice,
680
+ peggedPrice,
681
+ liquidityPromised,
2486
682
  ownerAccount,
2487
683
  satoshis,
2488
684
  vaultPubkey,
@@ -2503,7 +699,7 @@ var BitcoinLocks = class _BitcoinLocks {
2503
699
  * @param waitForSignatureMillis - Optional timeout in milliseconds to wait for the signature. If -1, waits indefinitely.
2504
700
  */
2505
701
  async findVaultCosignSignature(utxoId, waitForSignatureMillis) {
2506
- const client = await this.client;
702
+ const client = this.client;
2507
703
  const releaseHeight = await client.query.bitcoinLocks.lockReleaseCosignHeightById(utxoId);
2508
704
  if (releaseHeight.isSome) {
2509
705
  const releaseHeightValue = releaseHeight.unwrap().toNumber();
@@ -2538,7 +734,7 @@ var BitcoinLocks = class _BitcoinLocks {
2538
734
  });
2539
735
  }
2540
736
  async blockHashAtHeight(atHeight) {
2541
- const client = await this.client;
737
+ const client = this.client;
2542
738
  for (let i = 0; i < 10; i++) {
2543
739
  const currentHeight = await client.query.system.number().then((x) => x.toNumber());
2544
740
  if (atHeight > currentHeight) {
@@ -2559,7 +755,7 @@ var BitcoinLocks = class _BitcoinLocks {
2559
755
  return void 0;
2560
756
  }
2561
757
  async getVaultCosignSignature(utxoId, atHeight) {
2562
- const client = await this.client;
758
+ const client = this.client;
2563
759
  const blockHash = await this.blockHashAtHeight(atHeight);
2564
760
  if (!blockHash) {
2565
761
  console.warn(`Block hash not found for height ${atHeight}`);
@@ -2577,8 +773,7 @@ var BitcoinLocks = class _BitcoinLocks {
2577
773
  return void 0;
2578
774
  }
2579
775
  async findPendingMints(utxoId) {
2580
- const client = await this.client;
2581
- const pendingMint = await client.query.mint.pendingMintUtxos();
776
+ const pendingMint = await this.client.query.mint.pendingMintUtxos();
2582
777
  const mintsPending = [];
2583
778
  for (const [utxoIdRaw, _accountId, mintAmountRaw] of pendingMint) {
2584
779
  if (utxoIdRaw.toNumber() === utxoId) {
@@ -2589,7 +784,7 @@ var BitcoinLocks = class _BitcoinLocks {
2589
784
  }
2590
785
  async createInitializeLockTx(args) {
2591
786
  const { vault, argonKeyring, satoshis, tip = 0n, ownerBitcoinPubkey } = args;
2592
- const client = await this.client;
787
+ const client = this.client;
2593
788
  if (ownerBitcoinPubkey.length !== 33) {
2594
789
  throw new Error(
2595
790
  `Invalid Bitcoin key length: ${ownerBitcoinPubkey.length}. Must be a compressed pukey (33 bytes).`
@@ -2617,7 +812,7 @@ var BitcoinLocks = class _BitcoinLocks {
2617
812
  return { tx, securityFee, txFee };
2618
813
  }
2619
814
  async getBitcoinLockFromTxResult(txResult) {
2620
- const client = await this.client;
815
+ const client = this.client;
2621
816
  const blockHash = await txResult.inBlockPromise;
2622
817
  const blockHeight = await client.at(blockHash).then((x) => x.query.system.number()).then((x) => x.toNumber());
2623
818
  const utxoId = await this.getUtxoIdFromEvents(txResult.events) ?? 0;
@@ -2632,7 +827,7 @@ var BitcoinLocks = class _BitcoinLocks {
2632
827
  }
2633
828
  async initializeLock(args) {
2634
829
  const { argonKeyring, tip = 0n, txProgressCallback } = args;
2635
- const client = await this.client;
830
+ const client = this.client;
2636
831
  const { tx, securityFee } = await this.createInitializeLockTx(args);
2637
832
  const submitter = new TxSubmitter(client, tx, argonKeyring);
2638
833
  const txResult = await submitter.submit({
@@ -2654,7 +849,7 @@ var BitcoinLocks = class _BitcoinLocks {
2654
849
  return argonAmount * SATS_PER_BTC / marketRatePerBitcoin;
2655
850
  }
2656
851
  async requestRelease(args) {
2657
- const client = await this.client;
852
+ const client = this.client;
2658
853
  const {
2659
854
  lock,
2660
855
  releaseRequest: { bitcoinNetworkFee, toScriptPubkey },
@@ -2671,8 +866,8 @@ var BitcoinLocks = class _BitcoinLocks {
2671
866
  argonKeyring
2672
867
  );
2673
868
  let redemptionPrice = await this.getRedemptionRate(lock.satoshis);
2674
- if (redemptionPrice > lock.lockPrice) {
2675
- redemptionPrice = lock.lockPrice;
869
+ if (redemptionPrice > lock.peggedPrice) {
870
+ redemptionPrice = lock.peggedPrice;
2676
871
  }
2677
872
  const canAfford = await submitter.canAfford({
2678
873
  tip,
@@ -2696,21 +891,20 @@ var BitcoinLocks = class _BitcoinLocks {
2696
891
  blockHeight
2697
892
  };
2698
893
  }
2699
- async releasePrice(satoshis, lockPrice) {
2700
- await this.client;
894
+ async releasePrice(satoshis, peggedPrice) {
2701
895
  const redemptionRate = await this.getRedemptionRate(satoshis);
2702
- if (redemptionRate > lockPrice) {
896
+ if (redemptionRate > peggedPrice) {
2703
897
  return redemptionRate;
2704
898
  }
2705
- return lockPrice;
899
+ return peggedPrice;
2706
900
  }
2707
901
  async getRatchetPrice(lock, vault) {
2708
- const { createdAtHeight, vaultClaimHeight, lockPrice, satoshis } = lock;
2709
- const client = await this.client;
902
+ const { createdAtHeight, vaultClaimHeight, peggedPrice, satoshis } = lock;
903
+ const client = this.client;
2710
904
  const marketRate = await this.getMarketRate(BigInt(satoshis));
2711
905
  let ratchetingFee = vault.terms.bitcoinBaseFee;
2712
906
  let burnAmount = 0n;
2713
- if (marketRate > lockPrice) {
907
+ if (marketRate > peggedPrice) {
2714
908
  const lockFee = vault.calculateBitcoinFee(marketRate);
2715
909
  const currentBitcoinHeight = await client.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => x.unwrap().blockHeight.toNumber());
2716
910
  const blockLength = vaultClaimHeight - createdAtHeight;
@@ -2718,7 +912,7 @@ var BitcoinLocks = class _BitcoinLocks {
2718
912
  const remainingDuration = 1 - elapsed;
2719
913
  ratchetingFee = BigInt(remainingDuration * Number(lockFee));
2720
914
  } else {
2721
- burnAmount = await this.releasePrice(lock.satoshis, lockPrice);
915
+ burnAmount = await this.releasePrice(lock.satoshis, peggedPrice);
2722
916
  }
2723
917
  return {
2724
918
  ratchetingFee,
@@ -2728,7 +922,7 @@ var BitcoinLocks = class _BitcoinLocks {
2728
922
  }
2729
923
  async ratchet(args) {
2730
924
  const { lock, argonKeyring, tip = 0n, vault, txProgressCallback } = args;
2731
- const client = await this.client;
925
+ const client = this.client;
2732
926
  const ratchetPrice = await this.getRatchetPrice(lock, vault);
2733
927
  const txSubmitter = new TxSubmitter(
2734
928
  client,
@@ -2761,94 +955,35 @@ var BitcoinLocks = class _BitcoinLocks {
2761
955
  const api = await client.at(blockHash);
2762
956
  const blockHeight = await api.query.system.number().then((x) => x.toNumber());
2763
957
  const bitcoinBlockHeight = await api.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => x.unwrap().blockHeight.toNumber());
2764
- const { amountBurned, newLockPrice, originalLockPrice } = ratchetEvent.data;
2765
- let mintAmount = newLockPrice.toBigInt();
2766
- if (newLockPrice > originalLockPrice) {
2767
- mintAmount -= originalLockPrice.toBigInt();
958
+ const { amountBurned, newPeggedPrice, originalPeggedPrice } = ratchetEvent.data;
959
+ let mintAmount = newPeggedPrice.toBigInt();
960
+ if (newPeggedPrice > originalPeggedPrice) {
961
+ mintAmount -= originalPeggedPrice.toBigInt();
2768
962
  }
2769
963
  return {
2770
964
  txFee: submission.finalFee ?? 0n,
2771
965
  securityFee: ratchetPrice.ratchetingFee,
2772
966
  pendingMint: mintAmount,
2773
- newLockPrice: newLockPrice.toBigInt(),
967
+ newPeggedPrice: newPeggedPrice.toBigInt(),
2774
968
  burned: amountBurned.toBigInt(),
2775
969
  blockHeight,
2776
970
  bitcoinBlockHeight
2777
971
  };
2778
972
  }
2779
- static async waitForSpace(accountset, options) {
2780
- const { argonAmount, bitcoinXpub, maxLockFee, tip = 0n } = options;
2781
- const vaults = new VaultMonitor(accountset, {
2782
- bitcoinSpaceAvailable: argonAmount
2783
- });
2784
- const bitcoinXpubBuffer = hexToU8a(bitcoinXpub);
2785
- return new Promise(async (resolve, reject) => {
2786
- vaults.events.on("bitcoin-space-above", async (vaultId, amount) => {
2787
- const vault = vaults.vaultsById[vaultId];
2788
- const fee = vault.calculateBitcoinFee(amount);
2789
- console.log(
2790
- `Vault ${vaultId} has ${formatArgons(amount)} argons available for bitcoin. Lock fee is ${formatArgons(fee)}`
2791
- );
2792
- if (maxLockFee !== void 0 && fee > maxLockFee) {
2793
- console.log(
2794
- `Skipping vault ${vaultId} due to high lock fee: ${formatArgons(maxLockFee)}`
2795
- );
2796
- return;
2797
- }
2798
- try {
2799
- const bitcoinLock = new _BitcoinLocks(accountset.client);
2800
- let satoshis = await bitcoinLock.requiredSatoshisForArgonLiquidity(amount);
2801
- satoshis -= options.satoshiWiggleRoomForDynamicPrice ?? 500n;
2802
- const { txResult, lock, securityFee } = await bitcoinLock.initializeLock({
2803
- vault,
2804
- satoshis,
2805
- argonKeyring: accountset.txSubmitterPair,
2806
- ownerBitcoinPubkey: bitcoinXpubBuffer,
2807
- tip
2808
- });
2809
- resolve({
2810
- satoshis,
2811
- argons: argonAmount,
2812
- vaultId,
2813
- securityFee,
2814
- txFee: txResult.finalFee,
2815
- finalizedPromise: txResult.finalizedPromise,
2816
- utxoId: lock.utxoId
2817
- });
2818
- } catch (err) {
2819
- console.error("Error submitting bitcoin lock tx:", err);
2820
- reject(err);
2821
- } finally {
2822
- vaults.stop();
2823
- }
2824
- });
2825
- await vaults.monitor();
2826
- });
2827
- }
2828
973
  };
2829
-
2830
- // src/keyringUtils.ts
2831
- function keyringFromSuri(suri, cryptoType = "sr25519") {
2832
- return new Keyring({ type: cryptoType }).createFromUri(suri);
2833
- }
2834
- function createKeyringPair(opts) {
2835
- const { cryptoType } = opts;
2836
- const seed = mnemonicGenerate();
2837
- return keyringFromSuri(seed, cryptoType);
2838
- }
2839
974
  async function waitForLoad() {
2840
975
  await cryptoWaitReady();
2841
976
  }
2842
- async function getClient(host) {
977
+ async function getClient(host, options) {
2843
978
  let provider;
2844
979
  if (host.startsWith("http")) {
2845
980
  provider = new HttpProvider(host);
2846
981
  } else {
2847
982
  provider = new WsProvider(host);
2848
983
  }
2849
- return await ApiPromise.create({ provider, noInitWarn: true });
984
+ return await ApiPromise.create({ provider, noInitWarn: true, ...options ?? {} });
2850
985
  }
2851
986
 
2852
- export { AccountMiners, AccountRegistry, Accountset, BidPool, BitcoinLocks, BlockWatch, CohortBidder, ExtrinsicError2 as ExtrinsicError, FrameCalculator, JsonExt, MICROGONS_PER_ARGON, MiningBids, SATS_PER_BTC, TxResult, TxSubmitter, TypedEmitter, Vault, VaultMonitor, WageProtector, checkForExtrinsicSuccess, convertFixedU128ToBigNumber, convertNumberToFixedU128, convertNumberToPermill, convertPermillToBigNumber, createKeyringPair, createNanoEvents, dispatchErrorToExtrinsicError, dispatchErrorToString, eventDataToJson, filterUndefined, formatArgons, formatPercent, getAuthorFromHeader, getClient, getConfig, getTickFromHeader, gettersToObject, keyringFromSuri, setConfig, toFixedNumber, waitForLoad };
987
+ export { BitcoinLocks, ExtrinsicError2 as ExtrinsicError, FIXED_U128_DECIMALS, MICROGONS_PER_ARGON, PERMILL_DECIMALS, SATS_PER_BTC, TxResult, TxSubmitter, Vault, WageProtector, checkForExtrinsicSuccess, createKeyringPair, dispatchErrorToExtrinsicError, dispatchErrorToString, formatArgons, fromFixedNumber, getAuthorFromHeader, getClient, getTickFromHeader, gettersToObject, keyringFromSuri, toFixedNumber, waitForLoad };
2853
988
  //# sourceMappingURL=index.js.map
2854
989
  //# sourceMappingURL=index.js.map