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