@arkade-os/sdk 0.3.0-alpha.7 → 0.3.1-alpha.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.
Files changed (88) hide show
  1. package/README.md +115 -14
  2. package/dist/cjs/adapters/expo.js +8 -0
  3. package/dist/cjs/arknote/index.js +3 -3
  4. package/dist/cjs/forfeit.js +5 -2
  5. package/dist/cjs/identity/singleKey.js +5 -4
  6. package/dist/cjs/index.js +7 -3
  7. package/dist/cjs/{bip322 → intent}/index.js +37 -55
  8. package/dist/cjs/providers/ark.js +62 -23
  9. package/dist/cjs/providers/expoArk.js +82 -0
  10. package/dist/cjs/providers/expoIndexer.js +105 -0
  11. package/dist/cjs/providers/indexer.js +3 -1
  12. package/dist/cjs/providers/utils.js +122 -0
  13. package/dist/cjs/script/base.js +1 -2
  14. package/dist/cjs/script/tapscript.js +20 -21
  15. package/dist/cjs/script/vhtlc.js +2 -2
  16. package/dist/cjs/tree/signingSession.js +7 -8
  17. package/dist/cjs/tree/txTree.js +3 -4
  18. package/dist/cjs/tree/validation.js +2 -3
  19. package/dist/cjs/utils/arkTransaction.js +117 -12
  20. package/dist/cjs/utils/unknownFields.js +5 -5
  21. package/dist/cjs/wallet/index.js +1 -1
  22. package/dist/cjs/wallet/onchain.js +4 -5
  23. package/dist/cjs/wallet/serviceWorker/utils.js +2 -9
  24. package/dist/cjs/wallet/serviceWorker/wallet.js +4 -8
  25. package/dist/cjs/wallet/serviceWorker/worker.js +25 -23
  26. package/dist/cjs/wallet/unroll.js +6 -7
  27. package/dist/cjs/wallet/utils.js +11 -0
  28. package/dist/cjs/wallet/vtxo-manager.js +381 -0
  29. package/dist/cjs/wallet/wallet.js +130 -143
  30. package/dist/esm/adapters/expo.js +3 -0
  31. package/dist/esm/arknote/index.js +2 -2
  32. package/dist/esm/forfeit.js +4 -1
  33. package/dist/esm/identity/singleKey.js +7 -6
  34. package/dist/esm/index.js +7 -6
  35. package/dist/esm/{bip322 → intent}/index.js +31 -48
  36. package/dist/esm/providers/ark.js +62 -23
  37. package/dist/esm/providers/expoArk.js +78 -0
  38. package/dist/esm/providers/expoIndexer.js +101 -0
  39. package/dist/esm/providers/indexer.js +3 -1
  40. package/dist/esm/providers/utils.js +87 -0
  41. package/dist/esm/script/base.js +1 -2
  42. package/dist/esm/script/tapscript.js +1 -2
  43. package/dist/esm/script/vhtlc.js +1 -1
  44. package/dist/esm/tree/signingSession.js +8 -9
  45. package/dist/esm/tree/txTree.js +3 -4
  46. package/dist/esm/tree/validation.js +2 -3
  47. package/dist/esm/utils/arkTransaction.js +108 -5
  48. package/dist/esm/utils/unknownFields.js +1 -1
  49. package/dist/esm/wallet/index.js +1 -1
  50. package/dist/esm/wallet/onchain.js +1 -2
  51. package/dist/esm/wallet/serviceWorker/utils.js +1 -8
  52. package/dist/esm/wallet/serviceWorker/wallet.js +5 -9
  53. package/dist/esm/wallet/serviceWorker/worker.js +26 -24
  54. package/dist/esm/wallet/unroll.js +2 -3
  55. package/dist/esm/wallet/utils.js +8 -0
  56. package/dist/esm/wallet/vtxo-manager.js +372 -0
  57. package/dist/esm/wallet/wallet.js +124 -137
  58. package/dist/types/adapters/expo.d.ts +4 -0
  59. package/dist/types/arknote/index.d.ts +1 -1
  60. package/dist/types/forfeit.d.ts +2 -2
  61. package/dist/types/identity/index.d.ts +1 -1
  62. package/dist/types/identity/singleKey.d.ts +1 -1
  63. package/dist/types/index.d.ts +8 -7
  64. package/dist/types/intent/index.d.ts +41 -0
  65. package/dist/types/providers/ark.d.ts +190 -22
  66. package/dist/types/providers/expoArk.d.ts +22 -0
  67. package/dist/types/providers/expoIndexer.d.ts +18 -0
  68. package/dist/types/providers/indexer.d.ts +8 -8
  69. package/dist/types/providers/utils.d.ts +18 -0
  70. package/dist/types/script/base.d.ts +3 -2
  71. package/dist/types/tree/signingSession.d.ts +10 -10
  72. package/dist/types/utils/anchor.d.ts +2 -2
  73. package/dist/types/utils/arkTransaction.d.ts +16 -4
  74. package/dist/types/utils/unknownFields.d.ts +2 -2
  75. package/dist/types/wallet/index.d.ts +47 -7
  76. package/dist/types/wallet/onchain.d.ts +1 -1
  77. package/dist/types/wallet/serviceWorker/utils.d.ts +1 -2
  78. package/dist/types/wallet/serviceWorker/wallet.d.ts +2 -2
  79. package/dist/types/wallet/serviceWorker/worker.d.ts +3 -1
  80. package/dist/types/wallet/unroll.d.ts +1 -1
  81. package/dist/types/wallet/utils.d.ts +2 -0
  82. package/dist/types/wallet/vtxo-manager.d.ts +207 -0
  83. package/dist/types/wallet/wallet.d.ts +16 -4
  84. package/package.json +11 -3
  85. package/dist/cjs/bip322/errors.js +0 -13
  86. package/dist/esm/bip322/errors.js +0 -9
  87. package/dist/types/bip322/errors.d.ts +0 -6
  88. package/dist/types/bip322/index.d.ts +0 -57
