PHP WebShell

Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@polkadot-api/observable-client/dist

Просмотр файла: index.js

"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);

// src/index.ts
var src_exports = {};
__export(src_exports, {
  BlockNotPinnedError: () => BlockNotPinnedError,
  BlockPrunedError: () => BlockPrunedError,
  NotBestBlockError: () => NotBestBlockError,
  getObservableClient: () => getObservableClient
});
module.exports = __toCommonJS(src_exports);

// src/utils/shareLatest.ts
var import_rxjs = require("rxjs");
var shareLatest = (0, import_rxjs.share)({
  connector: () => new import_rxjs.ReplaySubject(1),
  resetOnError: true,
  resetOnComplete: true,
  resetOnRefCountZero: true
});

// src/utils/concatMapEager.ts
var import_rxjs2 = require("rxjs");
var concatMapEager = (mapper, concurrent = Infinity) => (source$) => new import_rxjs2.Observable((observer) => {
  let topSubscription;
  const queues = /* @__PURE__ */ new Map();
  const innerSubscriptions = /* @__PURE__ */ new Map();
  const results = /* @__PURE__ */ new Map();
  let mapperIdx = 0;
  let subscriptionIdx = 0;
  let observerIdx = 0;
  const nextSubscription = () => {
    const inner$ = queues.get(subscriptionIdx);
    if (!inner$) {
      if (innerSubscriptions.size === 0 && (typeof topSubscription === "undefined" || topSubscription.closed)) {
        observer.complete();
      }
      return;
    }
    const idx = subscriptionIdx++;
    queues.delete(idx);
    if (observerIdx !== idx) {
      results.set(idx, []);
    }
    innerSubscriptions.set(
      idx,
      inner$.subscribe({
        next(x) {
          if (observerIdx === idx) {
            observer.next(x);
          } else {
            results.get(idx).push(x);
          }
        },
        complete() {
          innerSubscriptions.delete(idx);
          if (idx === observerIdx) {
            observerIdx++;
            while (results.has(observerIdx)) {
              results.get(observerIdx).forEach((x) => observer.next(x));
              results.delete(observerIdx);
              if (innerSubscriptions.has(observerIdx)) {
                break;
              }
              observerIdx++;
            }
          }
          nextSubscription();
        },
        error(e) {
          observer.error(e);
        }
      })
    );
  };
  topSubscription = source$.subscribe({
    next(outterValue) {
      const idx = mapperIdx++;
      queues.set(
        idx,
        (0, import_rxjs2.defer)(() => mapper(outterValue, idx))
      );
      if (innerSubscriptions.size < concurrent) {
        nextSubscription();
      }
    },
    error(e) {
      observer.error(e);
    },
    complete() {
      if (innerSubscriptions.size === 0) {
        observer.complete();
      }
    }
  });
  return () => {
    innerSubscriptions.forEach((subscription) => subscription.unsubscribe());
    topSubscription.unsubscribe();
    queues.clear();
    results.clear();
  };
});

// src/utils/with-default-value.ts
var import_rxjs3 = require("rxjs");
var withDefaultValue = (defaultValue) => (source$) => new import_rxjs3.Observable((observer) => {
  let hasEmited = false;
  const subscription = source$.subscribe({
    next(v) {
      hasEmited = true;
      observer.next(v);
    },
    error(e) {
      observer.error(e);
    },
    complete() {
      observer.complete();
    }
  });
  if (!hasEmited) observer.next(defaultValue);
  return subscription;
});

// src/chainHead/chainHead.ts
var import_substrate_bindings2 = require("@polkadot-api/substrate-bindings");
var import_substrate_client4 = require("@polkadot-api/substrate-client");
var import_rxjs17 = require("rxjs");

