@arkade-os/sdk 0.3.0-alpha.0 → 0.3.0-alpha.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.
Files changed (73) hide show
  1. package/dist/cjs/arknote/index.js +4 -4
  2. package/dist/cjs/bip322/index.js +9 -7
  3. package/dist/cjs/forfeit.js +2 -2
  4. package/dist/cjs/identity/singleKey.js +10 -7
  5. package/dist/cjs/index.js +2 -2
  6. package/dist/cjs/musig2/keys.js +1 -1
  7. package/dist/cjs/musig2/nonces.js +1 -1
  8. package/dist/cjs/musig2/sign.js +1 -1
  9. package/dist/cjs/networks.js +6 -6
  10. package/dist/cjs/providers/ark.js +53 -71
  11. package/dist/cjs/providers/indexer.js +45 -51
  12. package/dist/cjs/providers/utils.js +60 -0
  13. package/dist/cjs/repositories/walletRepository.js +34 -4
  14. package/dist/cjs/script/address.js +3 -3
  15. package/dist/cjs/script/base.js +7 -7
  16. package/dist/cjs/script/tapscript.js +29 -23
  17. package/dist/cjs/script/vhtlc.js +2 -2
  18. package/dist/cjs/tree/signingSession.js +11 -10
  19. package/dist/cjs/tree/txTree.js +9 -9
  20. package/dist/cjs/tree/validation.js +6 -6
  21. package/dist/cjs/utils/arkTransaction.js +5 -5
  22. package/dist/cjs/utils/unknownFields.js +5 -5
  23. package/dist/cjs/wallet/onchain.js +5 -5
  24. package/dist/cjs/wallet/unroll.js +6 -6
  25. package/dist/cjs/wallet/wallet.js +21 -22
  26. package/dist/esm/arknote/index.js +2 -2
  27. package/dist/esm/bip322/index.js +3 -1
  28. package/dist/esm/forfeit.js +1 -1
  29. package/dist/esm/identity/singleKey.js +5 -2
  30. package/dist/esm/index.js +1 -1
  31. package/dist/esm/musig2/keys.js +1 -1
  32. package/dist/esm/musig2/nonces.js +1 -1
  33. package/dist/esm/musig2/sign.js +1 -1
  34. package/dist/esm/networks.js +1 -1
  35. package/dist/esm/providers/ark.js +53 -71
  36. package/dist/esm/providers/indexer.js +45 -51
  37. package/dist/esm/providers/utils.js +57 -0
  38. package/dist/esm/repositories/walletRepository.js +34 -4
  39. package/dist/esm/script/address.js +1 -1
  40. package/dist/esm/script/base.js +3 -3
  41. package/dist/esm/script/tapscript.js +10 -4
  42. package/dist/esm/script/vhtlc.js +1 -1
  43. package/dist/esm/tree/signingSession.js +6 -5
  44. package/dist/esm/tree/txTree.js +5 -5
  45. package/dist/esm/tree/validation.js +3 -3
  46. package/dist/esm/utils/arkTransaction.js +2 -2
  47. package/dist/esm/utils/unknownFields.js +1 -1
  48. package/dist/esm/wallet/onchain.js +2 -2
  49. package/dist/esm/wallet/unroll.js +2 -2
  50. package/dist/esm/wallet/wallet.js +9 -10
  51. package/dist/types/arknote/index.d.ts +1 -1
  52. package/dist/types/bip322/index.d.ts +2 -2
  53. package/dist/types/forfeit.d.ts +1 -1
  54. package/dist/types/identity/index.d.ts +4 -3
  55. package/dist/types/identity/singleKey.d.ts +2 -1
  56. package/dist/types/index.d.ts +1 -1
  57. package/dist/types/providers/ark.d.ts +1 -0
  58. package/dist/types/providers/utils.d.ts +1 -0
  59. package/dist/types/script/address.d.ts +1 -1
  60. package/dist/types/script/base.d.ts +1 -1
  61. package/dist/types/script/default.d.ts +1 -1
  62. package/dist/types/script/tapscript.d.ts +1 -1
  63. package/dist/types/script/vhtlc.d.ts +1 -1
  64. package/dist/types/tree/txTree.d.ts +3 -3
  65. package/dist/types/tree/validation.d.ts +1 -1
  66. package/dist/types/utils/anchor.d.ts +1 -1
  67. package/dist/types/utils/arkTransaction.d.ts +3 -3
  68. package/dist/types/utils/unknownFields.d.ts +1 -1
  69. package/dist/types/wallet/index.d.ts +1 -1
  70. package/dist/types/wallet/onchain.d.ts +2 -2
  71. package/dist/types/wallet/unroll.d.ts +1 -1
  72. package/dist/types/wallet/wallet.d.ts +1 -1
  73. package/package.json +3 -2
