@argonprotocol/mainchain 1.3.7 → 1.3.9
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/README.md +7 -190
- package/browser/index.d.ts +479 -927
- package/browser/index.js +206 -1999
- package/browser/index.js.map +1 -1
- package/lib/index.cjs +1088 -69
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +479 -927
- package/lib/index.d.ts +479 -927
- package/lib/index.js +1101 -82
- package/lib/index.js.map +1 -1
- package/package.json +6 -14
- package/lib/chunk-4ZBJ5W3P.cjs +0 -743
- package/lib/chunk-4ZBJ5W3P.cjs.map +0 -1
- package/lib/chunk-PE7HFDHD.js +0 -743
- package/lib/chunk-PE7HFDHD.js.map +0 -1
- package/lib/chunk-PXZPYJ4P.js +0 -2982
- package/lib/chunk-PXZPYJ4P.js.map +0 -1
- package/lib/chunk-VXYWJG66.cjs +0 -2982
- package/lib/chunk-VXYWJG66.cjs.map +0 -1
- package/lib/cli.cjs +0 -19
- package/lib/cli.cjs.map +0 -1
- package/lib/cli.d.cts +0 -1
- package/lib/cli.d.ts +0 -1
- package/lib/cli.js +0 -19
- package/lib/cli.js.map +0 -1
- package/lib/clis/index.cjs +0 -30
- package/lib/clis/index.cjs.map +0 -1
- package/lib/clis/index.d.cts +0 -129
- package/lib/clis/index.d.ts +0 -129
- package/lib/clis/index.js +0 -30
- package/lib/clis/index.js.map +0 -1
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 {
|
|
12
|
+
import { mnemonicGenerate, cryptoWaitReady } from '@polkadot/util-crypto';
|
|
13
13
|
export { decodeAddress, mnemonicGenerate } from '@polkadot/util-crypto';
|
|
14
|
-
import * as
|
|
15
|
-
import
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
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 } =
|
|
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 =
|
|
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/
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
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/
|
|
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
|
|
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 =
|
|
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:
|
|
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
|
-
|
|
1363
|
-
vault.terms.
|
|
393
|
+
treasuryProfitSharing: fromFixedNumber(
|
|
394
|
+
vault.terms.treasuryProfitSharing.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:
|
|
1373
|
-
terms.bitcoinAnnualPercentRate.toBigInt()
|
|
404
|
+
bitcoinAnnualPercentRate: fromFixedNumber(
|
|
405
|
+
terms.bitcoinAnnualPercentRate.toBigInt(),
|
|
406
|
+
FIXED_U128_DECIMALS
|
|
1374
407
|
),
|
|
1375
408
|
bitcoinBaseFee: terms.bitcoinBaseFee.toBigInt(),
|
|
1376
|
-
|
|
1377
|
-
vault.terms.
|
|
409
|
+
treasuryProfitSharing: fromFixedNumber(
|
|
410
|
+
vault.terms.treasuryProfitSharing.toBigInt(),
|
|
411
|
+
PERMILL_DECIMALS
|
|
1378
412
|
)
|
|
1379
413
|
};
|
|
1380
414
|
}
|
|
@@ -1388,31 +422,31 @@ var Vault = class _Vault {
|
|
|
1388
422
|
return [...this.argonsScheduledForRelease.values()].reduce((acc, val) => acc + val, 0n);
|
|
1389
423
|
}
|
|
1390
424
|
securitizationRatioBN() {
|
|
1391
|
-
return new
|
|
425
|
+
return new BigNumber2__default(this.securitizationRatio);
|
|
1392
426
|
}
|
|
1393
427
|
recoverySecuritization() {
|
|
1394
|
-
const reserved = new
|
|
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,
|
|
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 =
|
|
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
|
/**
|
|
1408
|
-
* Returns the amount of Argons available to match per
|
|
442
|
+
* Returns the amount of Argons available to match per treasury pool
|
|
1409
443
|
*/
|
|
1410
444
|
activatedSecuritizationPerSlot() {
|
|
1411
445
|
const activated = this.activatedSecuritization();
|
|
1412
446
|
return activated / 10n;
|
|
1413
447
|
}
|
|
1414
448
|
calculateBitcoinFee(amount) {
|
|
1415
|
-
const fee = this.terms.bitcoinAnnualPercentRate.multipliedBy(Number(amount)).integerValue(
|
|
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,
|
|
460
|
+
static async create(client, keypair, args, config = {}) {
|
|
1427
461
|
const {
|
|
1428
462
|
securitization,
|
|
1429
463
|
securitizationRatio,
|
|
@@ -1444,18 +478,18 @@ var Vault = class _Vault {
|
|
|
1444
478
|
xpubBytes = bytes;
|
|
1445
479
|
}
|
|
1446
480
|
}
|
|
1447
|
-
|
|
481
|
+
const vaultParams = {
|
|
1448
482
|
terms: {
|
|
1449
483
|
// convert to fixed u128
|
|
1450
|
-
bitcoinAnnualPercentRate: toFixedNumber(annualPercentRate,
|
|
484
|
+
bitcoinAnnualPercentRate: toFixedNumber(annualPercentRate, FIXED_U128_DECIMALS),
|
|
1451
485
|
bitcoinBaseFee: BigInt(baseFee),
|
|
1452
|
-
|
|
486
|
+
treasuryProfitSharing: toFixedNumber(args.treasuryProfitSharing, PERMILL_DECIMALS)
|
|
1453
487
|
},
|
|
1454
|
-
securitizationRatio: toFixedNumber(securitizationRatio,
|
|
488
|
+
securitizationRatio: toFixedNumber(securitizationRatio, FIXED_U128_DECIMALS),
|
|
1455
489
|
securitization: BigInt(securitization),
|
|
1456
490
|
bitcoinXpubkey: xpubBytes
|
|
1457
491
|
};
|
|
1458
|
-
|
|
492
|
+
const tx = new TxSubmitter(client, client.tx.vaults.create(vaultParams), keypair);
|
|
1459
493
|
if (doNotExceedBalance) {
|
|
1460
494
|
const finalTip = tip ?? 0n;
|
|
1461
495
|
let txFee = await tx.feeEstimate(finalTip);
|
|
@@ -1492,881 +526,63 @@ var Vault = class _Vault {
|
|
|
1492
526
|
if (rawVault.isNone) {
|
|
1493
527
|
throw new Error("Vault creation failed, vault not found");
|
|
1494
528
|
}
|
|
1495
|
-
const tickDuration =
|
|
529
|
+
const tickDuration = config.tickDurationMillis ?? await client.query.ticks.genesisTicker().then((x) => x.tickDurationMillis.toNumber());
|
|
1496
530
|
const vault = new _Vault(vaultId, rawVault.unwrap(), tickDuration);
|
|
1497
531
|
return { vault, txResult: result };
|
|
1498
532
|
}
|
|
1499
533
|
};
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
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
|
-
};
|
|
534
|
+
function toFixedNumber(value, decimals) {
|
|
535
|
+
const factor = new BigNumber2__default(10).pow(decimals);
|
|
536
|
+
const bn = new BigNumber2__default(value);
|
|
537
|
+
const int = bn.times(factor).integerValue(BigNumber2__default.ROUND_DOWN);
|
|
538
|
+
return BigInt(int.toFixed(0));
|
|
539
|
+
}
|
|
540
|
+
function fromFixedNumber(value, decimals = FIXED_U128_DECIMALS) {
|
|
541
|
+
const factor = new BigNumber2__default(10).pow(decimals);
|
|
542
|
+
const bn = new BigNumber2__default(value.toString());
|
|
543
|
+
return bn.div(factor);
|
|
544
|
+
}
|
|
545
|
+
var FIXED_U128_DECIMALS = 18;
|
|
546
|
+
var PERMILL_DECIMALS = 6;
|
|
2354
547
|
var SATS_PER_BTC = 100000000n;
|
|
2355
|
-
var BitcoinLocks = class
|
|
548
|
+
var BitcoinLocks = class {
|
|
2356
549
|
constructor(client) {
|
|
2357
550
|
this.client = client;
|
|
2358
551
|
}
|
|
2359
552
|
async getUtxoIdFromEvents(events) {
|
|
2360
|
-
const client = await this.client;
|
|
2361
553
|
for (const event of events) {
|
|
2362
|
-
if (client.events.bitcoinLocks.BitcoinLockCreated.is(event)) {
|
|
554
|
+
if (this.client.events.bitcoinLocks.BitcoinLockCreated.is(event)) {
|
|
2363
555
|
return event.data.utxoId.toNumber();
|
|
2364
556
|
}
|
|
2365
557
|
}
|
|
2366
558
|
return void 0;
|
|
2367
559
|
}
|
|
2368
|
-
async getMarketRate(satoshis) {
|
|
2369
|
-
|
|
560
|
+
async getMarketRate(priceIndex, satoshis) {
|
|
561
|
+
return priceIndex.getBtcMicrogonPrice(satoshis);
|
|
562
|
+
}
|
|
563
|
+
async getRedemptionRate(priceIndex, details) {
|
|
564
|
+
const { satoshis, peggedPrice } = details;
|
|
565
|
+
const satsPerArgon = Number(SATS_PER_BTC) / MICROGONS_PER_ARGON;
|
|
566
|
+
let price = Number(priceIndex.btcUsdPrice);
|
|
567
|
+
price = price / satsPerArgon * Number(satoshis);
|
|
568
|
+
if (peggedPrice !== void 0 && peggedPrice < price) {
|
|
569
|
+
price = Number(peggedPrice);
|
|
570
|
+
}
|
|
571
|
+
const r = Number(priceIndex.rValue);
|
|
572
|
+
let multiplier;
|
|
573
|
+
if (r >= 1) {
|
|
574
|
+
multiplier = 1;
|
|
575
|
+
} else if (r >= 0.9) {
|
|
576
|
+
multiplier = 20 * (r * r) - 38 * r + 19;
|
|
577
|
+
} else if (r >= 0.01) {
|
|
578
|
+
multiplier = (0.5618 * r + 0.3944) / r;
|
|
579
|
+
} else {
|
|
580
|
+
multiplier = 1 / r * (0.576 * r + 0.4);
|
|
581
|
+
}
|
|
582
|
+
return BigInt(Math.floor(price * multiplier));
|
|
583
|
+
}
|
|
584
|
+
async getMarketRateApi(satoshis) {
|
|
585
|
+
const client = this.client;
|
|
2370
586
|
const sats = client.createType("U64", satoshis.toString());
|
|
2371
587
|
const marketRate = await client.rpc.state.call("BitcoinApis_market_rate", sats.toHex(true));
|
|
2372
588
|
const rate = client.createType("Option<U128>", marketRate);
|
|
@@ -2375,8 +591,8 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2375
591
|
}
|
|
2376
592
|
return rate.value.toBigInt();
|
|
2377
593
|
}
|
|
2378
|
-
async
|
|
2379
|
-
const client =
|
|
594
|
+
async getRedemptionRateApi(satoshis) {
|
|
595
|
+
const client = this.client;
|
|
2380
596
|
const sats = client.createType("U64", satoshis.toString());
|
|
2381
597
|
const marketRate = await client.rpc.state.call("BitcoinApis_redemption_rate", sats.toHex(true));
|
|
2382
598
|
const rate = client.createType("Option<U128>", marketRate);
|
|
@@ -2386,7 +602,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2386
602
|
return rate.value.toBigInt();
|
|
2387
603
|
}
|
|
2388
604
|
async getConfig() {
|
|
2389
|
-
const client =
|
|
605
|
+
const client = this.client;
|
|
2390
606
|
const bitcoinNetwork = await client.query.bitcoinUtxos.bitcoinNetwork();
|
|
2391
607
|
return {
|
|
2392
608
|
lockReleaseCosignDeadlineFrames: client.consts.bitcoinLocks.lockReleaseCosignDeadlineFrames.toNumber(),
|
|
@@ -2396,24 +612,19 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2396
612
|
};
|
|
2397
613
|
}
|
|
2398
614
|
async getBitcoinConfirmedBlockHeight() {
|
|
2399
|
-
|
|
2400
|
-
return await client.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => x.value?.blockHeight.toNumber() ?? 0);
|
|
615
|
+
return await this.client.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => x.value?.blockHeight.toNumber() ?? 0);
|
|
2401
616
|
}
|
|
2402
617
|
/**
|
|
2403
618
|
* Gets the UTXO reference by ID.
|
|
2404
619
|
* @param utxoId - The UTXO ID to look up.
|
|
2405
|
-
* @param
|
|
620
|
+
* @param clientAtHeight - Optional client at the block height to query the UTXO reference at a specific point in time.
|
|
2406
621
|
* @return An object containing the transaction ID and output index, or undefined if not found.
|
|
2407
622
|
* @return.txid - The Bitcoin transaction ID of the UTXO.
|
|
2408
623
|
* @return.vout - The output index of the UTXO in the transaction.
|
|
2409
624
|
* @return.bitcoinTxid - The Bitcoin transaction ID of the UTXO formatted in little endian
|
|
2410
625
|
*/
|
|
2411
|
-
async getUtxoRef(utxoId,
|
|
2412
|
-
|
|
2413
|
-
if (atHeight !== void 0) {
|
|
2414
|
-
const blockHash = await client.rpc.chain.getBlockHash(atHeight);
|
|
2415
|
-
client = await client.at(blockHash);
|
|
2416
|
-
}
|
|
626
|
+
async getUtxoRef(utxoId, clientAtHeight) {
|
|
627
|
+
const client = clientAtHeight ?? this.client;
|
|
2417
628
|
const refRaw = await client.query.bitcoinUtxos.utxoIdToRef(utxoId);
|
|
2418
629
|
if (!refRaw) {
|
|
2419
630
|
return;
|
|
@@ -2424,12 +635,8 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2424
635
|
const vout = ref.outputIndex.toNumber();
|
|
2425
636
|
return { txid, vout, bitcoinTxid };
|
|
2426
637
|
}
|
|
2427
|
-
async getReleaseRequest(utxoId,
|
|
2428
|
-
|
|
2429
|
-
if (atHeight !== void 0) {
|
|
2430
|
-
const blockHash = await client.rpc.chain.getBlockHash(atHeight);
|
|
2431
|
-
client = await client.at(blockHash);
|
|
2432
|
-
}
|
|
638
|
+
async getReleaseRequest(utxoId, clientAtHeight) {
|
|
639
|
+
const client = clientAtHeight ?? this.client;
|
|
2433
640
|
const requestMaybe = await client.query.bitcoinLocks.lockReleaseRequestsByUtxoId(utxoId);
|
|
2434
641
|
if (!requestMaybe.isSome) {
|
|
2435
642
|
return void 0;
|
|
@@ -2445,7 +652,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2445
652
|
}
|
|
2446
653
|
async submitVaultSignature(args) {
|
|
2447
654
|
const { utxoId, vaultSignature, argonKeyring, txProgressCallback } = args;
|
|
2448
|
-
const client =
|
|
655
|
+
const client = this.client;
|
|
2449
656
|
if (!vaultSignature || vaultSignature.byteLength < 70 || vaultSignature.byteLength > 73) {
|
|
2450
657
|
throw new Error(
|
|
2451
658
|
`Invalid vault signature length: ${vaultSignature.byteLength}. Must be 70-73 bytes.`
|
|
@@ -2457,8 +664,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2457
664
|
return await submitter.submit({ txProgressCallback });
|
|
2458
665
|
}
|
|
2459
666
|
async getBitcoinLock(utxoId) {
|
|
2460
|
-
const
|
|
2461
|
-
const utxoRaw = await client.query.bitcoinLocks.locksByUtxoId(utxoId);
|
|
667
|
+
const utxoRaw = await this.client.query.bitcoinLocks.locksByUtxoId(utxoId);
|
|
2462
668
|
if (!utxoRaw.isSome) {
|
|
2463
669
|
return;
|
|
2464
670
|
}
|
|
@@ -2467,7 +673,8 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2467
673
|
const wscriptHash = utxo.utxoScriptPubkey.asP2wsh.wscriptHash.toHex().replace("0x", "");
|
|
2468
674
|
const p2wshScriptHashHex = `0x${p2shBytesPrefix}${wscriptHash}`;
|
|
2469
675
|
const vaultId = utxo.vaultId.toNumber();
|
|
2470
|
-
const
|
|
676
|
+
const peggedPrice = utxo.peggedPrice.toBigInt();
|
|
677
|
+
const liquidityPromised = utxo.liquidityPromised.toBigInt();
|
|
2471
678
|
const ownerAccount = utxo.ownerAccount.toHuman();
|
|
2472
679
|
const satoshis = utxo.satoshis.toBigInt();
|
|
2473
680
|
const vaultPubkey = utxo.vaultPubkey.toHex();
|
|
@@ -2479,6 +686,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2479
686
|
cosignHdIndex: cosign_hd_index.toNumber(),
|
|
2480
687
|
claimHdIndex: claim_hd_index.toNumber()
|
|
2481
688
|
};
|
|
689
|
+
const securityFees = utxo.securityFees.toBigInt();
|
|
2482
690
|
const vaultClaimHeight = utxo.vaultClaimHeight.toNumber();
|
|
2483
691
|
const openClaimHeight = utxo.openClaimHeight.toNumber();
|
|
2484
692
|
const createdAtHeight = utxo.createdAtHeight.toNumber();
|
|
@@ -2491,7 +699,8 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2491
699
|
utxoId,
|
|
2492
700
|
p2wshScriptHashHex,
|
|
2493
701
|
vaultId,
|
|
2494
|
-
|
|
702
|
+
peggedPrice,
|
|
703
|
+
liquidityPromised,
|
|
2495
704
|
ownerAccount,
|
|
2496
705
|
satoshis,
|
|
2497
706
|
vaultPubkey,
|
|
@@ -2501,6 +710,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2501
710
|
vaultClaimHeight,
|
|
2502
711
|
openClaimHeight,
|
|
2503
712
|
createdAtHeight,
|
|
713
|
+
securityFees,
|
|
2504
714
|
isVerified,
|
|
2505
715
|
isRejectedNeedsRelease,
|
|
2506
716
|
fundHoldExtensionsByBitcoinExpirationHeight
|
|
@@ -2512,7 +722,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2512
722
|
* @param waitForSignatureMillis - Optional timeout in milliseconds to wait for the signature. If -1, waits indefinitely.
|
|
2513
723
|
*/
|
|
2514
724
|
async findVaultCosignSignature(utxoId, waitForSignatureMillis) {
|
|
2515
|
-
const client =
|
|
725
|
+
const client = this.client;
|
|
2516
726
|
const releaseHeight = await client.query.bitcoinLocks.lockReleaseCosignHeightById(utxoId);
|
|
2517
727
|
if (releaseHeight.isSome) {
|
|
2518
728
|
const releaseHeightValue = releaseHeight.unwrap().toNumber();
|
|
@@ -2547,7 +757,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2547
757
|
});
|
|
2548
758
|
}
|
|
2549
759
|
async blockHashAtHeight(atHeight) {
|
|
2550
|
-
const client =
|
|
760
|
+
const client = this.client;
|
|
2551
761
|
for (let i = 0; i < 10; i++) {
|
|
2552
762
|
const currentHeight = await client.query.system.number().then((x) => x.toNumber());
|
|
2553
763
|
if (atHeight > currentHeight) {
|
|
@@ -2568,7 +778,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2568
778
|
return void 0;
|
|
2569
779
|
}
|
|
2570
780
|
async getVaultCosignSignature(utxoId, atHeight) {
|
|
2571
|
-
const client =
|
|
781
|
+
const client = this.client;
|
|
2572
782
|
const blockHash = await this.blockHashAtHeight(atHeight);
|
|
2573
783
|
if (!blockHash) {
|
|
2574
784
|
console.warn(`Block hash not found for height ${atHeight}`);
|
|
@@ -2586,8 +796,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2586
796
|
return void 0;
|
|
2587
797
|
}
|
|
2588
798
|
async findPendingMints(utxoId) {
|
|
2589
|
-
const
|
|
2590
|
-
const pendingMint = await client.query.mint.pendingMintUtxos();
|
|
799
|
+
const pendingMint = await this.client.query.mint.pendingMintUtxos();
|
|
2591
800
|
const mintsPending = [];
|
|
2592
801
|
for (const [utxoIdRaw, _accountId, mintAmountRaw] of pendingMint) {
|
|
2593
802
|
if (utxoIdRaw.toNumber() === utxoId) {
|
|
@@ -2597,8 +806,8 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2597
806
|
return mintsPending;
|
|
2598
807
|
}
|
|
2599
808
|
async createInitializeLockTx(args) {
|
|
2600
|
-
const { vault, argonKeyring, satoshis, tip = 0n, ownerBitcoinPubkey } = args;
|
|
2601
|
-
const client =
|
|
809
|
+
const { vault, priceIndex, argonKeyring, satoshis, tip = 0n, ownerBitcoinPubkey } = args;
|
|
810
|
+
const client = this.client;
|
|
2602
811
|
if (ownerBitcoinPubkey.length !== 33) {
|
|
2603
812
|
throw new Error(
|
|
2604
813
|
`Invalid Bitcoin key length: ${ownerBitcoinPubkey.length}. Must be a compressed pukey (33 bytes).`
|
|
@@ -2610,7 +819,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2610
819
|
client.tx.bitcoinLocks.initialize(vault.vaultId, satoshis, ownerBitcoinPubkey),
|
|
2611
820
|
argonKeyring
|
|
2612
821
|
);
|
|
2613
|
-
const marketPrice = await this.getMarketRate(
|
|
822
|
+
const marketPrice = await this.getMarketRate(priceIndex, satoshis);
|
|
2614
823
|
const isVaultOwner = argonKeyring.address === vault.operatorAccountId;
|
|
2615
824
|
const securityFee = isVaultOwner ? 0n : vault.calculateBitcoinFee(marketPrice);
|
|
2616
825
|
const { canAfford, availableBalance, txFee } = await submitter.canAfford({
|
|
@@ -2626,7 +835,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2626
835
|
return { tx, securityFee, txFee };
|
|
2627
836
|
}
|
|
2628
837
|
async getBitcoinLockFromTxResult(txResult) {
|
|
2629
|
-
const client =
|
|
838
|
+
const client = this.client;
|
|
2630
839
|
const blockHash = await txResult.inBlockPromise;
|
|
2631
840
|
const blockHeight = await client.at(blockHash).then((x) => x.query.system.number()).then((x) => x.toNumber());
|
|
2632
841
|
const utxoId = await this.getUtxoIdFromEvents(txResult.events) ?? 0;
|
|
@@ -2641,7 +850,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2641
850
|
}
|
|
2642
851
|
async initializeLock(args) {
|
|
2643
852
|
const { argonKeyring, tip = 0n, txProgressCallback } = args;
|
|
2644
|
-
const client =
|
|
853
|
+
const client = this.client;
|
|
2645
854
|
const { tx, securityFee } = await this.createInitializeLockTx(args);
|
|
2646
855
|
const submitter = new TxSubmitter(client, tx, argonKeyring);
|
|
2647
856
|
const txResult = await submitter.submit({
|
|
@@ -2658,14 +867,15 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2658
867
|
securityFee
|
|
2659
868
|
};
|
|
2660
869
|
}
|
|
2661
|
-
async requiredSatoshisForArgonLiquidity(argonAmount) {
|
|
2662
|
-
const marketRatePerBitcoin =
|
|
870
|
+
async requiredSatoshisForArgonLiquidity(priceIndex, argonAmount) {
|
|
871
|
+
const marketRatePerBitcoin = priceIndex.getBtcMicrogonPrice(SATS_PER_BTC);
|
|
2663
872
|
return argonAmount * SATS_PER_BTC / marketRatePerBitcoin;
|
|
2664
873
|
}
|
|
2665
874
|
async requestRelease(args) {
|
|
2666
|
-
const client =
|
|
875
|
+
const client = this.client;
|
|
2667
876
|
const {
|
|
2668
877
|
lock,
|
|
878
|
+
priceIndex,
|
|
2669
879
|
releaseRequest: { bitcoinNetworkFee, toScriptPubkey },
|
|
2670
880
|
argonKeyring,
|
|
2671
881
|
tip,
|
|
@@ -2679,10 +889,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2679
889
|
client.tx.bitcoinLocks.requestRelease(lock.utxoId, toScriptPubkey, bitcoinNetworkFee),
|
|
2680
890
|
argonKeyring
|
|
2681
891
|
);
|
|
2682
|
-
|
|
2683
|
-
if (redemptionPrice > lock.lockPrice) {
|
|
2684
|
-
redemptionPrice = lock.lockPrice;
|
|
2685
|
-
}
|
|
892
|
+
const redemptionPrice = await this.getRedemptionRate(priceIndex, lock);
|
|
2686
893
|
const canAfford = await submitter.canAfford({
|
|
2687
894
|
tip,
|
|
2688
895
|
unavailableBalance: BigInt(redemptionPrice)
|
|
@@ -2705,21 +912,16 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2705
912
|
blockHeight
|
|
2706
913
|
};
|
|
2707
914
|
}
|
|
2708
|
-
async releasePrice(
|
|
2709
|
-
await this.
|
|
2710
|
-
const redemptionRate = await this.getRedemptionRate(satoshis);
|
|
2711
|
-
if (redemptionRate > lockPrice) {
|
|
2712
|
-
return redemptionRate;
|
|
2713
|
-
}
|
|
2714
|
-
return lockPrice;
|
|
915
|
+
async releasePrice(priceIndex, lock) {
|
|
916
|
+
return await this.getRedemptionRate(priceIndex, lock);
|
|
2715
917
|
}
|
|
2716
|
-
async getRatchetPrice(lock, vault) {
|
|
2717
|
-
const { createdAtHeight, vaultClaimHeight,
|
|
2718
|
-
const client =
|
|
2719
|
-
const marketRate = await this.getMarketRate(BigInt(satoshis));
|
|
918
|
+
async getRatchetPrice(lock, priceIndex, vault) {
|
|
919
|
+
const { createdAtHeight, vaultClaimHeight, peggedPrice, satoshis } = lock;
|
|
920
|
+
const client = this.client;
|
|
921
|
+
const marketRate = await this.getMarketRate(priceIndex, BigInt(satoshis));
|
|
2720
922
|
let ratchetingFee = vault.terms.bitcoinBaseFee;
|
|
2721
923
|
let burnAmount = 0n;
|
|
2722
|
-
if (marketRate >
|
|
924
|
+
if (marketRate > peggedPrice) {
|
|
2723
925
|
const lockFee = vault.calculateBitcoinFee(marketRate);
|
|
2724
926
|
const currentBitcoinHeight = await client.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => x.unwrap().blockHeight.toNumber());
|
|
2725
927
|
const blockLength = vaultClaimHeight - createdAtHeight;
|
|
@@ -2727,7 +929,7 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2727
929
|
const remainingDuration = 1 - elapsed;
|
|
2728
930
|
ratchetingFee = BigInt(remainingDuration * Number(lockFee));
|
|
2729
931
|
} else {
|
|
2730
|
-
burnAmount = await this.releasePrice(
|
|
932
|
+
burnAmount = await this.releasePrice(priceIndex, lock);
|
|
2731
933
|
}
|
|
2732
934
|
return {
|
|
2733
935
|
ratchetingFee,
|
|
@@ -2736,9 +938,9 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2736
938
|
};
|
|
2737
939
|
}
|
|
2738
940
|
async ratchet(args) {
|
|
2739
|
-
const { lock, argonKeyring, tip = 0n, vault, txProgressCallback } = args;
|
|
2740
|
-
const client =
|
|
2741
|
-
const ratchetPrice = await this.getRatchetPrice(lock, vault);
|
|
941
|
+
const { lock, priceIndex, argonKeyring, tip = 0n, vault, txProgressCallback } = args;
|
|
942
|
+
const client = this.client;
|
|
943
|
+
const ratchetPrice = await this.getRatchetPrice(lock, priceIndex, vault);
|
|
2742
944
|
const txSubmitter = new TxSubmitter(
|
|
2743
945
|
client,
|
|
2744
946
|
client.tx.bitcoinLocks.ratchet(lock.utxoId),
|
|
@@ -2770,94 +972,99 @@ var BitcoinLocks = class _BitcoinLocks {
|
|
|
2770
972
|
const api = await client.at(blockHash);
|
|
2771
973
|
const blockHeight = await api.query.system.number().then((x) => x.toNumber());
|
|
2772
974
|
const bitcoinBlockHeight = await api.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => x.unwrap().blockHeight.toNumber());
|
|
2773
|
-
const {
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
975
|
+
const {
|
|
976
|
+
amountBurned,
|
|
977
|
+
liquidityPromised: liquidityPromisedRaw,
|
|
978
|
+
newPeggedPrice,
|
|
979
|
+
originalPeggedPrice
|
|
980
|
+
} = ratchetEvent.data;
|
|
981
|
+
const liquidityPromised = liquidityPromisedRaw.toBigInt();
|
|
982
|
+
let mintAmount = liquidityPromised;
|
|
983
|
+
if (liquidityPromised > originalPeggedPrice.toBigInt()) {
|
|
984
|
+
mintAmount -= originalPeggedPrice.toBigInt();
|
|
2777
985
|
}
|
|
2778
986
|
return {
|
|
2779
987
|
txFee: submission.finalFee ?? 0n,
|
|
2780
988
|
securityFee: ratchetPrice.ratchetingFee,
|
|
2781
989
|
pendingMint: mintAmount,
|
|
2782
|
-
|
|
990
|
+
liquidityPromised,
|
|
991
|
+
newPeggedPrice: newPeggedPrice.toBigInt(),
|
|
2783
992
|
burned: amountBurned.toBigInt(),
|
|
2784
993
|
blockHeight,
|
|
2785
994
|
bitcoinBlockHeight
|
|
2786
995
|
};
|
|
2787
996
|
}
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
}
|
|
997
|
+
};
|
|
998
|
+
var PriceIndex = class {
|
|
999
|
+
constructor() {
|
|
1000
|
+
__publicField(this, "btcUsdPrice");
|
|
1001
|
+
__publicField(this, "argonotUsdPrice");
|
|
1002
|
+
__publicField(this, "argonUsdPrice");
|
|
1003
|
+
__publicField(this, "argonUsdTargetPrice");
|
|
1004
|
+
__publicField(this, "argonTimeWeightedAverageLiquidity");
|
|
1005
|
+
__publicField(this, "lastUpdatedTick");
|
|
1006
|
+
}
|
|
1007
|
+
async load(client) {
|
|
1008
|
+
const current = await client.query.priceIndex.current();
|
|
1009
|
+
if (!current.isSome) {
|
|
1010
|
+
this.argonUsdPrice = void 0;
|
|
1011
|
+
this.argonotUsdPrice = void 0;
|
|
1012
|
+
this.btcUsdPrice = void 0;
|
|
1013
|
+
this.argonUsdTargetPrice = void 0;
|
|
1014
|
+
this.argonTimeWeightedAverageLiquidity = void 0;
|
|
1015
|
+
this.lastUpdatedTick = void 0;
|
|
1016
|
+
return this;
|
|
1017
|
+
}
|
|
1018
|
+
const value = current.unwrap();
|
|
1019
|
+
this.btcUsdPrice = fromFixedNumber(value.btcUsdPrice.toBigInt(), FIXED_U128_DECIMALS);
|
|
1020
|
+
this.argonotUsdPrice = fromFixedNumber(value.argonotUsdPrice.toBigInt(), FIXED_U128_DECIMALS);
|
|
1021
|
+
this.argonUsdPrice = fromFixedNumber(value.argonUsdPrice.toBigInt(), FIXED_U128_DECIMALS);
|
|
1022
|
+
this.argonUsdTargetPrice = fromFixedNumber(
|
|
1023
|
+
value.argonUsdTargetPrice.toBigInt(),
|
|
1024
|
+
FIXED_U128_DECIMALS
|
|
1025
|
+
);
|
|
1026
|
+
this.argonTimeWeightedAverageLiquidity = fromFixedNumber(
|
|
1027
|
+
value.argonTimeWeightedAverageLiquidity.toBigInt(),
|
|
1028
|
+
FIXED_U128_DECIMALS
|
|
1029
|
+
);
|
|
1030
|
+
this.lastUpdatedTick = value.tick.toNumber();
|
|
1031
|
+
return this;
|
|
1032
|
+
}
|
|
1033
|
+
getBtcMicrogonPrice(satoshis) {
|
|
1034
|
+
if (this.btcUsdPrice === void 0 || this.argonUsdPrice === void 0) {
|
|
1035
|
+
throw new Error("PriceIndex not loaded");
|
|
1036
|
+
}
|
|
1037
|
+
const satoshiCents = this.btcUsdPrice.multipliedBy(satoshis).dividedBy(SATS_PER_BTC);
|
|
1038
|
+
const microgons = satoshiCents.multipliedBy(MICROGONS_PER_ARGON).dividedBy(this.argonUsdPrice);
|
|
1039
|
+
return BigInt(microgons.integerValue(BigNumber2__default.ROUND_DOWN).toString());
|
|
1040
|
+
}
|
|
1041
|
+
get rValue() {
|
|
1042
|
+
if (this.argonUsdTargetPrice === void 0 || this.argonUsdPrice === void 0) {
|
|
1043
|
+
throw new Error("PriceIndex not loaded");
|
|
1044
|
+
}
|
|
1045
|
+
return this.argonUsdPrice.div(this.argonUsdTargetPrice);
|
|
1046
|
+
}
|
|
1047
|
+
get argonCpi() {
|
|
1048
|
+
if (this.argonUsdTargetPrice === void 0 || this.argonUsdPrice === void 0) {
|
|
1049
|
+
throw new Error("PriceIndex not loaded");
|
|
1050
|
+
}
|
|
1051
|
+
const ratio = this.argonUsdTargetPrice.div(this.argonUsdPrice);
|
|
1052
|
+
return ratio.minus(1);
|
|
2836
1053
|
}
|
|
2837
1054
|
};
|
|
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
1055
|
async function waitForLoad() {
|
|
2849
1056
|
await cryptoWaitReady();
|
|
2850
1057
|
}
|
|
2851
|
-
async function getClient(host) {
|
|
1058
|
+
async function getClient(host, options) {
|
|
2852
1059
|
let provider;
|
|
2853
1060
|
if (host.startsWith("http")) {
|
|
2854
1061
|
provider = new HttpProvider(host);
|
|
2855
1062
|
} else {
|
|
2856
1063
|
provider = new WsProvider(host);
|
|
2857
1064
|
}
|
|
2858
|
-
return await ApiPromise.create({ provider, noInitWarn: true });
|
|
1065
|
+
return await ApiPromise.create({ provider, noInitWarn: true, ...options ?? {} });
|
|
2859
1066
|
}
|
|
2860
1067
|
|
|
2861
|
-
export {
|
|
1068
|
+
export { BitcoinLocks, ExtrinsicError2 as ExtrinsicError, FIXED_U128_DECIMALS, MICROGONS_PER_ARGON, PERMILL_DECIMALS, PriceIndex, SATS_PER_BTC, TxResult, TxSubmitter, Vault, WageProtector, checkForExtrinsicSuccess, createKeyringPair, dispatchErrorToExtrinsicError, dispatchErrorToString, formatArgons, fromFixedNumber, getAuthorFromHeader, getClient, getTickFromHeader, gettersToObject, keyringFromSuri, toFixedNumber, waitForLoad };
|
|
2862
1069
|
//# sourceMappingURL=index.js.map
|
|
2863
1070
|
//# sourceMappingURL=index.js.map
|