// src/chainHead/enhancers/operationLimitRecovery.ts
var import_substrate_client = require("@polkadot-api/substrate-client");
var import_rxjs4 = require("rxjs");
var PendingTaskQueue = class {
  constructor() {
    __publicField(this, "first");
    __publicField(this, "last");
  }
  getRemoveFn(node) {
    return () => {
      if (node.prev) {
        node.prev.next = node.next;
      } else {
        this.first = node.next;
      }
      if (node.next) {
        node.next.prev = node.prev;
      } else {
        this.last = node.prev;
      }
      delete node.prev;
      delete node.next;
    };
  }
  push(value) {
    const newNode = { value };
    if (this.last === void 0) {
      this.last = this.first = newNode;
    } else {
      this.last.next = newNode;
      newNode.prev = this.last;
      this.last = newNode;
    }
    return this.getRemoveFn(newNode);
  }
  unshift(value) {
    this.first = { value, next: this.first };
    this.first.next && (this.first.next.prev = this.first);
    this.last || (this.last = this.first);
    return this.getRemoveFn(this.first);
  }
  pop() {
    const result = this.first?.value;
    if (this.first) {
      this.first = this.first.next;
      if (!this.first) {
        this.last = void 0;
      } else {
        delete this.first.prev?.next;
        delete this.first.prev;
      }
    }
    return result;
  }
  isEmpty() {
    return !this.first;
  }
};
var getWithRecovery = () => {
  const tearDownOperations = /* @__PURE__ */ new Map();
  const setTeardown = (observable, cb) => {
    tearDownOperations.set(observable, () => {
      tearDownOperations.delete(observable);
      cb();
    });
  };
  const teardown = (observable) => {
    tearDownOperations.get(observable)?.();
  };
  const pendingTasks = new PendingTaskQueue();
  const unshift = pendingTasks.unshift.bind(pendingTasks);
  const push = pendingTasks.push.bind(pendingTasks);
  const addTask = (task, topPriority) => {
    const fn = topPriority ? unshift : push;
    setTeardown(task.source$, fn(task));
  };
  const onEmptySlot = () => {
    const data = pendingTasks.pop();
    if (!data) return;
    tearDownOperations.delete(data.source$);
    process(data);
  };
  const process = (data) => {
    const { source$, observer } = data;
    let isOperationLimit = false;
    const subscription = source$.subscribe({
      next(x) {
        observer.next(x);
      },
      error(e) {
        ;
        (isOperationLimit = e instanceof import_substrate_client.OperationLimitError) ? addTask(data, true) : observer.error(e);
      },
      complete() {
        observer.complete();
      }
    });
    if (!subscription.closed) {
      setTeardown(source$, () => {
        subscription.unsubscribe();
        onEmptySlot();
      });
    } else if (!isOperationLimit) onEmptySlot();
  };
  const withRecovery = (topPriority = false) => (source$) => new import_rxjs4.Observable((observer) => {
    const pendingTask = { observer, source$ };
    if (pendingTasks.isEmpty()) {
      process(pendingTask);
    } else {
      addTask(pendingTask, topPriority);
    }
    return () => {
      teardown(source$);
    };
  });
  const withNormalRecovery = withRecovery();
  const withRecoveryFn = (fn) => (...args) => withNormalRecovery(fn(...args));
  return { withRecovery, withRecoveryFn };
};

// src/chainHead/enhancers/optionalHash.ts
var import_rxjs5 = require("rxjs");
var getWithOptionalhash$ = (finalized$, best$) => {
  return (fn) => (hash, ...args) => {
    const hash$ = hash === null || hash === "finalized" ? finalized$ : hash === "best" ? best$ : (0, import_rxjs5.of)(hash);
    return hash$.pipe(
      (0, import_rxjs5.take)(1),
      (0, import_rxjs5.mergeMap)((h) => fn(h, ...args))
    );
  };
};

// src/chainHead/enhancers/fromAbortControllerFn.ts
var import_rxjs6 = require("rxjs");
var fromAbortControllerFn = (fn) => (...args) => new import_rxjs6.Observable((observer) => {
  let aborter = new AbortController();
  fn(...[...args, aborter.signal]).then(
    (value) => {
      observer.next(value);
      observer.complete();
    },
    (error) => {
      observer.error(error);
    }
  );
  return () => {
    observer.unsubscribe();
    aborter.abort();
    aborter = void 0;
  };
});

// src/chainHead/enhancers/lazyFollower.ts
var withLazyFollower = (getFollower) => (key) => (...args) => getFollower()[key](...args);

// src/chainHead/enhancers/whileBestBlock.ts
var import_rxjs11 = require("rxjs");

// src/chainHead/errors.ts
var BlockNotPinnedError = class extends Error {
  constructor() {
    super("Block is not pinned");
    this.name = "BlockNotPinnedError";
  }
};
var BlockPrunedError = class extends Error {
  constructor() {
    super("Block pruned");
    this.name = "BlockPrunedError";
  }
};
var NotBestBlockError = class extends Error {
  constructor() {
    super("Block is not best block or finalized");
    this.name = "NotBestBlockError";
  }
};

// src/chainHead/streams/follow.ts
var import_substrate_client2 = require("@polkadot-api/substrate-client");
var import_rxjs7 = require("rxjs");
var getFollow$ = (chainHead) => {
  let follower = null;
  let unfollow = import_rxjs7.noop;
  const follow$ = new import_rxjs7.Observable((observer) => {
    follower = chainHead(
      true,
      (e) => {
        observer.next(e);
      },
      (e) => {
        follower = null;
        observer.error(e);
      }
    );
    unfollow = () => {
      observer.complete();
      follower?.unfollow();
    };
  }).pipe((0, import_rxjs7.share)());
  return {
    getFollower: () => {
      if (!follower) throw new Error("Missing chainHead subscription");
      return follower;
    },
    unfollow: () => {
      unfollow();
    },
    follow$
  };
};
var retryOnStopError = () => (source$) => new import_rxjs7.Observable((observer) => {
  const subscription = new import_rxjs7.Subscription();
  const subscribe = () => source$.subscribe({
    next: (v) => observer.next(v),
    error: (e) => {
      if (e instanceof import_substrate_client2.StopError) {
        observer.next({ type: "stop-error" });
        subscription.add(subscribe());
      } else {
        observer.error(e);
      }
    },
    complete: () => observer.complete()
  });
  subscription.add(subscribe());
  return subscription;
});