@@ -2,10 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OnchainWallet = void 0;
4
4
  exports.selectCoins = selectCoins;
5
- const payment_1 = require("@scure/btc-signer/payment");
5
+ const payment_js_1 = require("@scure/btc-signer/payment.js");
6
6
  const networks_1 = require("../networks");
7
7
  const onchain_1 = require("../providers/onchain");
8
- const btc_signer_1 = require("@scure/btc-signer");
8
+ const transaction_js_1 = require("@scure/btc-signer/transaction.js");
9
9
  const anchor_1 = require("../utils/anchor");
10
10
  const txSizeEstimator_1 = require("../utils/txSizeEstimator");
11
11
  /**
@@ -39,7 +39,7 @@ class OnchainWallet {
39
39
  }
40
40
  const network = (0, networks_1.getNetwork)(networkName);
41
41
  const onchainProvider = provider || new onchain_1.EsploraProvider(onchain_1.ESPLORA_URL[networkName]);
42
- const onchainP2TR = (0, payment_1.p2tr)(pubkey, undefined, network);
42
+ const onchainP2TR = (0, payment_js_1.p2tr)(pubkey, undefined, network);
43
43
  return new OnchainWallet(identity, network, onchainP2TR, onchainProvider);
44
44
  }
45
45
  get address() {
@@ -80,7 +80,7 @@ class OnchainWallet {
80
80
  // Select coins
81
81
  const selected = selectCoins(coins, totalNeeded);
82
82
  // Create transaction
83
- let tx = new btc_signer_1.Transaction();
83
+ let tx = new transaction_js_1.Transaction();
84
84
  // Add inputs
85
85
  for (const input of selected.inputs) {
86
86
  tx.addInput({
@@ -108,7 +108,7 @@ class OnchainWallet {
108
108
  }
109
109
  async bumpP2A(parent) {
110
110
  const parentVsize = parent.vsize;
111
- let child = new btc_signer_1.Transaction({
111
+ let child = new transaction_js_1.Transaction({
112
112
  allowUnknownInputs: true,
113
113
  allowLegacyWitnessUtxo: true,
114
114
  version: 3,
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Unroll = void 0;
4
- const btc_signer_1 = require("@scure/btc-signer");
4
+ const transaction_js_1 = require("@scure/btc-signer/transaction.js");
5
5
  const indexer_1 = require("../providers/indexer");
6
6
  const base_1 = require("@scure/base");
7
7
  const base_2 = require("../script/base");
8
- const psbt_1 = require("@scure/btc-signer/psbt");
8
+ const psbt_js_1 = require("@scure/btc-signer/psbt.js");
9
9
  const txSizeEstimator_1 = require("../utils/txSizeEstimator");
10
10
  const wallet_1 = require("./wallet");
11
11
  var Unroll;
@@ -106,7 +106,7 @@ var Unroll;
106
106
  if (virtualTxs.txs.length === 0) {
107
107
  throw new Error(`Tx ${nextTxToBroadcast.txid} not found`);
108
108
  }
109
- const tx = btc_signer_1.Transaction.fromPSBT(base_1.base64.decode(virtualTxs.txs[0]), {
109
+ const tx = transaction_js_1.Transaction.fromPSBT(base_1.base64.decode(virtualTxs.txs[0]), {
110
110
  allowUnknownInputs: true,
111
111
  });
112
112
  // finalize the tree transaction
@@ -197,11 +197,11 @@ var Unroll;
197
197
  amount: BigInt(vtxo.value),
198
198
  script: base_2.VtxoScript.decode(vtxo.tapTree).pkScript,
199
199
  },
200
- sighashType: btc_signer_1.SigHash.DEFAULT,
200
+ sighashType: transaction_js_1.SigHash.DEFAULT,
201
201
  });
202
- txWeightEstimator.addTapscriptInput(64, spendingLeaf[1].length, psbt_1.TaprootControlBlock.encode(spendingLeaf[0]).length);
202
+ txWeightEstimator.addTapscriptInput(64, spendingLeaf[1].length, psbt_js_1.TaprootControlBlock.encode(spendingLeaf[0]).length);
203
203
  }
204
- const tx = new btc_signer_1.Transaction({ allowUnknownInputs: true, version: 2 });
204
+ const tx = new transaction_js_1.Transaction({ allowUnknownInputs: true, version: 2 });
205
205
  for (const input of inputs) {
206
206
  tx.addInput(input);
207
207
  }
@@ -37,9 +37,9 @@ exports.Wallet = void 0;
37
37
  exports.waitForIncomingFunds = waitForIncomingFunds;
38
38
  const base_1 = require("@scure/base");
39
39
  const bip68 = __importStar(require("bip68"));
40
- const payment_1 = require("@scure/btc-signer/payment");
41
- const btc_signer_1 = require("@scure/btc-signer");
42
- const psbt_1 = require("@scure/btc-signer/psbt");
40
+ const payment_js_1 = require("@scure/btc-signer/payment.js");
41
+ const transaction_js_1 = require("@scure/btc-signer/transaction.js");
42
+ const psbt_js_1 = require("@scure/btc-signer/psbt.js");
43
43
  const transactionHistory_1 = require("../utils/transactionHistory");
44
44
  const address_1 = require("../script/address");
45
45
  const default_1 = require("../script/default");
@@ -49,7 +49,7 @@ const ark_1 = require("../providers/ark");
49
49
  const forfeit_1 = require("../forfeit");
50
50
  const validation_1 = require("../tree/validation");
51
51
  const _1 = require(".");
52
- const utils_1 = require("@scure/btc-signer/utils");
52
+ const utils_js_1 = require("@scure/btc-signer/utils.js");
53
53
  const base_2 = require("../script/base");
54
54
  const tapscript_1 = require("../script/tapscript");
55
55
  const arkTransaction_1 = require("../utils/arkTransaction");
@@ -135,14 +135,12 @@ class Wallet {
135
135
  // Save tapscripts
136
136
  const offchainTapscript = bareVtxoTapscript;
137
137
  // the serverUnrollScript is the one used to create output scripts of the checkpoint transactions
138
- const serverUnrollScript = tapscript_1.CSVMultisigTapscript.encode({
139
- timelock: exitTimelock,
140
- pubkeys: [serverPubKey],
141
- });
138
+ const rawCheckpointExitClosure = base_1.hex.decode(info.checkpointExitClosure);
139
+ const serverUnrollScript = tapscript_1.CSVMultisigTapscript.decode(rawCheckpointExitClosure);
142
140
  // parse the server forfeit address
143
141
  // server is expecting funds to be sent to this address
144
- const forfeitAddress = (0, payment_1.Address)(network).decode(info.forfeitAddress);
145
- const forfeitOutputScript = payment_1.OutScript.encode(forfeitAddress);
142
+ const forfeitAddress = (0, payment_js_1.Address)(network).decode(info.forfeitAddress);
143
+ const forfeitOutputScript = payment_js_1.OutScript.encode(forfeitAddress);
146
144
  // Set up storage and repositories
147
145
  const storage = config.storage || new inMemory_1.InMemoryStorageAdapter();
148
146
  const walletRepository = new walletRepository_1.WalletRepositoryImpl(storage);
@@ -204,8 +202,9 @@ class Wallet {
204
202
  }
205
203
  async getVtxos(filter) {
206
204
  const address = await this.getAddress();
207
- // Try to get from cache first
208
- const cachedVtxos = await this.walletRepository.getVtxos(address);
205
+ // Try to get from cache first first (optional fast path)
206
+ // const cachedVtxos = await this.walletRepository.getVtxos(address);
207
+ // if (cachedVtxos.length) return cachedVtxos;
209
208
  // For now, always fetch fresh data from provider and update cache
210
209
  // In future, we can add cache invalidation logic based on timestamps
211
210
  const spendableVtxos = await this.getVirtualCoins(filter);
@@ -402,7 +401,7 @@ class Wallet {
402
401
  // TODO persist final virtual tx and checkpoints to repository
403
402
  // sign the checkpoints
404
403
  const finalCheckpoints = await Promise.all(signedCheckpointTxs.map(async (c) => {
405
- const tx = btc_signer_1.Transaction.fromPSBT(base_1.base64.decode(c));
404
+ const tx = transaction_js_1.Transaction.fromPSBT(base_1.base64.decode(c));
406
405
  const signedCheckpoint = await this.identity.sign(tx);
407
406
  return base_1.base64.encode(signedCheckpoint.toPSBT());
408
407
  }));
@@ -458,8 +457,8 @@ class Wallet {
458
457
  }
459
458
  catch {
460
459
  // onchain
461
- const addr = (0, payment_1.Address)(this.network).decode(output.address);
462
- script = payment_1.OutScript.encode(addr);
460
+ const addr = (0, payment_js_1.Address)(this.network).decode(output.address);
461
+ script = payment_js_1.OutScript.encode(addr);
463
462
  onchainOutputIndexes.push(index);
464
463
  }
465
464
  outputs.push({
@@ -697,7 +696,7 @@ class Wallet {
697
696
  }
698
697
  async handleBatchStartedEvent(event, intentId, serverPubKey, forfeitOutputScript) {
699
698
  const utf8IntentId = new TextEncoder().encode(intentId);
700
- const intentIdHash = (0, utils_1.sha256)(utf8IntentId);
699
+ const intentIdHash = (0, utils_js_1.sha256)(utf8IntentId);
701
700
  const intentIdHashStr = base_1.hex.encode(new Uint8Array(intentIdHash));
702
701
  let skip = true;
703
702
  // check if our intent ID hash matches any in the event
@@ -720,7 +719,7 @@ class Wallet {
720
719
  },
721
720
  pubkeys: [serverPubKey],
722
721
  }).script;
723
- const sweepTapTreeRoot = (0, payment_1.tapLeafHash)(sweepTapscript);
722
+ const sweepTapTreeRoot = (0, payment_js_1.tapLeafHash)(sweepTapscript);
724
723
  return {
725
724
  roundId: event.id,
726
725
  sweepTapTreeRoot,
@@ -731,7 +730,7 @@ class Wallet {
731
730
  // validates the vtxo tree, creates a signing session and generates the musig2 nonces
732
731
  async handleSettlementSigningEvent(event, sweepTapTreeRoot, session, vtxoGraph) {
733
732
  // validate the unsigned vtxo tree
734
- const commitmentTx = btc_signer_1.Transaction.fromPSBT(base_1.base64.decode(event.unsignedCommitmentTx));
733
+ const commitmentTx = transaction_js_1.Transaction.fromPSBT(base_1.base64.decode(event.unsignedCommitmentTx));
735
734
  (0, validation_1.validateVtxoTxGraph)(vtxoGraph, commitmentTx, sweepTapTreeRoot);
736
735
  // TODO check if our registered outputs are in the vtxo tree
737
736
  const sharedOutput = commitmentTx.getOutput(0);
@@ -750,7 +749,7 @@ class Wallet {
750
749
  // the signed forfeits transactions to submit
751
750
  const signedForfeits = [];
752
751
  const vtxos = await this.getVirtualCoins();
753
- let settlementPsbt = btc_signer_1.Transaction.fromPSBT(base_1.base64.decode(event.commitmentTx));
752
+ let settlementPsbt = transaction_js_1.Transaction.fromPSBT(base_1.base64.decode(event.commitmentTx));
754
753
  let hasBoardingUtxos = false;
755
754
  let connectorIndex = 0;
756
755
  const connectorsLeaves = connectorsGraph?.leaves() || [];
@@ -792,7 +791,7 @@ class Wallet {
792
791
  throw new Error("not enough connectors received");
793
792
  }
794
793
  const connectorLeaf = connectorsLeaves[connectorIndex];
795
- const connectorTxId = base_1.hex.encode((0, utils_1.sha256x2)(connectorLeaf.toBytes(true)).reverse());
794
+ const connectorTxId = base_1.hex.encode((0, utils_js_1.sha256x2)(connectorLeaf.toBytes(true)).reverse());
796
795
  const connectorOutput = connectorLeaf.getOutput(0);
797
796
  if (!connectorOutput) {
798
797
  throw new Error("connector output not found");
@@ -811,7 +810,7 @@ class Wallet {
811
810
  amount: BigInt(vtxo.value),
812
811
  script: base_2.VtxoScript.decode(input.tapTree).pkScript,
813
812
  },
814
- sighashType: btc_signer_1.SigHash.DEFAULT,
813
+ sighashType: transaction_js_1.SigHash.DEFAULT,
815
814
  tapLeafScript: [input.forfeitTapLeafScript],
816
815
  },
817
816
  {
@@ -917,7 +916,7 @@ function finalizeWithExtraWitnesses(inputExtraWitnesses) {
917
916
  tx.updateInput(i, {
918
917
  finalScriptWitness: [
919
918
  script,
920
- psbt_1.TaprootControlBlock.encode(cb),
919
+ psbt_js_1.TaprootControlBlock.encode(cb),
921
920
  ],
922
921
  });
923
922
  }
@@ -1,7 +1,7 @@
1
1
  import { base58, hex } from "@scure/base";
2
2
  import { VtxoScript } from '../script/base.js';
3
- import { sha256 } from "@scure/btc-signer/utils";
4
- import { Script } from "@scure/btc-signer";
3
+ import { sha256 } from "@scure/btc-signer/utils.js";
4
+ import { Script } from "@scure/btc-signer/script.js";
5
5
  /**
6
6
  * ArkNotes are special virtual coins in the Ark protocol that can be created
7
7
  * and spent without requiring any transactions. The server mints them, and they
@@ -1,4 +1,6 @@
1
- import { OP, Transaction, Script, SigHash } from "@scure/btc-signer";
1
+ import { OP } from "@scure/btc-signer/script.js";
2
+ import { Transaction, SigHash } from "@scure/btc-signer/transaction.js";
3
+ import { Script } from "@scure/btc-signer/script.js";
2
4
  import { ErrMissingData, ErrMissingInputs, ErrMissingWitnessUtxo, } from './errors.js';
3
5
  import { schnorr } from "@noble/curves/secp256k1.js";
4
6
  import { base64 } from "@scure/base";
@@ -1,4 +1,4 @@
1
- import { Transaction } from "@scure/btc-signer";
1
+ import { Transaction } from "@scure/btc-signer/transaction.js";
2
2
  import { P2A } from './utils/anchor.js';
3
3
  export function buildForfeitTx(inputs, forfeitPkScript, txLocktime) {
4
4
  const tx = new Transaction({
@@ -1,6 +1,6 @@
1
- import { pubSchnorr, randomPrivateKeyBytes, sha256, } from "@scure/btc-signer/utils";
1
+ import { pubECDSA, pubSchnorr, randomPrivateKeyBytes, sha256, } from "@scure/btc-signer/utils.js";
2
2
  import { hex } from "@scure/base";
3
- import { SigHash } from "@scure/btc-signer";
3
+ import { SigHash } from "@scure/btc-signer/transaction.js";
4
4
  import { TreeSignerSession } from '../tree/signingSession.js';
5
5
  import { schnorr } from "@noble/secp256k1";
6
6
  const ZERO_32 = new Uint8Array(32).fill(0);
@@ -70,6 +70,9 @@ export class SingleKey {
70
70
  }
71
71
  return txCpy;
72
72
  }
73
+ compressedPublicKey() {
74
+ return Promise.resolve(pubECDSA(this.key, true));
75
+ }
73
76
  xOnlyPublicKey() {
74
77
  return Promise.resolve(pubSchnorr(this.key));
75
78
  }
package/dist/esm/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Transaction } from "@scure/btc-signer";
1
+ import { Transaction } from "@scure/btc-signer/transaction.js";
2
2
  import { SingleKey } from './identity/singleKey.js';
3
3
  import { ArkAddress } from './script/address.js';
4
4
  import { VHTLC } from './script/vhtlc.js';
@@ -1,4 +1,4 @@
1
- import * as musig from "@scure/btc-signer/musig2";
1
+ import * as musig from "@scure/btc-signer/musig2.js";
2
2
  import { schnorr } from "@noble/curves/secp256k1.js";
3
3
  // Aggregates multiple public keys according to the MuSig2 algorithm
4
4
  export function aggregateKeys(publicKeys, sort, options = {}) {
@@ -1,4 +1,4 @@
1
- import * as musig from "@scure/btc-signer/musig2";
1
+ import * as musig from "@scure/btc-signer/musig2.js";
2
2
  /**
3
3
  * Generates a pair of public and secret nonces for MuSig2 signing
4
4
  */
