@secondlayer/stacks 6.2.1 → 6.3.0

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.
@@ -1591,21 +1591,22 @@ interface AbiContract {
1591
1591
  defined_traits?: ReadonlyArray<AbiTraitDefinition>;
1592
1592
  }
1593
1593
  /**
1594
- * `<contract>::<asset-name>` — the shape a fungible/non-fungible asset filter
1595
- * takes, expressed so the compiler can check it.
1594
+ * A fungible or non-fungible asset identifier: `<contract>::<asset-name>`.
1595
+ *
1596
+ * This is the shape an asset filter takes, expressed so the compiler can check it.
1596
1597
  *
1597
1598
  * The most common mistake in this API is passing a CONTRACT ID
1598
1599
  * (`SP….sbtc-token`) where an asset identifier (`SP….sbtc-token::sbtc-token`)
1599
1600
  * belongs, and the failure mode is a query that quietly returns zero rows. The
1600
1601
  * two differ structurally by `::`, so a template-literal type catches it at the
1601
- * call site — no brand, no cast, literals just work.
1602
+ * call site. No brand, no cast, literals just work.
1602
1603
  *
1603
1604
  * A value that is only known at runtime (config, env) is not narrow enough on
1604
1605
  * purpose; run it through {@link assetId} once, which validates and narrows.
1605
1606
  *
1606
- * Wildcard patterns (Webhooks/Subgraphs-only) are admitted by the second arm — they
1607
- * are legitimately not full identifiers (`SPB.*`), and the runtime validator
1608
- * short-circuits on them for the same reason.
1607
+ * Wildcard patterns (Webhooks/Subgraphs-only) are admitted by the second arm.
1608
+ * They are legitimately not full identifiers (`SPB.*`), and the runtime
1609
+ * validator short-circuits on them for the same reason.
1609
1610
  */
1610
1611
  type AssetIdentifier = `${string}::${string}` | `${string}*${string}`;
1611
1612
  /** Scalar print field types (structural mirror of the subgraphs `ColumnType`). */
@@ -1783,6 +1784,7 @@ interface SbtcWithdrawalSweptConfirmedSpec {
1783
1784
  sweepTxid?: string;
1784
1785
  }
1785
1786
  type ChainEventFilterSpec = StxTransferSpec | StxMintSpec | StxBurnSpec | StxLockSpec | FtTransferSpec | FtMintSpec | FtBurnSpec | NftTransferSpec | NftMintSpec | NftBurnSpec | ContractCallSpec | ContractDeploySpec | NestedContractCallSpec | VarSetSpec | MapSetSpec | MapInsertSpec | MapDeleteSpec | PrintEventSpec | SbtcDepositSpec | SbtcWithdrawalCreateSpec | SbtcWithdrawalAcceptSpec | SbtcWithdrawalRejectSpec | SbtcWithdrawalSweptConfirmedSpec;
1787
+ /** The filter spec for one chain event type. */
1786
1788
  type SpecFor<T extends ChainEventFilterType> = Extract<ChainEventFilterSpec, {
1787
1789
  type: T
1788
1790
  }>;
@@ -1858,10 +1860,11 @@ type ProjectionsFor<
1858
1860
  toSubgraphSource(): S
1859
1861
  } : {});
1860
1862
  /**
1861
- * A canonical chain-event filter: the spec fields plus the projections its
1862
- * member supports. Write the filter once; project it to a query
1863
- * (`toIndexParams`), a stream (`toStreamsParams`), a webhook trigger
1864
- * (`toChainTrigger`), or a subgraph source (`toSubgraphSource`).
1863
+ * A chain-event filter: the spec fields plus its member's projections.
1864
+ *
1865
+ * Write the filter once; project it to a query (`toIndexParams`), a stream
1866
+ * (`toStreamsParams`), a webhook trigger (`toChainTrigger`), or a subgraph
1867
+ * source (`toSubgraphSource`).
1865
1868
  */
1866
1869
  type ChainEventFilter<
1867
1870
  T extends ChainEventFilterType = ChainEventFilterType,
@@ -1869,6 +1872,7 @@ type ChainEventFilter<
1869
1872
  type: T
1870
1873
  } = SpecFor<T>
1871
1874
  > = S & ProjectionsFor<T, S>;
1875
+ /** The fields a filter factory takes for one event type, without `type`. */
1872
1876
  type Fields<T extends ChainEventFilterType> = Omit<SpecFor<T>, "type">;