@@ -1,12 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildOffchainTx = buildOffchainTx;
4
- const transaction_js_1 = require("@scure/btc-signer/transaction.js");
4
+ exports.hasBoardingTxExpired = hasBoardingTxExpired;
5
+ exports.verifyTapscriptSignatures = verifyTapscriptSignatures;
6
+ const secp256k1_js_1 = require("@noble/curves/secp256k1.js");
7
+ const base_1 = require("@scure/base");
8
+ const btc_signer_1 = require("@scure/btc-signer");
9
+ const payment_js_1 = require("@scure/btc-signer/payment.js");
5
10
  const tapscript_1 = require("../script/tapscript");
6
- const base_1 = require("../script/base");
11
+ const base_2 = require("../script/base");
7
12
  const anchor_1 = require("./anchor");
8
- const base_2 = require("@scure/base");
9
- const utils_js_1 = require("@scure/btc-signer/utils.js");
10
13
  const unknownFields_1 = require("./unknownFields");
11
14
  /**
12
15
  * Builds an offchain transaction with checkpoint transactions.
@@ -31,7 +34,7 @@ function buildOffchainTx(inputs, outputs, serverUnrollScript) {
31
34
  function buildVirtualTx(inputs, outputs) {
32
35
  let lockTime = 0n;
33
36
  for (const input of inputs) {
34
- const tapscript = (0, tapscript_1.decodeTapscript)((0, base_1.scriptFromTapLeafScript)(input.tapLeafScript));
37
+ const tapscript = (0, tapscript_1.decodeTapscript)((0, base_2.scriptFromTapLeafScript)(input.tapLeafScript));
35
38
  if (tapscript_1.CLTVMultisigTapscript.is(tapscript)) {
36
39
  if (lockTime !== 0n) {
37
40
  // if a locktime is already set, check if the new locktime is in the same unit
@@ -45,7 +48,7 @@ function buildVirtualTx(inputs, outputs) {
45
48
  }
46
49
  }
47
50
  }
48
- const tx = new transaction_js_1.Transaction({
51
+ const tx = new btc_signer_1.Transaction({
49
52
  version: 3,
50
53
  allowUnknown: true,
51
54
  allowUnknownOutputs: true,
@@ -55,9 +58,9 @@ function buildVirtualTx(inputs, outputs) {
55
58
  tx.addInput({
56
59
  txid: input.txid,
57
60
  index: input.vout,
58
- sequence: lockTime ? transaction_js_1.DEFAULT_SEQUENCE - 1 : undefined,
61
+ sequence: lockTime ? btc_signer_1.DEFAULT_SEQUENCE - 1 : undefined,
59
62
  witnessUtxo: {
60
- script: base_1.VtxoScript.decode(input.tapTree).pkScript,
63
+ script: base_2.VtxoScript.decode(input.tapTree).pkScript,
61
64
  amount: BigInt(input.value),
62
65
  },
63
66
  tapLeafScript: [input.tapLeafScript],
@@ -74,9 +77,9 @@ function buildVirtualTx(inputs, outputs) {
74
77
  function buildCheckpointTx(vtxo, serverUnrollScript) {
75
78
  // create the checkpoint vtxo script from collaborative closure
76
79
  const collaborativeClosure = (0, tapscript_1.decodeTapscript)(vtxo.checkpointTapLeafScript ??
77
- (0, base_1.scriptFromTapLeafScript)(vtxo.tapLeafScript));
80
+ (0, base_2.scriptFromTapLeafScript)(vtxo.tapLeafScript));
78
81
  // create the checkpoint vtxo script combining collaborative closure and server unroll script
79
- const checkpointVtxoScript = new base_1.VtxoScript([
82
+ const checkpointVtxoScript = new base_2.VtxoScript([
80
83
  serverUnrollScript.script,
81
84
  collaborativeClosure.script,
82
85
  ]);
@@ -88,10 +91,10 @@ function buildCheckpointTx(vtxo, serverUnrollScript) {
88
91
  },
89
92
  ]);
90
93
  // get the collaborative leaf proof
91
- const collaborativeLeafProof = checkpointVtxoScript.findLeaf(base_2.hex.encode(collaborativeClosure.script));
94
+ const collaborativeLeafProof = checkpointVtxoScript.findLeaf(base_1.hex.encode(collaborativeClosure.script));
92
95
  // create the checkpoint input that will be used as input of the virtual tx
93
96
  const checkpointInput = {
94
- txid: base_2.hex.encode((0, utils_js_1.sha256x2)(checkpointTx.toBytes(true)).reverse()),
97
+ txid: checkpointTx.id,
95
98
  vout: 0,
96
99
  value: vtxo.value,
97
100
  tapLeafScript: collaborativeLeafProof,
@@ -106,3 +109,105 @@ const nLocktimeMinSeconds = 500000000n;
106
109
  function isSeconds(locktime) {
107
110
  return locktime >= nLocktimeMinSeconds;
108
111
  }
112
+ function hasBoardingTxExpired(coin, boardingTimelock) {
113
+ if (!coin.status.block_time)
114
+ return false;
115
+ if (boardingTimelock.value === 0n)
116
+ return true;
117
+ if (boardingTimelock.type !== "blocks")
118
+ return false; // TODO: handle get chain tip
119
+ // validate expiry in terms of seconds
120
+ const now = BigInt(Math.floor(Date.now() / 1000));
121
+ const blockTime = BigInt(Math.floor(coin.status.block_time));
122
+ return blockTime + boardingTimelock.value <= now;
123
+ }
124
+ /**
125
+ * Formats a sighash type as a hex string (e.g., 0x01)
126
+ */
127
+ function formatSighash(type) {
128
+ return `0x${type.toString(16).padStart(2, "0")}`;
129
+ }
130
+ /**
131
+ * Verify tapscript signatures on a transaction input
132
+ * @param tx Transaction to verify
133
+ * @param inputIndex Index of the input to verify
134
+ * @param requiredSigners List of required signer pubkeys (hex encoded)
135
+ * @param excludePubkeys List of pubkeys to exclude from verification (hex encoded, e.g., server key not yet signed)
136
+ * @param allowedSighashTypes List of allowed sighash types (defaults to [SigHash.DEFAULT])
137
+ * @throws Error if verification fails
138
+ */
139
+ function verifyTapscriptSignatures(tx, inputIndex, requiredSigners, excludePubkeys = [], allowedSighashTypes = [btc_signer_1.SigHash.DEFAULT]) {
140
+ const input = tx.getInput(inputIndex);
141
+ // Collect prevout scripts and amounts for ALL inputs (required for preimageWitnessV1)
142
+ const prevoutScripts = [];
143
+ const prevoutAmounts = [];
144
+ for (let i = 0; i < tx.inputsLength; i++) {
145
+ const inp = tx.getInput(i);
146
+ if (!inp.witnessUtxo) {
147
+ throw new Error(`Input ${i} is missing witnessUtxo`);
148
+ }
149
+ prevoutScripts.push(inp.witnessUtxo.script);
150
+ prevoutAmounts.push(inp.witnessUtxo.amount);
151
+ }
152
+ // Verify tapScriptSig signatures
153
+ if (!input.tapScriptSig || input.tapScriptSig.length === 0) {
154
+ throw new Error(`Input ${inputIndex} is missing tapScriptSig`);
155
+ }
156
+ // Verify each signature in tapScriptSig
157
+ for (const [tapScriptSigData, signature] of input.tapScriptSig) {
158
+ const pubKey = tapScriptSigData.pubKey;
159
+ const pubKeyHex = base_1.hex.encode(pubKey);
160
+ // Skip verification for excluded pubkeys
161
+ if (excludePubkeys.includes(pubKeyHex)) {
162
+ continue;
163
+ }
164
+ // Extract sighash type from signature
165
+ // Schnorr signatures are 64 bytes, with optional 1-byte sighash appended
166
+ const sighashType = signature.length === 65 ? signature[64] : btc_signer_1.SigHash.DEFAULT;
167
+ const sig = signature.subarray(0, 64);
168
+ // Verify sighash type is allowed
169
+ if (!allowedSighashTypes.includes(sighashType)) {
170
+ const sighashName = formatSighash(sighashType);
171
+ throw new Error(`Unallowed sighash type ${sighashName} for input ${inputIndex}, pubkey ${pubKeyHex}.`);
172
+ }
173
+ // Find the tapLeafScript that matches this signature's leafHash
174
+ if (!input.tapLeafScript || input.tapLeafScript.length === 0) {
175
+ throw new Error();
176
+ }
177
+ // Search for the leaf that matches the leafHash in tapScriptSigData
178
+ const leafHash = tapScriptSigData.leafHash;
179
+ const leafHashHex = base_1.hex.encode(leafHash);
180
+ let matchingScript;
181
+ let matchingVersion;
182
+ for (const [_, scriptWithVersion] of input.tapLeafScript) {
183
+ const script = scriptWithVersion.subarray(0, -1);
184
+ const version = scriptWithVersion[scriptWithVersion.length - 1];
185
+ // Compute the leaf hash for this script and compare as hex strings
186
+ const computedLeafHash = (0, payment_js_1.tapLeafHash)(script, version);
187
+ const computedHex = base_1.hex.encode(computedLeafHash);
188
+ if (computedHex === leafHashHex) {
189
+ matchingScript = script;
190
+ matchingVersion = version;
191
+ break;
192
+ }
193
+ }
194
+ if (!matchingScript || matchingVersion === undefined) {
195
+ throw new Error(`Input ${inputIndex}: No tapLeafScript found matching leafHash ${base_1.hex.encode(leafHash)}`);
196
+ }
197
+ // Reconstruct the message that was signed
198
+ // Note: preimageWitnessV1 requires ALL input prevout scripts and amounts
199
+ const message = tx.preimageWitnessV1(inputIndex, prevoutScripts, sighashType, prevoutAmounts, undefined, matchingScript, matchingVersion);
200
+ // Verify the schnorr signature
201
+ const isValid = secp256k1_js_1.schnorr.verify(sig, message, pubKey);
202
+ if (!isValid) {
203
+ throw new Error(`Invalid signature for input ${inputIndex}, pubkey ${pubKeyHex}`);
204
+ }
205
+ }
206
+ // Verify we have signatures from all required signers (excluding those we're skipping)
207
+ const signedPubkeys = input.tapScriptSig.map(([data]) => base_1.hex.encode(data.pubKey));
208
+ const requiredNotExcluded = requiredSigners.filter((pk) => !excludePubkeys.includes(pk));
209
+ const missingSigners = requiredNotExcluded.filter((pk) => !signedPubkeys.includes(pk));
210
+ if (missingSigners.length > 0) {
211
+ throw new Error(`Missing signatures from: ${missingSigners.map((pk) => pk.slice(0, 16)).join(", ")}...`);
212
+ }
213
+ }
@@ -37,7 +37,7 @@ exports.VtxoTreeExpiry = exports.CosignerPublicKey = exports.ConditionWitness =
37
37
  exports.setArkPsbtField = setArkPsbtField;