@@ -1,4 +1,4 @@
1
- import * as musig from "@scure/btc-signer/musig2";
1
+ import * as musig from "@scure/btc-signer/musig2.js";
2
2
  import { bytesToNumberBE } from "@noble/curves/utils.js";
3
3
  import { Point } from "@noble/secp256k1";
4
4
  import { aggregateKeys } from './keys.js';
@@ -1,4 +1,4 @@
1
- import { NETWORK, TEST_NETWORK } from "@scure/btc-signer";
1
+ import { NETWORK, TEST_NETWORK } from "@scure/btc-signer/utils.js";
2
2
  export const getNetwork = (network) => {
3
3
  return networks[network];
4
4
  };
@@ -1,4 +1,5 @@
1
1
  import { hex } from "@scure/base";
2
+ import { eventSourceIterator } from './utils.js';
2
3
  export var SettlementEventType;
3
4
  (function (SettlementEventType) {
4
5
  SettlementEventType["BatchStarted"] = "batch_started";
@@ -41,6 +42,7 @@ export class RestArkProvider {
41
42
  vtxoMinAmount: BigInt(fromServer.vtxoMinAmount ?? 0),
42
43
  vtxoMaxAmount: BigInt(fromServer.vtxoMaxAmount ?? -1),
43
44
  boardingExitDelay: BigInt(fromServer.boardingExitDelay ?? 0),
45
+ checkpointExitClosure: fromServer.checkpointTapscript ?? "",
44
46
  marketHour: "marketHour" in fromServer && fromServer.marketHour != null
45
47
  ? {
46
48
  nextStartTime: BigInt(fromServer.marketHour.nextStartTime ?? 0),
@@ -215,39 +217,21 @@ export class RestArkProvider {
215
217
  : "";
216
218
  while (!signal?.aborted) {
217
219
  try {
218
- const response = await fetch(url + queryParams, {
219
- headers: {
220
- Accept: "application/json",
221
- },
222
- signal,
223
- });
224
- if (!response.ok) {
225
- throw new Error(`Unexpected status ${response.status} when fetching event stream`);
226
- }
227
- if (!response.body) {
228
- throw new Error("Response body is null");
229
- }
230
- const reader = response.body.getReader();
231
- const decoder = new TextDecoder();
232
- let buffer = "";
233
- while (!signal?.aborted) {
234
- const { done, value } = await reader.read();
235
- if (done) {
236
- break;
237
- }
238
- // Append new data to buffer and split by newlines
239
- buffer += decoder.decode(value, { stream: true });
240
- const lines = buffer.split("\n");
241
- // Process all complete lines
242
- for (let i = 0; i < lines.length - 1; i++) {
243
- const line = lines[i].trim();
244
- if (!line)
245
- continue;
220
+ const eventSource = new EventSource(url + queryParams);
221
+ // Set up abort handling
222
+ const abortHandler = () => {
223
+ eventSource.close();
224
+ };
225
+ signal?.addEventListener("abort", abortHandler);
226
+ try {
227
+ for await (const event of eventSourceIterator(eventSource)) {
228
+ if (signal?.aborted)
229
+ break;
246
230
  try {
247
- const data = JSON.parse(line);
248
- const event = this.parseSettlementEvent(data.result);
249
- if (event) {
250
- yield event;
231
+ const data = JSON.parse(event.data);
232
+ const settlementEvent = this.parseSettlementEvent(data);
233
+ if (settlementEvent) {
234
+ yield settlementEvent;
251
235
  }
252
236
  }
253
237
  catch (err) {
@@ -255,8 +239,10 @@ export class RestArkProvider {
255
239
  throw err;
256
240
  }
257
241
  }
258
- // Keep the last partial line in the buffer
259
- buffer = lines[lines.length - 1];
242
+ }
243
+ finally {
244
+ signal?.removeEventListener("abort", abortHandler);
245
+ eventSource.close();
260
246
  }
261
247
  }
262
248
  catch (error) {
@@ -264,7 +250,6 @@ export class RestArkProvider {
264
250
  break;
265
251
  }
266
252
  // ignore timeout errors, they're expected when the server is not sending anything for 5 min
267
- // these timeouts are set by builtin fetch function
268
253
  if (isFetchTimeoutError(error)) {
269
254
  console.debug("Timeout error ignored");
270
255
  continue;
@@ -278,42 +263,32 @@ export class RestArkProvider {
278
263
  const url = `${this.serverUrl}/v1/txs`;
279
264
  while (!signal?.aborted) {
280
265
  try {
281
- const response = await fetch(url, {
282
- headers: {
283
- Accept: "application/json",
284
- },
285
- signal,
286
- });
287
- if (!response.ok) {
288
- throw new Error(`Unexpected status ${response.status} when fetching transaction stream`);
289
- }
290
- if (!response.body) {
291
- throw new Error("Response body is null");
292
- }
293
- const reader = response.body.getReader();
294
- const decoder = new TextDecoder();
295
- let buffer = "";
296
- while (!signal?.aborted) {
297
- const { done, value } = await reader.read();
298
- if (done) {
299
- break;
300
- }
301
- // Append new data to buffer and split by newlines
302
- buffer += decoder.decode(value, { stream: true });
303
- const lines = buffer.split("\n");
304
- // Process all complete lines
305
- for (let i = 0; i < lines.length - 1; i++) {
306
- const line = lines[i].trim();
307
- if (!line)
308
- continue;
309
- const data = JSON.parse(line);
310
- const txNotification = this.parseTransactionNotification(data.result);
311
- if (txNotification) {
312
- yield txNotification;
266
+ const eventSource = new EventSource(url);
267
+ // Set up abort handling
268
+ const abortHandler = () => {
269
+ eventSource.close();
270
+ };
271
+ signal?.addEventListener("abort", abortHandler);
272
+ try {
273
+ for await (const event of eventSourceIterator(eventSource)) {
274
+ if (signal?.aborted)
275
+ break;
276
+ try {
277
+ const data = JSON.parse(event.data);
278
+ const txNotification = this.parseTransactionNotification(data);
279
+ if (txNotification) {
280
+ yield txNotification;
281
+ }
282
+ }
283
+ catch (err) {
284
+ console.error("Failed to parse transaction notification:", err);
285
+ throw err;
313
286
  }
314
287
  }
315
- // Keep the last partial line in the buffer
316
- buffer = lines[lines.length - 1];
288
+ }
289
+ finally {
290
+ signal?.removeEventListener("abort", abortHandler);
291
+ eventSource.close();
317
292
  }
318
293
  }
319
294
  catch (error) {
@@ -321,12 +296,11 @@ export class RestArkProvider {
321
296
  break;
322
297
  }
323
298
  // ignore timeout errors, they're expected when the server is not sending anything for 5 min
324
- // these timeouts are set by builtin fetch function
325
299
  if (isFetchTimeoutError(error)) {
326
300
  console.debug("Timeout error ignored");
327
301
  continue;
328
302
  }
329
- console.error("Address subscription error:", error);
303
+ console.error("Transaction stream error:", error);
330
304
  throw error;
331
305
  }
332
306
  }
@@ -409,6 +383,10 @@ export class RestArkProvider {
409
383
  signature: data.treeSignature.signature,
410
384
  };
411
385
  }
386
+ // Skip heartbeat events
387
+ if (data.heartbeat) {
388
+ return null;
389
+ }
412
390
  console.warn("Unknown event type:", data);
413
391
  return null;
414
392
  }
@@ -435,6 +413,10 @@ export class RestArkProvider {
435
413
  },
436
414
  };
437
415
  }
416
+ // Skip heartbeat events
417
+ if (data.heartbeat) {
418
+ return null;
419
+ }
438
420
  console.warn("Unknown transaction notification type:", data);
439
421
  return null;
440
422
  }