// src/chainHead/streams/get-runtime-creator.ts
var import_metadata_builders = require("@polkadot-api/metadata-builders");
var import_substrate_bindings = require("@polkadot-api/substrate-bindings");
var import_utils = require("@polkadot-api/utils");
var import_rxjs8 = require("rxjs");
var v15Args = (0, import_utils.toHex)(import_substrate_bindings.u32.enc(15));
var opaqueMeta14 = (0, import_substrate_bindings.Tuple)(import_substrate_bindings.compact, (0, import_substrate_bindings.Bytes)());
var opaqueMeta15 = (0, import_substrate_bindings.Option)((0, import_substrate_bindings.Bytes)());
var u32ListDecoder = (0, import_substrate_bindings.Vector)(import_substrate_bindings.u32).dec;
var getRuntimeCreator = (call$, finalized$) => {
  const getMetadata$ = (hash) => {
    const recoverCall$ = (hash2, method, args) => call$(hash2, method, args).pipe(
      (0, import_rxjs8.catchError)((e) => {
        if (e instanceof BlockNotPinnedError) {
          return finalized$.pipe(
            (0, import_rxjs8.take)(1),
            (0, import_rxjs8.switchMap)((newHash) => recoverCall$(newHash, method, args))
          );
        }
        throw e;
      })
    );
    const versions = recoverCall$(hash, "Metadata_metadata_versions", "").pipe(
      (0, import_rxjs8.map)(u32ListDecoder)
    );
    const v14 = recoverCall$(hash, "Metadata_metadata", "").pipe(
      (0, import_rxjs8.map)((x) => {
        const [, metadataRaw] = opaqueMeta14.dec(x);
        const metadata = import_substrate_bindings.metadata.dec(metadataRaw);
        return { metadata: metadata.metadata.value, metadataRaw };
      })
    );
    const v15 = recoverCall$(
      hash,
      "Metadata_metadata_at_version",
      v15Args
    ).pipe(
      (0, import_rxjs8.map)((x) => {
        const metadataRaw = opaqueMeta15.dec(x);
        const metadata = import_substrate_bindings.metadata.dec(metadataRaw);
        return { metadata: metadata.metadata.value, metadataRaw };
      })
    );
    return versions.pipe(
      (0, import_rxjs8.catchError)(() => (0, import_rxjs8.of)([14])),
      (0, import_rxjs8.mergeMap)((v) => v.includes(15) ? v15 : v14)
    );
  };
  return (hash) => {
    const usages = /* @__PURE__ */ new Set([hash]);
    const runtimeContext$ = getMetadata$(hash).pipe(
      (0, import_rxjs8.map)(({ metadata, metadataRaw }) => {
        const checksumBuilder = (0, import_metadata_builders.getChecksumBuilder)(metadata);
        const dynamicBuilder = (0, import_metadata_builders.getDynamicBuilder)(metadata);
        const events = dynamicBuilder.buildStorage("System", "Events");
        const assetPayment = metadata.extrinsic.signedExtensions.find(
          (x) => x.identifier === "ChargeAssetTxPayment"
        );
        let _assetId = null;
        if (assetPayment) {
          const assetTxPayment = (0, import_metadata_builders.getLookupFn)(metadata.lookup)(assetPayment.type);
          if (assetTxPayment.type === "struct") {
            const optionalAssetId = assetTxPayment.value.asset_id;
            if (optionalAssetId.type === "option")
              _assetId = optionalAssetId.value.id;
          }
        }
        const asset = _assetId === null ? [import_substrate_bindings._void.enc, null] : [
          dynamicBuilder.buildDefinition(_assetId).enc,
          checksumBuilder.buildDefinition(_assetId)
        ];
        return {
          asset,
          metadataRaw,
          metadata,
          checksumBuilder,
          dynamicBuilder,
          events: {
            key: events.enc(),
            dec: events.dec
          },
          accountId: (0, import_substrate_bindings.AccountId)(dynamicBuilder.ss58Prefix)
        };
      }),
      (0, import_rxjs8.shareReplay)(1)
    );
    const result = {
      at: hash,
      runtime: runtimeContext$,
      addBlock: (block) => {
        usages.add(block);
        return result;
      },
      deleteBlocks: (blocks) => {
        blocks.forEach((block) => {
          usages.delete(block);
        });
        return usages.size;
      },
      usages
    };
    runtimeContext$.subscribe();
    return result;
  };
};