1873
1877
  /** The `on.*` namespace, annotated explicitly — bunup's dts emitter needs an
1874
1878
  * annotation on exported values (an inferred object of generic factories
@@ -1591,21 +1591,22 @@ interface AbiContract {
1591
1591
  defined_traits?: ReadonlyArray<AbiTraitDefinition>;
1592
1592
  }
1593
1593
  /**
1594
- * `<contract>::<asset-name>` — the shape a fungible/non-fungible asset filter
1595
- * takes, expressed so the compiler can check it.
1594
+ * A fungible or non-fungible asset identifier: `<contract>::<asset-name>`.
1595
+ *
1596
+ * This is the shape an asset filter takes, expressed so the compiler can check it.
1596
1597
  *
1597
1598
  * The most common mistake in this API is passing a CONTRACT ID
1598
1599
  * (`SP….sbtc-token`) where an asset identifier (`SP….sbtc-token::sbtc-token`)
1599
1600
  * belongs, and the failure mode is a query that quietly returns zero rows. The
1600
1601
  * two differ structurally by `::`, so a template-literal type catches it at the
1601
- * call site — no brand, no cast, literals just work.
1602
+ * call site. No brand, no cast, literals just work.
1602
1603
  *
1603
1604
  * A value that is only known at runtime (config, env) is not narrow enough on
1604
1605
  * purpose; run it through {@link assetId} once, which validates and narrows.
1605
1606
  *
1606
- * Wildcard patterns (Webhooks/Subgraphs-only) are admitted by the second arm — they
1607
- * are legitimately not full identifiers (`SPB.*`), and the runtime validator
1608
- * short-circuits on them for the same reason.
1607
+ * Wildcard patterns (Webhooks/Subgraphs-only) are admitted by the second arm.
1608
+ * They are legitimately not full identifiers (`SPB.*`), and the runtime
1609
+ * validator short-circuits on them for the same reason.
1609
1610
  */
1610
1611
  type AssetIdentifier = `${string}::${string}` | `${string}*${string}`;
1611
1612
  /** Scalar print field types (structural mirror of the subgraphs `ColumnType`). */
@@ -1783,6 +1784,7 @@ interface SbtcWithdrawalSweptConfirmedSpec {
1783
1784
  sweepTxid?: string;
1784
1785
  }
1785
1786
  type ChainEventFilterSpec = StxTransferSpec | StxMintSpec | StxBurnSpec | StxLockSpec | FtTransferSpec | FtMintSpec | FtBurnSpec | NftTransferSpec | NftMintSpec | NftBurnSpec | ContractCallSpec | ContractDeploySpec | NestedContractCallSpec | VarSetSpec | MapSetSpec | MapInsertSpec | MapDeleteSpec | PrintEventSpec | SbtcDepositSpec | SbtcWithdrawalCreateSpec | SbtcWithdrawalAcceptSpec | SbtcWithdrawalRejectSpec | SbtcWithdrawalSweptConfirmedSpec;
1787
+ /** The filter spec for one chain event type. */
1786
1788
  type SpecFor<T extends ChainEventFilterType> = Extract<ChainEventFilterSpec, {
1787
1789
  type: T
1788
1790
  }>;
@@ -1858,10 +1860,11 @@ type ProjectionsFor<
1858
1860
  toSubgraphSource(): S
1859
1861
  } : {});
1860
1862
  /**
1861
- * A canonical chain-event filter: the spec fields plus the projections its
1862
- * member supports. Write the filter once; project it to a query
1863
- * (`toIndexParams`), a stream (`toStreamsParams`), a webhook trigger
1864
- * (`toChainTrigger`), or a subgraph source (`toSubgraphSource`).
1863
+ * A chain-event filter: the spec fields plus its member's projections.
1864
+ *
1865
+ * Write the filter once; project it to a query (`toIndexParams`), a stream
1866
+ * (`toStreamsParams`), a webhook trigger (`toChainTrigger`), or a subgraph
1867
+ * source (`toSubgraphSource`).
1865
1868
  */
1866
1869
  type ChainEventFilter<
1867
1870
  T extends ChainEventFilterType = ChainEventFilterType,
@@ -1869,6 +1872,7 @@ type ChainEventFilter<
1869
1872
  type: T
1870
1873
  } = SpecFor<T>
1871
1874
  > = S & ProjectionsFor<T, S>;
1875
+ /** The fields a filter factory takes for one event type, without `type`. */
1872
1876
  type Fields<T extends ChainEventFilterType> = Omit<SpecFor<T>, "type">;