38
38
  exports.getArkPsbtFields = getArkPsbtFields;
39
39
  const bip68 = __importStar(require("bip68"));
40
- const script_js_1 = require("@scure/btc-signer/script.js");
40
+ const btc_signer_1 = require("@scure/btc-signer");
41
41
  const base_1 = require("@scure/base");
42
42
  /**
43
43
  * ArkPsbtFieldKey is the key values for ark psbt fields.
@@ -126,12 +126,12 @@ exports.ConditionWitness = {
126
126
  type: exports.ArkPsbtFieldKeyType,
127
127
  key: encodedPsbtFieldKey[ArkPsbtFieldKey.ConditionWitness],
128
128
  },
129
- script_js_1.RawWitness.encode(value),
129
+ btc_signer_1.RawWitness.encode(value),
130
130
  ],
131
131
  decode: (value) => nullIfCatch(() => {
132
132
  if (!checkKeyIncludes(value[0], ArkPsbtFieldKey.ConditionWitness))
133
133
  return null;
134
- return script_js_1.RawWitness.decode(value[1]);
134
+ return btc_signer_1.RawWitness.decode(value[1]);
135
135
  }),
136
136
  };
137
137
  /**
@@ -176,12 +176,12 @@ exports.VtxoTreeExpiry = {
176
176
  type: exports.ArkPsbtFieldKeyType,
177
177
  key: encodedPsbtFieldKey[ArkPsbtFieldKey.VtxoTreeExpiry],
178
178
  },
179
- (0, script_js_1.ScriptNum)(6, true).encode(value.value === 0n ? 0n : value.value),
179
+ (0, btc_signer_1.ScriptNum)(6, true).encode(value.value === 0n ? 0n : value.value),
180
180
  ],
181
181
  decode: (unknown) => nullIfCatch(() => {
182
182
  if (!checkKeyIncludes(unknown[0], ArkPsbtFieldKey.VtxoTreeExpiry))
183
183
  return null;
184
- const v = (0, script_js_1.ScriptNum)(6, true).decode(unknown[1]);
184
+ const v = (0, btc_signer_1.ScriptNum)(6, true).decode(unknown[1]);
185
185
  if (!v)
186
186
  return null;
187
187
  const { blocks, seconds } = bip68.decode(Number(v));
@@ -10,7 +10,7 @@ var TxType;
10
10
  TxType["TxReceived"] = "RECEIVED";
11
11
  })(TxType || (exports.TxType = TxType = {}));
12
12
  function isSpendable(vtxo) {
13
- return vtxo.spentBy === undefined || vtxo.spentBy === "";
13
+ return !vtxo.isSpent;
14
14
  }
15
15
  function isRecoverable(vtxo) {
16
16
  return vtxo.virtualStatus.state === "swept" && isSpendable(vtxo);
@@ -2,10 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OnchainWallet = void 0;
4
4
  exports.selectCoins = selectCoins;
5
- const payment_js_1 = require("@scure/btc-signer/payment.js");
5
+ const btc_signer_1 = require("@scure/btc-signer");
6
6
  const networks_1 = require("../networks");
7
7
  const onchain_1 = require("../providers/onchain");
8
- const transaction_js_1 = require("@scure/btc-signer/transaction.js");
9
8
  const anchor_1 = require("../utils/anchor");
10
9
  const txSizeEstimator_1 = require("../utils/txSizeEstimator");
11
10
  /**
@@ -39,7 +38,7 @@ class OnchainWallet {
39
38
  }
40
39
  const network = (0, networks_1.getNetwork)(networkName);
41
40
  const onchainProvider = provider || new onchain_1.EsploraProvider(onchain_1.ESPLORA_URL[networkName]);
42
- const onchainP2TR = (0, payment_js_1.p2tr)(pubkey, undefined, network);
41
+ const onchainP2TR = (0, btc_signer_1.p2tr)(pubkey, undefined, network);
43
42
  return new OnchainWallet(identity, network, onchainP2TR, onchainProvider);
44
43
  }
45
44
  get address() {
@@ -80,7 +79,7 @@ class OnchainWallet {
80
79
  // Select coins
81
80
  const selected = selectCoins(coins, totalNeeded);
82
81
  // Create transaction
83
- let tx = new transaction_js_1.Transaction();
82
+ let tx = new btc_signer_1.Transaction();
84
83
  // Add inputs
85
84
  for (const input of selected.inputs) {
86
85
  tx.addInput({
@@ -108,7 +107,7 @@ class OnchainWallet {
108
107
  }
109
108
  async bumpP2A(parent) {
110
109
  const parentVsize = parent.vsize;
111
- let child = new transaction_js_1.Transaction({
110
+ let child = new btc_signer_1.Transaction({
112
111
  allowUnknownInputs: true,
113
112
  allowLegacyWitnessUtxo: true,
114
113
  version: 3,
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_DB_NAME = void 0;
3
4
  exports.setupServiceWorker = setupServiceWorker;
4
- exports.extendVirtualCoin = extendVirtualCoin;
5
+ exports.DEFAULT_DB_NAME = "arkade-service-worker";
5
6
  /**
6
7
  * setupServiceWorker sets up the service worker.
7
8
  * @param path - the path to the service worker script
@@ -48,11 +49,3 @@ async function setupServiceWorker(path) {
48
49
  navigator.serviceWorker.addEventListener("error", onError);
49
50
  });
50
51
  }
51
- function extendVirtualCoin(wallet, vtxo) {
52
- return {
53
- ...vtxo,
54
- forfeitTapLeafScript: wallet.offchainTapscript.forfeit(),
55
- intentTapLeafScript: wallet.offchainTapscript.exit(),
56
- tapTree: wallet.offchainTapscript.encode(),
57
- };
58
- }
@@ -25,7 +25,7 @@ class ServiceWorkerWallet {
25
25
  }
26
26
  static async create(options) {
27
27
  // Default to IndexedDB for service worker context
28
- const storage = options.storage || new indexedDB_1.IndexedDBStorageAdapter("wallet-db");
28
+ const storage = new indexedDB_1.IndexedDBStorageAdapter(options.dbName || utils_1.DEFAULT_DB_NAME, options.dbVersion);
29
29
  // Create repositories
30
30
  const walletRepo = new walletRepository_1.WalletRepositoryImpl(storage);
31
31
  const contractRepo = new contractRepository_1.ContractRepositoryImpl(storage);
@@ -34,7 +34,7 @@ class ServiceWorkerWallet {
34
34
  ? options.identity
35
35
  : null;
36
36
  if (!identity) {
37
- throw new Error("ServiceWorkerWallet.create() requires a Identity that can expose its private key");
37
+ throw new Error("ServiceWorkerWallet.create() requires a Identity that can expose a single private key");
38
38
  }
39
39
  // Extract private key for service worker initialization
40
40
  const privateKey = identity.toHex();
@@ -77,13 +77,9 @@ class ServiceWorkerWallet {
77
77
  // Register and setup the service worker
78
78
  const serviceWorker = await (0, utils_1.setupServiceWorker)(options.serviceWorkerPath);
79
79
  // Use the existing create method
80
- return await ServiceWorkerWallet.create({
81
- arkServerPublicKey: options.arkServerPublicKey,
82
- arkServerUrl: options.arkServerUrl,
83
- esploraUrl: options.esploraUrl,
84
- identity: options.identity,
80
+ return ServiceWorkerWallet.create({
81
+ ...options,
85
82
  serviceWorker,
86
- storage: options.storage,
87
83
  });
88
84
  }
89
85
  // send a message and wait for a response
@@ -13,15 +13,18 @@ const indexer_1 = require("../../providers/indexer");
13
13
  const base_1 = require("@scure/base");
14
14
  const indexedDB_1 = require("../../storage/indexedDB");
15
15
  const walletRepository_1 = require("../../repositories/walletRepository");
16
- const utils_1 = require("./utils");
16
+ const utils_1 = require("../utils");
17
+ const utils_2 = require("./utils");
17
18
  /**
18
19
  * Worker is a class letting to interact with ServiceWorkerWallet from the client
19
20
  * it aims to be run in a service worker context
20
21
  */