// src/chainHead/streams/pinned-blocks.ts
var import_rxjs9 = require("rxjs");
var deleteBlock = (blocks, blockHash) => {
  blocks.get(blocks.get(blockHash).parent)?.children.delete(blockHash);
  blocks.delete(blockHash);
};
var getBlocksToUnpin = (blocks, pruned) => {
  const result = [...pruned];
  let current = blocks.blocks.get(blocks.blocks.get(blocks.finalized).parent);
  const trail = [];
  while (current) {
    trail.push(current.hash);
    if (current.refCount === 0 && !current.unpinned) {
      result.push(current.hash);
      current.unpinned = true;
    }
    current = blocks.blocks.get(current.parent);
  }
  const deletedBlocks = [...pruned];
  for (let i = trail.length - 1; i >= 0; i--) {
    current = blocks.blocks.get(trail[i]);
    if (!current.unpinned) return result;
    deletedBlocks.push(current.hash);
  }
  deletedBlocks.forEach((hash) => {
    deleteBlock(blocks.blocks, hash);
  });
  Object.entries(blocks.runtimes).map(([key, value]) => ({
    key,
    usages: value.deleteBlocks(deletedBlocks)
  })).filter((x) => x.usages === 0).map((x) => x.key).forEach((unusedRuntime) => {
    delete blocks.runtimes[unusedRuntime];
  });
  return result;
};
var getPinnedBlocks$ = (follow$, getHeader, call$, blockUsage$, onUnpin) => {
  const pinnedBlocks$ = (0, import_rxjs9.merge)(
    blockUsage$,
    follow$.pipe(withInitializedNumber(getHeader), retryOnStopError())
  ).pipe(
    (0, import_rxjs9.scan)((acc, event) => {
      switch (event.type) {
        case "initialized":
          if (acc.recovering) {
            const isConnected = event.finalizedBlockHashes.some(
              (hash) => acc.blocks.has(hash)
            );
            if (!isConnected) {
              acc = getInitialPinnedBlocks();
            }
          }
          const [finalizedHash] = event.finalizedBlockHashes.slice(-1);
          acc.finalized = acc.best = finalizedHash;
          const lastIdx = event.finalizedBlockHashes.length - 1;
          event.finalizedBlockHashes.forEach((hash, i) => {
            if (acc.blocks.has(hash)) {
              acc.blocks.get(hash).recovering = false;
            } else {
              acc.blocks.set(hash, {
                hash,
                parent: i === 0 ? event.parentHash : event.finalizedBlockHashes[i - 1],
                children: new Set(
                  i === lastIdx ? [] : [event.finalizedBlockHashes[i + 1]]
                ),
                runtime: hash,
                refCount: 0,
                number: event.number + i,
                recovering: false
              });
            }
          });
          const finalizedRuntime = Object.values(acc.runtimes).find(
            (runtime) => runtime.usages.has(finalizedHash)
          );
          acc.finalizedRuntime = finalizedRuntime ?? (acc.runtimes[finalizedHash] = getRuntime(finalizedHash));
          return acc;
        case "stop-error":
          for (const block of acc.blocks.values()) {
            block.recovering = true;
          }
          acc.recovering = true;
          return acc;
        case "newBlock": {
          const { parentBlockHash: parent, blockHash: hash } = event;
          if (acc.blocks.has(hash)) {
            acc.blocks.get(hash).recovering = false;
          } else {
            const parentNode = acc.blocks.get(parent);
            parentNode.children.add(hash);
            if (event.newRuntime) {
              acc.runtimes[hash] = getRuntime(hash);
              acc.runtimes[hash].runtime.subscribe();
            }
            const block = {
              hash,
              number: parentNode.number + 1,
              parent,
              children: /* @__PURE__ */ new Set(),
              runtime: event.newRuntime ? hash : parentNode.runtime,
              refCount: 0,
              recovering: false
            };
            acc.blocks.set(hash, block);
            acc.runtimes[block.runtime].addBlock(hash);
          }
          return acc;
        }
        case "bestBlockChanged": {
          if (acc.recovering) {
            for (const [hash, block] of acc.blocks) {
              if (block.recovering) {
                deleteBlock(acc.blocks, hash);
              }
            }
            acc.recovering = false;
          }
          acc.best = event.bestBlockHash;
          return acc;
        }
        case "finalized": {
          acc.finalized = event.finalizedBlockHashes.slice(-1)[0];
          acc.finalizedRuntime = acc.runtimes[acc.blocks.get(acc.finalized).runtime];
          const actuallyPruned = [...new Set(event.prunedBlockHashes)];
          onUnpin(getBlocksToUnpin(acc, actuallyPruned));
          return acc;
        }
        case "blockUsage": {
          if (!acc.blocks.has(event.value.hash)) return acc;
          const block = acc.blocks.get(event.value.hash);
          block.refCount += event.value.type === "hold" ? 1 : -1;
          if (block.refCount === 0 && block.number < acc.blocks.get(acc.finalized).number && !block.recovering) {
            block.unpinned = true;
            onUnpin([block.hash]);
          }
          return acc;
        }
      }
    }, getInitialPinnedBlocks()),
    (0, import_rxjs9.filter)((x) => !!x.finalizedRuntime.runtime),
    (0, import_rxjs9.map)((x) => ({ ...x })),
    shareLatest
  );
  const getRuntime = getRuntimeCreator(
    withStopRecovery(pinnedBlocks$, call$),
    pinnedBlocks$.pipe((0, import_rxjs9.map)((v) => v.finalized))
  );
  return pinnedBlocks$;
};
var getInitialPinnedBlocks = () => ({
  best: "",
  finalized: "",
  runtimes: {},
  blocks: /* @__PURE__ */ new Map(),
  finalizedRuntime: {},
  recovering: false
});
var withInitializedNumber = (getHeader) => (source$) => source$.pipe(
  (0, import_rxjs9.concatMap)((event) => {
    return event.type !== "initialized" ? (0, import_rxjs9.of)(event) : getHeader(event.finalizedBlockHashes[0]).then((header) => ({
      ...event,
      number: header.number,
      parentHash: header.parentHash
    }));
  })
);