1873
1877
  /** The `on.*` namespace, annotated explicitly — bunup's dts emitter needs an
1874
1878
  * annotation on exported values (an inferred object of generic factories
@@ -5452,6 +5452,14 @@ function rootFromProof(leafInternal, proof) {
5452
5452
  }
5453
5453
 
5454
5454
  // src/bitcoin/proof.ts
5455
+ class BitcoinSourceError extends Error {
5456
+ code;
5457
+ name = "BitcoinSourceError";
5458
+ constructor(code, message) {
5459
+ super(message);
5460
+ this.code = code;
5461
+ }
5462
+ }
5455
5463
  function normalizeTxid2(txid) {
5456
5464
  return without0x(txid).toLowerCase();
5457
5465
  }
@@ -5528,22 +5536,32 @@ function bitcoinRpcSource(config) {
5528
5536
  const basic = typeof config.auth === "string" ? config.auth : btoa(`${config.auth.username}:${config.auth.password}`);
5529
5537
  headers.authorization = `Basic ${basic}`;
5530
5538
  }
5531
- const res = await doFetch(config.url, {
5532
- method: "POST",
5533
- headers,
5534
- body: JSON.stringify({
5535
- jsonrpc: "1.0",
5536
- id: "secondlayer",
5537
- method,
5538
- params: rpcParams
5539
- })
5540
- });
5541
- if (!res.ok) {
5542
- throw new Error(`bitcoin rpc ${method} failed: HTTP ${res.status}`);
5539
+ let res;
5540
+ try {
5541
+ res = await doFetch(config.url, {
5542
+ method: "POST",
5543
+ headers,
5544
+ body: JSON.stringify({
5545
+ jsonrpc: "1.0",
5546
+ id: "secondlayer",
5547
+ method,
5548
+ params: rpcParams
5549
+ })
5550
+ });
5551
+ } catch (error) {
5552
+ throw new BitcoinSourceError("unavailable", `bitcoin rpc ${method} failed: ${error instanceof Error ? error.message : "network error"}`);
5553
+ }
5554
+ let json;
5555
+ try {
5556
+ json = await res.json();
5557
+ } catch {
5558
+ throw new BitcoinSourceError("unavailable", `bitcoin rpc ${method} failed: HTTP ${res.status}`);
5543
5559
  }
5544
- const json = await res.json();
5545
5560
  if (json.error) {
5546
- throw new Error(`bitcoin rpc ${method} error: ${json.error.message}`);
5561
+ throw new BitcoinSourceError(json.error.code === -5 ? "not-found" : "unavailable", `bitcoin rpc ${method} error: ${json.error.message}`);
5562
+ }
5563
+ if (!res.ok) {
5564
+ throw new BitcoinSourceError("unavailable", `bitcoin rpc ${method} failed: HTTP ${res.status}`);
5547
5565
  }
5548
5566
  return json.result;
5549
5567
  }
@@ -5557,7 +5575,7 @@ function bitcoinRpcSource(config) {
5557
5575
  true
5558
5576
  ]);
5559
5577
  if (!tx.blockhash) {
5560
- throw new Error(`tx ${txid} is not in a block (node needs -txindex, or the tx is unconfirmed)`);
5578
+ throw new BitcoinSourceError("unconfirmed", `tx ${txid} is not in a block (node needs -txindex, or the tx is unconfirmed)`);
5561
5579
  }
5562
5580
  const block = await rpc("getblock", [
5563
5581
  tx.blockhash,
@@ -5578,9 +5596,14 @@ function esploraSource(config) {
5578
5596
  const doFetch = config.fetch ?? fetch;
5579
5597
  const base = config.url.replace(/\/+$/, "");
5580
5598
  async function get(path) {
5581
- const res = await doFetch(`${base}${path}`);
5599
+ let res;
5600
+ try {
5601
+ res = await doFetch(`${base}${path}`);
5602
+ } catch (error) {
5603
+ throw new BitcoinSourceError("unavailable", `esplora GET ${path} failed: ${error instanceof Error ? error.message : "network error"}`);
5604
+ }
5582
5605
  if (!res.ok) {
5583
- throw new Error(`esplora GET ${path} failed: HTTP ${res.status}`);
5606
+ throw new BitcoinSourceError(res.status === 404 ? "not-found" : "unavailable", `esplora GET ${path} failed: HTTP ${res.status}`);
5584
5607
  }
5585
5608
  return res;
5586
5609
  }
@@ -5591,7 +5614,7 @@ function esploraSource(config) {
5591
5614
  async getBlockForTx(txid) {
5592
5615
  const status = await (await get(`/tx/${txid}`)).json();
5593
5616
  if (!status.status.confirmed) {
5594
- throw new Error(`tx ${txid} is unconfirmed`);
5617
+ throw new BitcoinSourceError("unconfirmed", `tx ${txid} is unconfirmed`);
5595
5618
  }
5596
5619
  const blockHashHex = status.status.block_hash;
5597
5620
  const header = (await (await get(`/block/${blockHashHex}/header`)).text()).trim();
@@ -6137,5 +6160,5 @@ function parseSignerCalldata(calldata) {
6137
6160
  };
6138
6161
  }
6139
6162
 
6140
- //# debugId=5713B30E41D0F0B964756E2164756E21
6163
+ //# debugId=B8DD8E4772B8284D64756E2164756E21
6141
6164
  //# sourceMappingURL=index.cjs.map