alkanesjs 1.2.0 → 1.2.2

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.
@@ -47368,7 +47368,8 @@ var ProtostoneTransaction = class {
47368
47368
  this.fee = Math.max(baseFee, this.MINIMUM_FEE);
47369
47369
  }
47370
47370
  calcCumulativeSpendRequirements() {
47371
- this.cumulativeSpendRequirementBtc = this.fee + this.MINIMUM_PROTOCOL_DUST * 2;
47371
+ this.cumulativeSpendRequirementBtc = this.fee + this.MINIMUM_PROTOCOL_DUST * (this.transactionOptions.transfers?.length ?? 0) + this.MINIMUM_PROTOCOL_DUST;
47372
+ console.log(this.cumulativeSpendRequirementBtc);
47372
47373
  this.cumulativeSpendRequirementAlkanes = this.transactionOptions.transfers.reduce(
47373
47374
  (acc, transfer) => {
47374
47375
  if (isBTCTransfer(transfer)) {
@@ -47596,7 +47597,7 @@ var ProtostoneTransaction = class {
47596
47597
  ),
47597
47598
  // Convert bigint to string for JSON compatibility
47598
47599
  amount: (0, import_integer.u128)(transfer.amount),
47599
- output: (0, import_integer.u32)(outputIds[address3] + (hasChange ? 1 : 0))
47600
+ output: (0, import_integer.u32)(outputIds[address3] + 1)
47600
47601
  };
47601
47602
  if (!alkanesEdicts[address3]) {
47602
47603
  alkanesEdicts[address3] = {};
@@ -47616,6 +47617,7 @@ var ProtostoneTransaction = class {
47616
47617
  output: edict.output
47617
47618
  }))
47618
47619
  );
47620
+ console.log(transactionEdicts[0]);
47619
47621
  return transactionEdicts;
47620
47622
  }
47621
47623
  addProtostoneData(edicts) {
@@ -52674,6 +52676,53 @@ var ElectrumApiProvider = class {
52674
52676
  );
52675
52677
  }
52676
52678
  }