// src/chainHead/streams/block-operations.ts
var import_rxjs10 = require("rxjs");
var isBestOrFinalizedBlock = (blocks$, blockHash) => blocks$.pipe(
  (0, import_rxjs10.takeWhile)((b) => b.blocks.has(blockHash)),
  (0, import_rxjs10.distinctUntilChanged)(
    (a, b) => a.finalized === b.finalized && a.best === b.best
  ),
  (0, import_rxjs10.filter)(
    (x) => x.blocks.get(x.best).number >= x.blocks.get(blockHash).number
  ),
  (0, import_rxjs10.map)((pinned) => {
    const { number } = pinned.blocks.get(blockHash);
    let current = pinned.blocks.get(pinned.best);
    let isFinalized = pinned.finalized === current.hash;
    while (current.number > number) {
      current = pinned.blocks.get(current.parent);
      isFinalized = isFinalized || pinned.finalized === current.hash;
    }
    if (isFinalized) return "finalized";
    return current.hash === blockHash ? "best" : null;
  }),
  (0, import_rxjs10.distinctUntilChanged)(),
  (0, import_rxjs10.takeWhile)((x) => x !== "finalized", true)
);

// src/chainHead/enhancers/whileBestBlock.ts
function withEnsureCanonicalChain(blocks$, follow$, fn) {
  return (hash, ensureCanonical, ...args) => {
    const enhancer = ensureCanonical ? (0, import_rxjs11.pipe)(
      throwWhenPrune(
        hash,
        follow$.pipe(
          retryOnStopError(),
          (0, import_rxjs11.filter)((evt) => evt.type === "finalized"),
          (0, import_rxjs11.mergeMap)((evt) => evt.prunedBlockHashes)
        )
      ),
      onlyIfIsBestOrFinalized(hash, blocks$)
    ) : (x) => x;
    return enhancer(fn(hash, ...args));
  };
}
var onlyIfIsBestOrFinalized = (hash, blocks$) => (source$) => isBestOrFinalizedBlock(blocks$, hash).pipe(
  (0, import_rxjs11.take)(1),
  (0, import_rxjs11.switchMap)(
    (isBest) => isBest ? source$ : (0, import_rxjs11.throwError)(() => new NotBestBlockError())
  )
);
var throwWhenPrune = (hash, pruned$) => (source$) => new import_rxjs11.Observable((subscriber) => {
  const prunedSubscription = pruned$.pipe((0, import_rxjs11.filter)((h) => h === hash)).subscribe(() => {
    subscriber.error(new BlockPrunedError());
  });
  const sourceSubscription = source$.subscribe(subscriber);
  return () => {
    prunedSubscription.unsubscribe();
    sourceSubscription.unsubscribe();
  };
});

// src/chainHead/enhancers/withStopRecovery.ts
var import_rxjs12 = require("rxjs");
function withStopRecovery(blocks$, fn) {
  return (hash, ...args) => {
    const source$ = fn(hash, ...args);
    return new import_rxjs12.Observable((observer) => {
      let sourceSub = null;
      let isSubscribed = false;
      const performSourceSub = () => {
        if (isSubscribed) return;
        isSubscribed = true;
        sourceSub = source$.subscribe({
          next: (v) => observer.next(v),
          error: (e) => observer.error(e),
          complete: () => observer.complete()
        });
        sourceSub.add(() => {
          isSubscribed = false;
          sourceSub = null;
        });
      };
      let isRecovering = false;
      const blockSub = blocks$.subscribe({
        next: (v) => {
          const block = v.blocks.get(hash);
          if (!block) {
            if (isRecovering) {
              observer.error(new BlockNotPinnedError());
            }
          } else if (block.recovering) {
            sourceSub?.unsubscribe();
          } else {
            performSourceSub();
          }
          isRecovering = v.recovering;
        },
        error: (e) => observer.error(e)
      });
      return () => {
        blockSub.unsubscribe();
        sourceSub?.unsubscribe();
      };
    });
  };
}