21
22
  class Worker {
22
- constructor(messageCallback = () => { }) {
23
+ constructor(dbName = utils_2.DEFAULT_DB_NAME, dbVersion = 1, messageCallback = () => { }) {
24
+ this.dbName = dbName;
25
+ this.dbVersion = dbVersion;
23
26
  this.messageCallback = messageCallback;
24
- this.storage = new indexedDB_1.IndexedDBStorageAdapter("arkade-service-worker", 1);
27
+ this.storage = new indexedDB_1.IndexedDBStorageAdapter(dbName, dbVersion);
25
28
  this.walletRepository = new walletRepository_1.WalletRepositoryImpl(this.storage);
26
29
  }
27
30
  /**
@@ -77,6 +80,8 @@ class Worker {
77
80
  this.incomingFundsSubscription();
78
81
  // Clear storage - this replaces vtxoRepository.close()
79
82
  await this.storage.clear();
83
+ // Reset in-memory caches by recreating the repository
84
+ this.walletRepository = new walletRepository_1.WalletRepositoryImpl(this.storage);
80
85
  this.wallet = undefined;
81
86
  this.arkProvider = undefined;
82
87
  this.indexerProvider = undefined;
@@ -105,7 +110,7 @@ class Worker {
105
110
  const txs = await this.wallet.getTransactionHistory();
106
111
  if (txs)
107
112
  await this.walletRepository.saveTransactions(address, txs);
108
- // stop previous subscriptions if any
113
+ // unsubscribe previous subscription if any
109
114
  if (this.incomingFundsSubscription)
110
115
  this.incomingFundsSubscription();
111
116
  // subscribe for incoming funds and notify all clients when new funds arrive
@@ -127,7 +132,7 @@ class Worker {
127
132
  // notify all clients about the vtxo update
128
133
  this.sendMessageToAllClients("VTXO_UPDATE", JSON.stringify({ newVtxos, spentVtxos }));
129
134
  }
130
- if (funds.type === "utxo" && funds.coins.length > 0) {
135
+ if (funds.type === "utxo") {
131
136
  // notify all clients about the utxo update
132
137
  this.sendMessageToAllClients("UTXO_UPDATE", JSON.stringify(funds.coins));
133
138
  }
@@ -354,23 +359,21 @@ class Worker {
354
359
  return;
355
360
  }
356
361
  try {
357
- let vtxos = await this.getSpendableVtxos();
358
- if (!message.filter?.withRecoverable) {
359
- if (!this.wallet)
360
- throw new Error("Wallet not initialized");
361
- // exclude subdust is we don't want recoverable
362
- const dustAmount = this.wallet?.dustAmount;
363
- vtxos =
364
- dustAmount == null
365
- ? vtxos
366
- : vtxos.filter((v) => !(0, __1.isSubdust)(v, dustAmount));
367
- }
368
- if (message.filter?.withRecoverable) {
369
- // get also swept and spendable vtxos
370
- const sweptVtxos = await this.getSweptVtxos();
371
- vtxos.push(...sweptVtxos.filter(__1.isSpendable));
372
- }
373
- event.source?.postMessage(response_1.Response.vtxos(message.id, vtxos));
362
+ const vtxos = await this.getSpendableVtxos();
363
+ const dustAmount = this.wallet.dustAmount;
364
+ const includeRecoverable = message.filter?.withRecoverable ?? false;
365
+ const filteredVtxos = includeRecoverable
366
+ ? vtxos
367
+ : vtxos.filter((v) => {
368
+ if (dustAmount != null && (0, __1.isSubdust)(v, dustAmount)) {
369
+ return false;
370
+ }
371
+ if ((0, __1.isRecoverable)(v)) {
372
+ return false;
373
+ }
374
+ return true;
375
+ });
376
+ event.source?.postMessage(response_1.Response.vtxos(message.id, filteredVtxos));
374
377
  }
375
378
  catch (error) {
376
379
  console.error("Error getting vtxos:", error);
@@ -529,7 +532,6 @@ class Worker {
529
532
  }
530
533
  async handleReloadWallet(event) {
531
534
  const message = event.data;
532
- console.log("RELOAD_WALLET message received", message);
533
535
  if (!request_1.Request.isReloadWallet(message)) {
534
536
  console.error("Invalid RELOAD_WALLET message format", message);
535
537
  event.source?.postMessage(response_1.Response.error(message.id, "Invalid RELOAD_WALLET message format"));
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Unroll = void 0;
4
- const transaction_js_1 = require("@scure/btc-signer/transaction.js");
5
- const indexer_1 = require("../providers/indexer");
6
4
  const base_1 = require("@scure/base");
5
+ const btc_signer_1 = require("@scure/btc-signer");
6
+ const indexer_1 = require("../providers/indexer");
7
7
  const base_2 = require("../script/base");
8
- const psbt_js_1 = require("@scure/btc-signer/psbt.js");
9
8
  const txSizeEstimator_1 = require("../utils/txSizeEstimator");
10
9
  const wallet_1 = require("./wallet");
11
10
  var Unroll;
@@ -106,7 +105,7 @@ var Unroll;
106
105
  if (virtualTxs.txs.length === 0) {
107
106
  throw new Error(`Tx ${nextTxToBroadcast.txid} not found`);
108
107
  }
109
- const tx = transaction_js_1.Transaction.fromPSBT(base_1.base64.decode(virtualTxs.txs[0]), {
108
+ const tx = btc_signer_1.Transaction.fromPSBT(base_1.base64.decode(virtualTxs.txs[0]), {
110
109
  allowUnknownInputs: true,
111
110
  });
112
111
  // finalize the tree transaction
@@ -197,11 +196,11 @@ var Unroll;
197
196
  amount: BigInt(vtxo.value),
198
197
  script: base_2.VtxoScript.decode(vtxo.tapTree).pkScript,
199
198
  },
200
- sighashType: transaction_js_1.SigHash.DEFAULT,
199
+ sighashType: btc_signer_1.SigHash.DEFAULT,
201
200
  });
202
- txWeightEstimator.addTapscriptInput(64, spendingLeaf[1].length, psbt_js_1.TaprootControlBlock.encode(spendingLeaf[0]).length);
201
+ txWeightEstimator.addTapscriptInput(64, spendingLeaf[1].length, btc_signer_1.TaprootControlBlock.encode(spendingLeaf[0]).length);
203
202
  }
204
- const tx = new transaction_js_1.Transaction({ allowUnknownInputs: true, version: 2 });
203
+ const tx = new btc_signer_1.Transaction({ allowUnknownInputs: true, version: 2 });
205
204
  for (const input of inputs) {
206
205
  tx.addInput(input);
207
206
  }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extendVirtualCoin = extendVirtualCoin;
4
+ function extendVirtualCoin(wallet, vtxo) {
5
+ return {
6
+ ...vtxo,
7
+ forfeitTapLeafScript: wallet.offchainTapscript.forfeit(),
8
+ intentTapLeafScript: wallet.offchainTapscript.exit(),
9
+ tapTree: wallet.offchainTapscript.encode(),
10
+ };
11
+ }