52679
+ async esplora_getblocktiphash() {
52680
+ try {
52681
+ const requestUrl = `${this.electrumApiUrl}/blocks/tip/hash`;
52682
+ const httpResponse = await fetch(requestUrl);
52683
+ if (!httpResponse.ok) {
52684
+ return new BoxedError(
52685
+ "UnknownError" /* UnknownError */,
52686
+ `Failed to fetch tip hash from ${requestUrl}: ${httpResponse.statusText}`
52687
+ );
52688
+ }
52689
+ const tipHash = (await httpResponse.text()).trim();
52690
+ return new BoxedSuccess(tipHash);
52691
+ } catch (error) {
52692
+ return new BoxedError(
52693
+ "UnknownError" /* UnknownError */,
52694
+ `Failed to fetch tip hash: ${error.message}`
52695
+ );
52696
+ }
52697
+ }
52698
+ async _esplora_getrawblock(blockHash) {
52699
+ try {
52700
+ const requestUrl = `${this.electrumApiUrl}/block/${blockHash}/raw`;
52701
+ const httpResponse = await fetch(requestUrl);
52702
+ if (!httpResponse.ok) {
52703
+ return new BoxedError(
52704
+ "UnknownError" /* UnknownError */,
52705
+ `Failed to fetch raw block ${blockHash} from ${requestUrl}: ${httpResponse.statusText}`
52706
+ );
52707
+ }
52708
+ const bytes3 = new Uint8Array(await httpResponse.arrayBuffer());
52709
+ const rawHex = Array.from(
52710
+ bytes3,
52711
+ (b) => b.toString(16).padStart(2, "0")
52712
+ ).join("");
52713
+ return new BoxedSuccess("0x" + rawHex);
52714
+ } catch (error) {
52715
+ return new BoxedError(
52716
+ "UnknownError" /* UnknownError */,
52717
+ `Failed to fetch raw block ${blockHash}: ${error.message}`
52718
+ );
52719
+ }
52720
+ }
52721
+ async esplora_getrawblocktip() {
52722
+ const tipHashResponse = await this.esplora_getblocktiphash();
52723
+ if (isBoxedError(tipHashResponse)) return tipHashResponse;
52724
+ return this._esplora_getrawblock(tipHashResponse.data);
52725
+ }
52677
52726
  /*
52678
52727
  async esplora_getbulktransactions(
52679
52728
  transactionIds: string[],
@@ -55209,6 +55258,42 @@ init_shim();
55209
55258
  init_process();
55210
55259
  init_buffer();
55211
55260
  var stripHex = (s) => s.startsWith("0x") ? s.slice(2) : s;
55261
+ function toU64LittleEndianHex(numStr) {
55262
+ const num2 = BigInt(numStr);
55263
+ const hex4 = num2.toString(16).padStart(16, "0");
55264
+ const bytes3 = hex4.match(/.{2}/g);
55265
+ if (!bytes3) throw new Error("Invalid hex conversion");
55266
+ const littleEndian = bytes3.reverse().join("");
55267
+ return `0x${littleEndian}`;
55268
+ }
55269
+ function makeFakeBlock(height) {
55270
+ const buf = new Uint8Array(80);
55271
+ const h = BigInt(height);
55272
+ for (let i = 0; i < 8; i++) {
55273
+ buf[72 + i] = Number(h >> BigInt(8 * i) & 0xffn);
55274
+ }
55275
+ const hex4 = Array.from(buf, (b) => b.toString(16).padStart(2, "0")).join("");
55276
+ return `${hex4}`;
55277
+ }
55278
+ function toU64BigEndianHex(numStr) {
55279
+ const MAX_U64 = BigInt("0xffffffffffffffff");
55280
+ const num2 = BigInt(numStr);
55281
+ if (num2 < 0n || num2 > MAX_U64) {
55282
+ throw new RangeError("Value exceeds u64 range");
55283
+ }
55284
+ const hex4 = num2.toString(16).padStart(16, "0");
55285
+ return `0x${hex4}`;
55286
+ }
55287
+ function toU128LittleEndianHex(numStr) {
55288
+ const MAX_U1282 = BigInt("0xffffffffffffffffffffffffffffffff");
55289
+ const num2 = BigInt(numStr);
55290
+ if (num2 < 0n || num2 > MAX_U1282) {
55291
+ throw new RangeError("Value exceeds u128 range");
55292
+ }
55293
+ const hex4 = num2.toString(16).padStart(32, "0");
55294
+ const littleEndian = hex4.match(/.{2}/g).reverse().join("");
55295
+ return `0x${littleEndian}`;
55296
+ }
55212
55297
  function mapToPrimitives(v) {
55213
55298
  switch (typeof v) {
55214
55299
  case "bigint":
@@ -55217,7 +55302,9 @@ function mapToPrimitives(v) {
55217
55302
  if (v === null) return null;
55218
55303
  if (Buffer3.isBuffer(v)) return "0x" + v.toString("hex");
55219
55304
  if (Array.isArray(v)) return v.map(mapToPrimitives);
55220
- return Object.fromEntries(Object.entries(v).map(([k, val]) => [k, mapToPrimitives(val)]));
55305
+ return Object.fromEntries(
55306
+ Object.entries(v).map(([k, val]) => [k, mapToPrimitives(val)])
55307
+ );
55221
55308
  }
55222
55309
  default:
55223
55310
  return v;
@@ -55226,13 +55313,16 @@ function mapToPrimitives(v) {
55226
55313
  function unmapFromPrimitives(v) {
55227
55314
  switch (typeof v) {
55228
55315
  case "string":
55229
- if (v.startsWith("0x") && v !== "0x") return Buffer3.from(stripHex(v), "hex");
55316
+ if (v.startsWith("0x") && v !== "0x")
55317
+ return Buffer3.from(stripHex(v), "hex");
55230
55318
  if (!isNaN(v)) return BigInt(v);
55231
55319
  return v;
55232
55320
  case "object": {
55233
55321
  if (v === null) return null;
55234
55322
  if (Array.isArray(v)) return v.map(unmapFromPrimitives);
55235
- return Object.fromEntries(Object.entries(v).map(([k, val]) => [k, unmapFromPrimitives(val)]));
55323
+ return Object.fromEntries(
55324
+ Object.entries(v).map(([k, val]) => [k, unmapFromPrimitives(val)])
55325
+ );
55236
55326
  }
55237
55327
  default:
55238
55328
  return v;
@@ -55242,7 +55332,9 @@ function parseSimulateReturn(v) {
55242
55332
  if (v === "0x") return void 0;
55243
55333
  const toUtf8 = Buffer3.from(stripHex(v), "hex").toString("utf8");
55244
55334
  const isUtf8 = !/[\uFFFD]/.test(toUtf8);
55245
- const rev = Buffer3.from(Array.from(Buffer3.from(stripHex(v), "hex")).reverse()).toString("hex");
55335
+ const rev = Buffer3.from(
55336
+ Array.from(Buffer3.from(stripHex(v), "hex")).reverse()
55337
+ ).toString("hex");
55246
55338
  return {
55247
55339
  string: isUtf8 ? toUtf8 : "0x" + stripHex(v),
55248
55340
  bytes: "0x" + stripHex(v),
@@ -55364,6 +55456,7 @@ var AlkanesRpcProvider = class {
55364
55456
  payload: ["alkanes_trace", [{ txid: leTxid, vout }]],
55365
55457
  call: async () => {
55366
55458
  try {
55459
+ await this.provider.pacer.waitForPacer();
55367
55460
  const encoded = consumeOrThrow(
55368
55461
  await this.rpc("alkanes_trace", [
55369
55462
  { txid: leTxid, vout }
@@ -55435,14 +55528,12 @@ var AlkanesRpcProvider = class {
55435
55528
  ]);
55436
55529
  }
55437
55530
  async alkanes_simulate(req) {
55438
- const currentHeight = consumeOrThrow(
55439
- await this.alkanes_metashrewHeight().call()
55440
- );
55531
+ await this.provider.pacer.waitForPacer();
55441
55532
  const merged = {
55442
55533
  alkanes: req.alkanes ?? [],
55443
55534
  transaction: req.transaction ?? "0x",
55444
55535
  block: "0x",
55445
- height: req.height ?? currentHeight,
55536
+ height: "908474",
55446
55537
  txindex: req.txindex ?? 0,
55447
55538
  target: {
55448
55539
  block: req.target?.block?.toString() ?? "0",
@@ -55453,6 +55544,7 @@ var AlkanesRpcProvider = class {
55453
55544
  refundPointer: req.refundPointer ?? 0,
55454
55545
  vout: req.vout ?? 0
55455
55546
  };
55547
+ console.log(merged);
55456
55548
  const res = await this.rpc(
55457
55549
  "alkanes_simulate",
55458
55550
  [merged]
@@ -55825,19 +55917,91 @@ var schemaAlkaneId = import_borsher4.BorshSchema.Struct({
55825
55917
  init_shim();
55826
55918
  init_process();
55827
55919
  init_buffer();
55920
+
55921
+ // src/pacer.ts
55922
+ init_shim();
55923
+ init_process();
55924
+ init_buffer();
55925
+ var WaitPacer = class {
55926
+ constructor(opts) {
55927
+ __publicField(this, "maxPerInterval");
55928
+ __publicField(this, "intervalMs");
55929
+ __publicField(this, "minGapMs");
55930
+ // track start times within the sliding window
55931
+ __publicField(this, "starts", []);
55932
+ __publicField(this, "lastStart", 0);
55933
+ // serialize callers so their start times are paced correctly
55934
+ __publicField(this, "tail", Promise.resolve());
55935
+ this.maxPerInterval = Math.max(1, opts.maxPerInterval);
55936
+ this.intervalMs = Math.max(1, opts.intervalMs);
55937
+ this.minGapMs = Math.floor(this.intervalMs / this.maxPerInterval);
55938
+ }
55939
+ setRate(maxPerInterval, intervalMs) {
55940
+ this.maxPerInterval = Math.max(1, maxPerInterval);
55941
+ this.intervalMs = Math.max(1, intervalMs);
55942
+ this.minGapMs = Math.floor(this.intervalMs / this.maxPerInterval);
55943
+ }
55944
+ now() {
55945
+ return Date.now();
55946
+ }
55947
+ sleep(ms) {
55948
+ return ms > 0 ? new Promise((r) => setTimeout(r, ms)) : Promise.resolve();
55949
+ }
55950
+ pruneWindow(now) {
55951
+ const cutoff = now - this.intervalMs;
55952
+ while (this.starts.length && this.starts[0] <= cutoff) this.starts.shift();
55953
+ }
55954
+ /** Await this immediately before the call that could rate-limit */
55955
+ waitForPacer() {
55956
+ const ticket = this.tail.then(async () => {
55957
+ while (true) {
55958
+ const now = this.now();
55959
+ this.pruneWindow(now);
55960
+ if (this.starts.length >= this.maxPerInterval) {
55961
+ const earliest = this.starts[0];
55962
+ const waitUntil = earliest + this.intervalMs;
55963
+ await this.sleep(Math.max(0, waitUntil - this.now()));
55964
+ continue;
55965
+ }
55966
+ const earliestStart = this.lastStart + this.minGapMs;
55967
+ const delay = Math.max(0, earliestStart - now);
55968
+ if (delay > 0) {
55969
+ await this.sleep(delay);
55970
+ continue;
55971
+ }
55972
+ const startTs = this.now();
55973
+ this.lastStart = startTs;
55974
+ this.starts.push(startTs);
55975
+ break;
55976
+ }
55977
+ });
55978
+ this.tail = ticket.catch(() => {
55979
+ });
55980
+ return ticket;
55981
+ }
55982
+ };
55983
+
55984
+ // src/provider.ts
55828
55985
  var Provider = class {
55829
- // 5 seconds
55830
55986
  constructor(config3) {
55831
55987
  __publicField(this, "sandshrewUrl");
55832
55988
  __publicField(this, "electrumApiUrl");
55833
55989
  __publicField(this, "network");
55834
55990
  __publicField(this, "explorerUrl");
55991
+ __publicField(this, "pacerSettings", {
55992
+ intervalMs: 1e3,
55993
+ maxPerInterval: 10
55994
+ });
55835
55995
  __publicField(this, "btcTicker");
55996
+ __publicField(this, "jitterMs", 1e3);
55997
+ // 1 second
55836
55998
  __publicField(this, "rpc");
55837
55999
  __publicField(this, "defaultFeeRate");
55838
56000
  __publicField(this, "TIMEOUT_MS", 6e4 * 5);
55839
56001
  // 5 minutes
55840
56002
  __publicField(this, "INTERVAL_MS", 5e3);
56003
+ // 5 seconds
56004
+ __publicField(this, "pacer");
55841
56005
  __publicField(this, "waitForBlocks", async (amount) => {
55842
56006
  try {
55843
56007
  let initialBlockCount = Number(
@@ -55929,8 +56093,10 @@ var Provider = class {
55929
56093
  this.network = config3.network;
55930
56094
  this.explorerUrl = config3.explorerUrl.replace(/\/+$/, "");
55931
56095
  this.btcTicker = config3.btcTicker ?? "BTC";
56096
+ this.pacerSettings = config3.pacerSettings ?? this.pacerSettings;
55932
56097
  this.defaultFeeRate = config3.defaultFeeRate ?? 5;
55933
56098
  this.rpc = new BaseRpcProvider(this);
56099
+ this.pacer = new WaitPacer(this.pacerSettings);
55934
56100
  }
55935
56101
  txUrl(txid) {
55936
56102
  return `${this.explorerUrl}/tx/${txid}`;
@@ -56039,6 +56205,7 @@ export {
56039
56205
  getProtostoneUnsignedPsbtBase64,
56040
56206
  getVSize,
56041
56207
  hexToUint8Array,
56208
+ makeFakeBlock,
56042
56209
  mapToPrimitives,
56043
56210
  minimumFee,
56044
56211
  parseSimulateReturn,
@@ -56052,6 +56219,9 @@ export {
56052
56219
  tapTweakHash,
56053
56220
  toEsploraTx,
56054
56221
  toFormattedUtxo,
56222
+ toU128LittleEndianHex,
56223
+ toU64BigEndianHex,
56224
+ toU64LittleEndianHex,
56055
56225
  trimUndefined,
56056
56226
  tweakSigner,
56057
56227
  u128Schema,