// src/chainHead/enhancers/operationInaccessibleRecovery.ts
var import_substrate_client3 = require("@polkadot-api/substrate-client");
var import_rxjs13 = require("rxjs");
var operable = (source$) => {
  const result = source$.pipe(
    (0, import_rxjs13.catchError)(
      (e) => e instanceof import_substrate_client3.OperationInaccessibleError ? (0, import_rxjs13.timer)(750).pipe((0, import_rxjs13.concatMap)(() => result)) : (0, import_rxjs13.throwError)(() => e)
    )
  );
  return result;
};
var withOperationInaccessibleRecovery = (fn) => (...args) => operable(fn(...args));

// src/chainHead/storage-queries.ts
var import_rxjs14 = require("rxjs");
var getRecoveralStorage$ = (getFollower, withRecovery) => {
  const recoveralStorage$ = (hash, queries, childTrie, isHighPriority) => new import_rxjs14.Observable(
    (observer) => getFollower().storageSubscription(
      hash,
      queries,
      childTrie ?? null,
      (items) => {
        observer.next(items);
      },
      (error) => {
        observer.error(error);
      },
      () => {
        observer.complete();
      },
      (nDiscarded) => {
        if (nDiscarded === 0) return;
        observer.next(
          recoveralStorage$(
            hash,
            queries.slice(-nDiscarded),
            childTrie,
            true
          )
        );
      }
    )
  ).pipe((0, import_rxjs14.mergeAll)(), withRecovery(isHighPriority));
  return recoveralStorage$;
};

// src/chainHead/track-tx.ts
var import_rxjs15 = require("rxjs");
var getTrackTx = (blocks$, getBody, getIsValid, getEvents) => {
  const whileBlockPresent = (hash) => (0, import_rxjs15.takeUntil)(blocks$.pipe((0, import_rxjs15.filter)(({ blocks }) => !blocks.has(hash))));
  const analyzeBlock = (hash, tx, alreadyPresent) => {
    if (alreadyPresent)
      return (0, import_rxjs15.of)({ hash, found: { type: false, isValid: true } });
    const whilePresent = whileBlockPresent(hash);
    return getBody(hash).pipe(
      (0, import_rxjs15.mergeMap)((txs) => {
        const index = txs.indexOf(tx);
        return index > -1 ? whilePresent(getEvents(hash)).pipe(
          (0, import_rxjs15.map)((events) => ({
            hash,
            found: {
              type: true,
              index,
              events
            }
          }))
        ) : getIsValid(hash, tx).pipe(
          (0, import_rxjs15.map)((isValid) => ({
            hash,
            found: { type: false, isValid }
          }))
        );
      }),
      whilePresent
    );
  };
  const findInBranch = (hash, tx, alreadyPresent) => analyzeBlock(hash, tx, alreadyPresent.has(hash)).pipe(
    (0, import_rxjs15.mergeMap)((analyzed) => {
      const { found } = analyzed;
      return found.type || !found.isValid ? (0, import_rxjs15.of)(analyzed) : blocks$.pipe(
        whileBlockPresent(hash),
        (0, import_rxjs15.mergeMap)((x) => x.blocks.get(hash).children),
        (0, import_rxjs15.distinct)(),
        (0, import_rxjs15.mergeMap)((hash2) => findInBranch(hash2, tx, alreadyPresent))
      );
    })
  );
  return (tx) => blocks$.pipe(
    (0, import_rxjs15.take)(1),
    (0, import_rxjs15.mergeMap)((x) => findInBranch(x.finalized, tx, new Set(x.blocks.keys())))
  );
};

// src/chainHead/validate-tx.ts
var import_rxjs16 = require("rxjs");
var import_utils3 = require("@polkadot-api/utils");
var external = new Uint8Array([2]);
var getValidateTxArgs = (tx, hash) => (0, import_utils3.toHex)((0, import_utils3.mergeUint8)(external, (0, import_utils3.fromHex)(tx), (0, import_utils3.fromHex)(hash)));
var getValidateTx = (call$) => (blockHash, tx) => call$(
  blockHash,
  "TaggedTransactionQueue_validate_transaction",
  getValidateTxArgs(tx, blockHash)
).pipe((0, import_rxjs16.map)((x) => x.startsWith("0x00")));

// src/chainHead/chainHead.ts
var toBlockInfo = ({ hash, number, parent }) => ({
  hash,
  number,
  parent
});
var getChainHead$ = (chainHead) => {
  const { getFollower, unfollow, follow$ } = getFollow$(chainHead);
  const lazyFollower = withLazyFollower(getFollower);
  const { withRecovery, withRecoveryFn } = getWithRecovery();
  const blockUsage$ = new import_rxjs17.Subject();
  const withRefcount = (fn) => (hash, ...args) => new import_rxjs17.Observable((observer) => {
    blockUsage$.next({ type: "blockUsage", value: { type: "hold", hash } });
    const subscription = fn(hash, ...args).subscribe(observer);
    return () => {
      setTimeout(() => {
        blockUsage$.next({
          type: "blockUsage",
          value: { type: "release", hash }
        });
      }, 0);
      subscription.unsubscribe();
    };
  });
  const withInMemory = (fn) => (hash, ...args) => new import_rxjs17.Observable((observer) => {
    let isPresent = false;
    pinnedBlocks$.pipe((0, import_rxjs17.take)(1)).subscribe((blocks) => {
      const block = blocks.blocks.get(hash);
      isPresent = !!block && !block.unpinned;
    });
    return isPresent ? fn(hash, ...args).subscribe(observer) : observer.error(new BlockNotPinnedError());
  });
  const getHeader = (hash) => getFollower().header(hash).then(import_substrate_bindings2.blockHeader.dec);
  const unpin = (hashes) => getFollower().unpin(hashes).catch((e) => {
    if (e instanceof import_substrate_client4.DisjointError) return;
    throw e;
  });
  const commonEnhancer = (fn) => {
    const canonicalChain = (_fn) => withEnsureCanonicalChain(pinnedBlocks$, follow$, _fn);
    return withInMemory(
      withRefcount(
        canonicalChain(
          withStopRecovery(
            pinnedBlocks$,
            withOperationInaccessibleRecovery(
              withRecoveryFn(fromAbortControllerFn(fn))
            )
          )
        )
      )
    );
  };
  const withCanonicalChain = (fn, withCanonicalChain2 = true) => (hash, ...args) => fn(hash, withCanonicalChain2, ...args);
  const _call$ = withOperationInaccessibleRecovery(
    withRecoveryFn(fromAbortControllerFn(lazyFollower("call")))
  );
  const cache = /* @__PURE__ */ new Map();
  const pinnedBlocks$ = getPinnedBlocks$(
    follow$,
    getHeader,
    withRefcount(_call$),
    blockUsage$,
    (blocks) => {
      unpin(blocks);
      blocks.forEach((hash) => {
        cache.delete(hash);
      });
    }
  );
  const getRuntimeContext$ = withRefcount(
    (hash) => pinnedBlocks$.pipe(
      (0, import_rxjs17.take)(1),
      (0, import_rxjs17.mergeMap)(
        (pinned) => pinned.runtimes[pinned.blocks.get(hash).runtime].runtime
      )
    )
  );
  const withRuntime = (mapper) => (source$) => source$.pipe(
    concatMapEager(
      (x) => getRuntimeContext$(mapper(x)).pipe((0, import_rxjs17.map)((runtime) => [x, runtime]))
    )
  );
  const upsertCachedStream = (hash, key, stream) => {
    const hashCache = cache.get(hash) ?? /* @__PURE__ */ new Map();
    const cached = hashCache.get(key);
    if (cached) return cached;
    cache.set(hash, hashCache);
    const connector = new import_rxjs17.ReplaySubject();
    const result = stream.pipe(
      (0, import_rxjs17.share)({
        connector: () => connector
      }),
      (0, import_rxjs17.tap)({
        complete() {
          hashCache.set(key, connector);
        }
      })
    );
    hashCache.set(key, result);
    return result;
  };
  const finalized$ = pinnedBlocks$.pipe(
    (0, import_rxjs17.distinctUntilChanged)((a, b) => a.finalized === b.finalized),
    (0, import_rxjs17.map)((pinned) => toBlockInfo(pinned.blocks.get(pinned.finalized))),
    shareLatest
  );
  const best$ = pinnedBlocks$.pipe(
    (0, import_rxjs17.distinctUntilChanged)((a, b) => a.best === b.best),
    (0, import_rxjs17.map)((pinned) => toBlockInfo(pinned.blocks.get(pinned.best))),
    shareLatest
  );
  const bestBlocks$ = pinnedBlocks$.pipe(
    (0, import_rxjs17.distinctUntilChanged)(
      (prev, current) => prev.finalized === current.finalized && prev.best === current.best
    ),
    (0, import_rxjs17.scan)((acc, pinned) => {
      const getBlockInfo = (hash) => acc.get(hash) || toBlockInfo(pinned.blocks.get(hash));
      const best = getBlockInfo(pinned.best);
      const finalized = getBlockInfo(pinned.finalized);
      const len = best.number - finalized.number + 1;
      const result = new Array(len);
      for (let i = 0, hash = best.hash; i < len; i++) {
        result[i] = getBlockInfo(hash);
        hash = result[i].parent;
      }
      return new Map(result.map((b) => [b.hash, b]));
    }, /* @__PURE__ */ new Map()),
    (0, import_rxjs17.map)((x) => [...x.values()]),
    shareLatest
  );
  const runtime$ = pinnedBlocks$.pipe(
    (0, import_rxjs17.distinctUntilChanged)((a, b) => a.finalizedRuntime === b.finalizedRuntime),
    (0, import_rxjs17.switchMap)(
      ({ finalizedRuntime: { runtime } }) => runtime.pipe(withDefaultValue(null))
    ),
    shareLatest
  );
  const metadata$ = runtime$.pipe((0, import_rxjs17.map)((x) => x?.metadata ?? null));
  const withOptionalHash$ = getWithOptionalhash$(
    finalized$.pipe((0, import_rxjs17.map)((b) => b.hash)),
    best$.pipe((0, import_rxjs17.map)((b) => b.hash))
  );
  const _body$ = commonEnhancer(lazyFollower("body"));
  const body$ = (hash) => upsertCachedStream(hash, "body", _body$(hash, true));
  const _storage$ = commonEnhancer(lazyFollower("storage"));
  const storage$ = withOptionalHash$(
    (hash, withCanonicalChain2, type, keyMapper, childTrie = null, mapper) => pinnedBlocks$.pipe(
      (0, import_rxjs17.take)(1),
      (0, import_rxjs17.mergeMap)(
        (pinned) => pinned.runtimes[pinned.blocks.get(hash).runtime].runtime
      ),
      (0, import_rxjs17.mergeMap)((ctx) => {
        const key = keyMapper(ctx);
        const unMapped$ = upsertCachedStream(
          hash,
          `storage-${type}-${key}-${childTrie ?? ""}`,
          _storage$(hash, withCanonicalChain2, type, key, childTrie)
        );
        return mapper ? upsertCachedStream(
          hash,
          `storage-${type}-${key}-${childTrie ?? ""}-dec`,
          unMapped$.pipe((0, import_rxjs17.map)((x) => mapper(x, ctx)))
        ) : unMapped$;
      })
    )
  );
  const recoveralStorage$ = getRecoveralStorage$(getFollower, withRecovery);
  const storageQueries$ = withOperationInaccessibleRecovery(
    withOptionalHash$(
      withRefcount(
        withStopRecovery(
          pinnedBlocks$,
          (hash, queries, childTrie) => recoveralStorage$(hash, queries, childTrie ?? null, false)
        )
      )
    )
  );
  const header$ = withOptionalHash$(
    withRefcount(
      withStopRecovery(
        pinnedBlocks$,
        (hash) => (0, import_rxjs17.defer)(() => getHeader(hash))
      )
    )
  );
  (0, import_rxjs17.merge)(runtime$, bestBlocks$).subscribe();
  const eventsAt$ = (hash, canonical = false) => storage$(
    hash,
    canonical,
    "value",
    (ctx) => ctx.events.key,
    null,
    (x, ctx) => ctx.events.dec(x)
  );
  const __call$ = commonEnhancer(lazyFollower("call"));
  const call$ = withOptionalHash$(
    (hash, canonical, fn, args) => upsertCachedStream(
      hash,
      `call-${fn}-${args}`,
      __call$(hash, canonical, fn, args)
    )
  );
  const validateTx$ = getValidateTx(withCanonicalChain(call$, false));
  const innerBody$ = (hash) => upsertCachedStream(hash, "body", _body$(hash, false));
  const trackTx$ = getTrackTx(pinnedBlocks$, innerBody$, validateTx$, eventsAt$);
  const trackTxWithoutEvents$ = getTrackTx(
    pinnedBlocks$,
    innerBody$,
    validateTx$,
    () => (0, import_rxjs17.of)()
  );
  return {
    follow$,
    finalized$,
    best$,
    bestBlocks$,
    runtime$,
    metadata$,
    header$,
    body$,
    call$: withCanonicalChain(call$),
    storage$: withCanonicalChain(storage$),
    storageQueries$,
    eventsAt$: withCanonicalChain(eventsAt$),
    trackTx$,
    trackTxWithoutEvents$,
    validateTx$,
    pinnedBlocks$,
    withRuntime,
    getRuntimeContext$: withOptionalHash$(getRuntimeContext$),
    unfollow
  };
};

// src/tx.ts
var import_rxjs18 = require("rxjs");
var tx_default = (baseTransaction) => (transaction) => new import_rxjs18.Observable(
  (observer) => baseTransaction(transaction, (e) => {
    observer.error(e);
  })
);

// src/getObservableClient.ts
var getObservableClient = ({
  chainHead,
  transaction,
  destroy
}) => ({
  chainHead$: () => getChainHead$(chainHead),
  broadcastTx$: tx_default(transaction),
  destroy
});
//# sourceMappingURL=index.js.map

Выполнить команду


Для локальной разработки. Не используйте в интернете!