@arkade-os/sdk 0.3.12 → 0.4.0-next.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 (250) hide show
  1. package/README.md +483 -54
  2. package/dist/cjs/adapters/expo-db.js +35 -0
  3. package/dist/cjs/asset/assetGroup.js +141 -0
  4. package/dist/cjs/asset/assetId.js +88 -0
  5. package/dist/cjs/asset/assetInput.js +204 -0
  6. package/dist/cjs/asset/assetOutput.js +159 -0
  7. package/dist/cjs/asset/assetRef.js +82 -0
  8. package/dist/cjs/asset/index.js +24 -0
  9. package/dist/cjs/asset/metadata.js +172 -0
  10. package/dist/cjs/asset/packet.js +164 -0
  11. package/dist/cjs/asset/types.js +25 -0
  12. package/dist/cjs/asset/utils.js +105 -0
  13. package/dist/cjs/contracts/arkcontract.js +148 -0
  14. package/dist/cjs/contracts/contractManager.js +436 -0
  15. package/dist/cjs/contracts/contractWatcher.js +567 -0
  16. package/dist/cjs/contracts/handlers/default.js +85 -0
  17. package/dist/cjs/contracts/handlers/delegate.js +89 -0
  18. package/dist/cjs/contracts/handlers/helpers.js +105 -0
  19. package/dist/cjs/contracts/handlers/index.js +19 -0
  20. package/dist/cjs/contracts/handlers/registry.js +89 -0
  21. package/dist/cjs/contracts/handlers/vhtlc.js +193 -0
  22. package/dist/cjs/contracts/index.js +41 -0
  23. package/dist/cjs/contracts/types.js +2 -0
  24. package/dist/cjs/db/manager.js +97 -0
  25. package/dist/cjs/forfeit.js +12 -8
  26. package/dist/cjs/identity/index.js +1 -0
  27. package/dist/cjs/identity/seedIdentity.js +255 -0
  28. package/dist/cjs/index.js +70 -14
  29. package/dist/cjs/intent/index.js +28 -2
  30. package/dist/cjs/providers/ark.js +7 -0
  31. package/dist/cjs/providers/delegator.js +66 -0
  32. package/dist/cjs/providers/expoIndexer.js +5 -0
  33. package/dist/cjs/providers/indexer.js +68 -1
  34. package/dist/cjs/providers/onchain.js +2 -2
  35. package/dist/cjs/providers/utils.js +1 -0
  36. package/dist/cjs/repositories/contractRepository.js +0 -103
  37. package/dist/cjs/repositories/inMemory/contractRepository.js +55 -0
  38. package/dist/cjs/repositories/inMemory/walletRepository.js +80 -0
  39. package/dist/cjs/repositories/index.js +16 -0
  40. package/dist/cjs/repositories/indexedDB/contractRepository.js +187 -0
  41. package/dist/cjs/repositories/indexedDB/db.js +57 -0
  42. package/dist/cjs/repositories/indexedDB/schema.js +159 -0
  43. package/dist/cjs/repositories/indexedDB/walletRepository.js +338 -0
  44. package/dist/cjs/repositories/indexedDB/websqlAdapter.js +144 -0
  45. package/dist/cjs/repositories/migrations/contractRepositoryImpl.js +127 -0
  46. package/dist/cjs/repositories/migrations/fromStorageAdapter.js +66 -0
  47. package/dist/cjs/repositories/migrations/walletRepositoryImpl.js +180 -0
  48. package/dist/cjs/repositories/walletRepository.js +0 -169
  49. package/dist/cjs/script/base.js +54 -0
  50. package/dist/cjs/script/delegate.js +49 -0
  51. package/dist/cjs/storage/asyncStorage.js +4 -1
  52. package/dist/cjs/storage/fileSystem.js +3 -0
  53. package/dist/cjs/storage/inMemory.js +3 -0
  54. package/dist/cjs/storage/indexedDB.js +5 -1
  55. package/dist/cjs/storage/localStorage.js +3 -0
  56. package/dist/cjs/utils/arkTransaction.js +16 -0
  57. package/dist/cjs/utils/transactionHistory.js +50 -0
  58. package/dist/cjs/utils/txSizeEstimator.js +39 -14
  59. package/dist/cjs/wallet/asset-manager.js +338 -0
  60. package/dist/cjs/wallet/asset.js +117 -0
  61. package/dist/cjs/wallet/batch.js +1 -1
  62. package/dist/cjs/wallet/delegator.js +235 -0
  63. package/dist/cjs/wallet/expo/background.js +133 -0
  64. package/dist/cjs/wallet/expo/index.js +9 -0
  65. package/dist/cjs/wallet/expo/wallet.js +231 -0
  66. package/dist/cjs/wallet/onchain.js +57 -12
  67. package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +568 -0
  68. package/dist/cjs/wallet/serviceWorker/wallet.js +383 -102
  69. package/dist/cjs/wallet/unroll.js +7 -2
  70. package/dist/cjs/wallet/utils.js +60 -0
  71. package/dist/cjs/wallet/validation.js +151 -0
  72. package/dist/cjs/wallet/vtxo-manager.js +1 -1
  73. package/dist/cjs/wallet/wallet.js +702 -260
  74. package/dist/cjs/worker/browser/service-worker-manager.js +82 -0
  75. package/dist/cjs/{wallet/serviceWorker → worker/browser}/utils.js +2 -1
  76. package/dist/cjs/worker/expo/asyncStorageTaskQueue.js +78 -0
  77. package/dist/cjs/worker/expo/index.js +12 -0
  78. package/dist/cjs/worker/expo/processors/contractPollProcessor.js +61 -0
  79. package/dist/cjs/worker/expo/processors/index.js +6 -0
  80. package/dist/cjs/worker/expo/taskQueue.js +41 -0
  81. package/dist/cjs/worker/expo/taskRunner.js +57 -0
  82. package/dist/cjs/worker/messageBus.js +252 -0
  83. package/dist/esm/adapters/expo-db.js +27 -0
  84. package/dist/esm/asset/assetGroup.js +137 -0
  85. package/dist/esm/asset/assetId.js +84 -0
  86. package/dist/esm/asset/assetInput.js +199 -0
  87. package/dist/esm/asset/assetOutput.js +154 -0
  88. package/dist/esm/asset/assetRef.js +78 -0
  89. package/dist/esm/asset/index.js +8 -0
  90. package/dist/esm/asset/metadata.js +167 -0
  91. package/dist/esm/asset/packet.js +159 -0
  92. package/dist/esm/asset/types.js +22 -0
  93. package/dist/esm/asset/utils.js +99 -0
  94. package/dist/esm/contracts/arkcontract.js +141 -0
  95. package/dist/esm/contracts/contractManager.js +432 -0
  96. package/dist/esm/contracts/contractWatcher.js +563 -0
  97. package/dist/esm/contracts/handlers/default.js +82 -0
  98. package/dist/esm/contracts/handlers/delegate.js +86 -0
  99. package/dist/esm/contracts/handlers/helpers.js +66 -0
  100. package/dist/esm/contracts/handlers/index.js +12 -0
  101. package/dist/esm/contracts/handlers/registry.js +86 -0
  102. package/dist/esm/contracts/handlers/vhtlc.js +190 -0
  103. package/dist/esm/contracts/index.js +13 -0
  104. package/dist/esm/contracts/types.js +1 -0
  105. package/dist/esm/db/manager.js +92 -0
  106. package/dist/esm/forfeit.js +11 -8
  107. package/dist/esm/identity/index.js +1 -0
  108. package/dist/esm/identity/seedIdentity.js +249 -0
  109. package/dist/esm/index.js +25 -15
  110. package/dist/esm/intent/index.js +28 -2
  111. package/dist/esm/providers/ark.js +7 -0
  112. package/dist/esm/providers/delegator.js +62 -0
  113. package/dist/esm/providers/expoIndexer.js +5 -0
  114. package/dist/esm/providers/indexer.js +68 -1
  115. package/dist/esm/providers/onchain.js +2 -2
  116. package/dist/esm/providers/utils.js +1 -0
  117. package/dist/esm/repositories/contractRepository.js +1 -101
  118. package/dist/esm/repositories/inMemory/contractRepository.js +51 -0
  119. package/dist/esm/repositories/inMemory/walletRepository.js +76 -0
  120. package/dist/esm/repositories/index.js +8 -0
  121. package/dist/esm/repositories/indexedDB/contractRepository.js +183 -0
  122. package/dist/esm/repositories/indexedDB/db.js +42 -0
  123. package/dist/esm/repositories/indexedDB/schema.js +155 -0
  124. package/dist/esm/repositories/indexedDB/walletRepository.js +334 -0
  125. package/dist/esm/repositories/indexedDB/websqlAdapter.js +138 -0
  126. package/dist/esm/repositories/migrations/contractRepositoryImpl.js +121 -0
  127. package/dist/esm/repositories/migrations/fromStorageAdapter.js +58 -0
  128. package/dist/esm/repositories/migrations/walletRepositoryImpl.js +176 -0
  129. package/dist/esm/repositories/walletRepository.js +1 -167
  130. package/dist/esm/script/base.js +21 -1
  131. package/dist/esm/script/delegate.js +46 -0
  132. package/dist/esm/storage/asyncStorage.js +4 -1
  133. package/dist/esm/storage/fileSystem.js +3 -0
  134. package/dist/esm/storage/inMemory.js +3 -0
  135. package/dist/esm/storage/indexedDB.js +5 -1
  136. package/dist/esm/storage/localStorage.js +3 -0
  137. package/dist/esm/utils/arkTransaction.js +15 -0
  138. package/dist/esm/utils/transactionHistory.js +50 -0
  139. package/dist/esm/utils/txSizeEstimator.js +39 -14
  140. package/dist/esm/wallet/asset-manager.js +333 -0
  141. package/dist/esm/wallet/asset.js +111 -0
  142. package/dist/esm/wallet/batch.js +1 -1
  143. package/dist/esm/wallet/delegator.js +231 -0
  144. package/dist/esm/wallet/expo/background.js +128 -0
  145. package/dist/esm/wallet/expo/index.js +2 -0
  146. package/dist/esm/wallet/expo/wallet.js +194 -0
  147. package/dist/esm/wallet/onchain.js +57 -12
  148. package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +564 -0
  149. package/dist/esm/wallet/serviceWorker/wallet.js +382 -101
  150. package/dist/esm/wallet/unroll.js +7 -2
  151. package/dist/esm/wallet/utils.js +55 -0
  152. package/dist/esm/wallet/validation.js +139 -0
  153. package/dist/esm/wallet/vtxo-manager.js +1 -1
  154. package/dist/esm/wallet/wallet.js +704 -229
  155. package/dist/esm/worker/browser/service-worker-manager.js +76 -0
  156. package/dist/esm/{wallet/serviceWorker → worker/browser}/utils.js +2 -1
  157. package/dist/esm/worker/expo/asyncStorageTaskQueue.js +74 -0
  158. package/dist/esm/worker/expo/index.js +4 -0
  159. package/dist/esm/worker/expo/processors/contractPollProcessor.js +58 -0
  160. package/dist/esm/worker/expo/processors/index.js +1 -0
  161. package/dist/esm/worker/expo/taskQueue.js +37 -0
  162. package/dist/esm/worker/expo/taskRunner.js +54 -0
  163. package/dist/esm/worker/messageBus.js +248 -0
  164. package/dist/types/adapters/expo-db.d.ts +7 -0
  165. package/dist/types/asset/assetGroup.d.ts +28 -0
  166. package/dist/types/asset/assetId.d.ts +19 -0
  167. package/dist/types/asset/assetInput.d.ts +46 -0
  168. package/dist/types/asset/assetOutput.d.ts +39 -0
  169. package/dist/types/asset/assetRef.d.ts +25 -0
  170. package/dist/types/asset/index.d.ts +8 -0
  171. package/dist/types/asset/metadata.d.ts +37 -0
  172. package/dist/types/asset/packet.d.ts +27 -0
  173. package/dist/types/asset/types.d.ts +18 -0
  174. package/dist/types/asset/utils.d.ts +21 -0
  175. package/dist/types/contracts/arkcontract.d.ts +101 -0
  176. package/dist/types/contracts/contractManager.d.ts +331 -0
  177. package/dist/types/contracts/contractWatcher.d.ts +192 -0
  178. package/dist/types/contracts/handlers/default.d.ts +19 -0
  179. package/dist/types/contracts/handlers/delegate.d.ts +21 -0
  180. package/dist/types/contracts/handlers/helpers.d.ts +18 -0
  181. package/dist/types/contracts/handlers/index.d.ts +7 -0
  182. package/dist/types/contracts/handlers/registry.d.ts +65 -0
  183. package/dist/types/contracts/handlers/vhtlc.d.ts +32 -0
  184. package/dist/types/contracts/index.d.ts +14 -0
  185. package/dist/types/contracts/types.d.ts +222 -0
  186. package/dist/types/db/manager.d.ts +22 -0
  187. package/dist/types/forfeit.d.ts +2 -1
  188. package/dist/types/identity/index.d.ts +1 -0
  189. package/dist/types/identity/seedIdentity.d.ts +128 -0
  190. package/dist/types/index.d.ts +21 -12
  191. package/dist/types/intent/index.d.ts +2 -1
  192. package/dist/types/providers/ark.d.ts +11 -2
  193. package/dist/types/providers/delegator.d.ts +29 -0
  194. package/dist/types/providers/indexer.d.ts +11 -1
  195. package/dist/types/repositories/contractRepository.d.ts +30 -19
  196. package/dist/types/repositories/inMemory/contractRepository.d.ts +17 -0
  197. package/dist/types/repositories/inMemory/walletRepository.d.ts +26 -0
  198. package/dist/types/repositories/index.d.ts +7 -0
  199. package/dist/types/repositories/indexedDB/contractRepository.d.ts +21 -0
  200. package/dist/types/repositories/indexedDB/db.d.ts +56 -0
  201. package/dist/types/repositories/indexedDB/schema.d.ts +8 -0
  202. package/dist/types/repositories/indexedDB/walletRepository.d.ts +25 -0
  203. package/dist/types/repositories/indexedDB/websqlAdapter.d.ts +49 -0
  204. package/dist/types/repositories/migrations/contractRepositoryImpl.d.ts +24 -0
  205. package/dist/types/repositories/migrations/fromStorageAdapter.d.ts +19 -0
  206. package/dist/types/repositories/migrations/walletRepositoryImpl.d.ts +27 -0
  207. package/dist/types/repositories/walletRepository.d.ts +13 -24
  208. package/dist/types/script/base.d.ts +1 -0
  209. package/dist/types/script/delegate.d.ts +36 -0
  210. package/dist/types/storage/asyncStorage.d.ts +4 -0
  211. package/dist/types/storage/fileSystem.d.ts +3 -0
  212. package/dist/types/storage/inMemory.d.ts +3 -0
  213. package/dist/types/storage/index.d.ts +3 -0
  214. package/dist/types/storage/indexedDB.d.ts +3 -0
  215. package/dist/types/storage/localStorage.d.ts +3 -0
  216. package/dist/types/utils/arkTransaction.d.ts +6 -0
  217. package/dist/types/utils/txSizeEstimator.d.ts +12 -2
  218. package/dist/types/wallet/asset-manager.d.ts +78 -0
  219. package/dist/types/wallet/asset.d.ts +21 -0
  220. package/dist/types/wallet/batch.d.ts +1 -1
  221. package/dist/types/wallet/delegator.d.ts +24 -0
  222. package/dist/types/wallet/expo/background.d.ts +66 -0
  223. package/dist/types/wallet/expo/index.d.ts +4 -0
  224. package/dist/types/wallet/expo/wallet.d.ts +97 -0
  225. package/dist/types/wallet/index.d.ts +75 -2
  226. package/dist/types/wallet/onchain.d.ts +22 -1
  227. package/dist/types/wallet/serviceWorker/wallet-message-handler.d.ts +366 -0
  228. package/dist/types/wallet/serviceWorker/wallet.d.ts +20 -11
  229. package/dist/types/wallet/utils.d.ts +13 -1
  230. package/dist/types/wallet/validation.d.ts +24 -0
  231. package/dist/types/wallet/wallet.d.ts +111 -17
  232. package/dist/types/worker/browser/service-worker-manager.d.ts +21 -0
  233. package/dist/types/{wallet/serviceWorker → worker/browser}/utils.d.ts +2 -1
  234. package/dist/types/worker/expo/asyncStorageTaskQueue.d.ts +46 -0
  235. package/dist/types/worker/expo/index.d.ts +7 -0
  236. package/dist/types/worker/expo/processors/contractPollProcessor.d.ts +14 -0
  237. package/dist/types/worker/expo/processors/index.d.ts +1 -0
  238. package/dist/types/worker/expo/taskQueue.d.ts +50 -0
  239. package/dist/types/worker/expo/taskRunner.d.ts +42 -0
  240. package/dist/types/worker/messageBus.d.ts +109 -0
  241. package/package.json +71 -17
  242. package/dist/cjs/wallet/serviceWorker/request.js +0 -78
  243. package/dist/cjs/wallet/serviceWorker/response.js +0 -222
  244. package/dist/cjs/wallet/serviceWorker/worker.js +0 -655
  245. package/dist/esm/wallet/serviceWorker/request.js +0 -75
  246. package/dist/esm/wallet/serviceWorker/response.js +0 -219
  247. package/dist/esm/wallet/serviceWorker/worker.js +0 -651
  248. package/dist/types/wallet/serviceWorker/request.d.ts +0 -74
  249. package/dist/types/wallet/serviceWorker/response.d.ts +0 -123
  250. package/dist/types/wallet/serviceWorker/worker.d.ts +0 -53
@@ -0,0 +1,249 @@
1
+ import { validateMnemonic, mnemonicToSeedSync } from "@scure/bip39";
2
+ import { wordlist } from "@scure/bip39/wordlists/english.js";
3
+ import { pubECDSA, pubSchnorr } from "@scure/btc-signer/utils.js";
4
+ import { SigHash } from "@scure/btc-signer";
5
+ import { TreeSignerSession } from '../tree/signingSession.js';
6
+ import { schnorr, signAsync } from "@noble/secp256k1";
7
+ import { defaultFactory, scureBIP32 as BIP32, networks, scriptExpressions, } from "@kukks/bitcoin-descriptors";
8
+ const { expand } = defaultFactory;
9
+ const ALL_SIGHASH = Object.values(SigHash).filter((x) => typeof x === "number");
10
+ /**
11
+ * Detects the network from a descriptor string by checking for tpub (testnet)
12
+ * vs xpub (mainnet) key prefix.
13
+ * @internal
14
+ */
15
+ function detectNetwork(descriptor) {
16
+ return descriptor.includes("tpub") ? networks.testnet : networks.bitcoin;
17
+ }
18
+ function hasDescriptor(opts) {
19
+ return "descriptor" in opts && typeof opts.descriptor === "string";
20
+ }
21
+ /**
22
+ * Builds a BIP86 Taproot output descriptor from a seed and network flag.
23
+ * @internal
24
+ */
25
+ function buildDescriptor(seed, isMainnet) {
26
+ const network = isMainnet ? networks.bitcoin : networks.testnet;
27
+ const masterNode = BIP32.fromSeed(seed, network);
28
+ return scriptExpressions.trBIP32({
29
+ masterNode,
30
+ network,
31
+ account: 0,
32
+ change: 0,
33
+ index: 0,
34
+ });
35
+ }
36
+ /**
37
+ * Seed-based identity derived from a raw seed and an output descriptor.
38
+ *
39
+ * This is the recommended identity type for most applications. It uses
40
+ * standard BIP86 (Taproot) derivation by default and stores an output
41
+ * descriptor for interoperability with other wallets. The descriptor
42
+ * format is HD-ready, allowing future support for multiple addresses
43
+ * and change derivation.
44
+ *
45
+ * Prefer this (or {@link MnemonicIdentity}) over `SingleKey` for new
46
+ * integrations — `SingleKey` exists for backward compatibility with
47
+ * raw nsec-style keys.
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const seed = mnemonicToSeedSync(mnemonic);
52
+ *
53
+ * // Testnet (BIP86 path m/86'/1'/0'/0/0)
54
+ * const identity = SeedIdentity.fromSeed(seed, { isMainnet: false });
55
+ *
56
+ * // Mainnet (BIP86 path m/86'/0'/0'/0/0)
57
+ * const identity = SeedIdentity.fromSeed(seed, { isMainnet: true });
58
+ *
59
+ * // Custom descriptor
60
+ * const identity = SeedIdentity.fromSeed(seed, { descriptor });
61
+ * ```
62
+ */
63
+ export class SeedIdentity {
64
+ constructor(seed, descriptor) {
65
+ if (seed.length !== 64) {
66
+ throw new Error("Seed must be 64 bytes");
67
+ }
68
+ this.seed = seed;
69
+ this.descriptor = descriptor;
70
+ const network = detectNetwork(descriptor);
71
+ // Parse and validate the descriptor using the library
72
+ const expansion = expand({ descriptor, network });
73
+ const keyInfo = expansion.expansionMap?.["@0"];
74
+ if (!keyInfo?.originPath) {
75
+ throw new Error("Descriptor must include a key origin path");
76
+ }
77
+ // Verify the xpub in the descriptor matches our seed
78
+ const masterNode = BIP32.fromSeed(seed, network);
79
+ const accountNode = masterNode.derivePath(`m${keyInfo.originPath}`);
80
+ if (accountNode.neutered().toBase58() !== keyInfo.bip32?.toBase58()) {
81
+ throw new Error("xpub mismatch: derived key does not match descriptor");
82
+ }
83
+ // Derive the private key using the full path from the descriptor
84
+ if (!keyInfo.path) {
85
+ throw new Error("Descriptor must specify a full derivation path");
86
+ }
87
+ const derivedNode = masterNode.derivePath(keyInfo.path);
88
+ if (!derivedNode.privateKey) {
89
+ throw new Error("Failed to derive private key");
90
+ }
91
+ this.derivedKey = derivedNode.privateKey;
92
+ }
93
+ /**
94
+ * Creates a SeedIdentity from a raw 64-byte seed.
95
+ *
96
+ * Pass `{ isMainnet }` for default BIP86 derivation, or
97
+ * `{ descriptor }` for a custom derivation path.
98
+ *
99
+ * @param seed - 64-byte seed (typically from mnemonicToSeedSync)
100
+ * @param opts - Network selection or custom descriptor.
101
+ */
102
+ static fromSeed(seed, opts) {
103
+ const descriptor = hasDescriptor(opts)
104
+ ? opts.descriptor
105
+ : buildDescriptor(seed, opts.isMainnet);
106
+ return new SeedIdentity(seed, descriptor);
107
+ }
108
+ async xOnlyPublicKey() {
109
+ return pubSchnorr(this.derivedKey);
110
+ }
111
+ async compressedPublicKey() {
112
+ return pubECDSA(this.derivedKey, true);
113
+ }
114
+ async sign(tx, inputIndexes) {
115
+ const txCpy = tx.clone();
116
+ if (!inputIndexes) {
117
+ try {
118
+ if (!txCpy.sign(this.derivedKey, ALL_SIGHASH)) {
119
+ throw new Error("Failed to sign transaction");
120
+ }
121
+ }
122
+ catch (e) {
123
+ if (e instanceof Error &&
124
+ e.message.includes("No inputs signed")) {
125
+ // ignore
126
+ }
127
+ else {
128
+ throw e;
129
+ }
130
+ }
131
+ return txCpy;
132
+ }
133
+ for (const inputIndex of inputIndexes) {
134
+ if (!txCpy.signIdx(this.derivedKey, inputIndex, ALL_SIGHASH)) {
135
+ throw new Error(`Failed to sign input #${inputIndex}`);
136
+ }
137
+ }
138
+ return txCpy;
139
+ }
140
+ async signMessage(message, signatureType = "schnorr") {
141
+ if (signatureType === "ecdsa") {
142
+ return signAsync(message, this.derivedKey, { prehash: false });
143
+ }
144
+ return schnorr.signAsync(message, this.derivedKey);
145
+ }
146
+ signerSession() {
147
+ return TreeSignerSession.random();
148
+ }
149
+ /**
150
+ * Converts to a watch-only identity that cannot sign.
151
+ */
152
+ async toReadonly() {
153
+ return ReadonlyDescriptorIdentity.fromDescriptor(this.descriptor);
154
+ }
155
+ }
156
+ /**
157
+ * Mnemonic-based identity derived from a BIP39 phrase.
158
+ *
159
+ * This is the most user-friendly identity type — recommended for wallet
160
+ * applications where users manage their own backup phrase. Extends
161
+ * {@link SeedIdentity} with mnemonic validation and optional passphrase
162
+ * support.
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * const identity = MnemonicIdentity.fromMnemonic(
167
+ * 'abandon abandon abandon ...',
168
+ * { isMainnet: true, passphrase: 'secret' }
169
+ * );
170
+ * ```
171
+ */
172
+ export class MnemonicIdentity extends SeedIdentity {
173
+ constructor(seed, descriptor) {
174
+ super(seed, descriptor);
175
+ }
176
+ /**
177
+ * Creates a MnemonicIdentity from a BIP39 mnemonic phrase.
178
+ *
179
+ * Pass `{ isMainnet }` for default BIP86 derivation, or
180
+ * `{ descriptor }` for a custom derivation path.
181
+ *
182
+ * @param phrase - BIP39 mnemonic phrase (12 or 24 words)
183
+ * @param opts - Network selection or custom descriptor, plus optional passphrase
184
+ */
185
+ static fromMnemonic(phrase, opts) {
186
+ if (!validateMnemonic(phrase, wordlist)) {
187
+ throw new Error("Invalid mnemonic");
188
+ }
189
+ const passphrase = opts.passphrase;
190
+ const seed = mnemonicToSeedSync(phrase, passphrase);
191
+ const descriptor = hasDescriptor(opts)
192
+ ? opts.descriptor
193
+ : buildDescriptor(seed, opts.isMainnet);
194
+ return new MnemonicIdentity(seed, descriptor);
195
+ }
196
+ }
197
+ /**
198
+ * Watch-only identity from an output descriptor.
199
+ *
200
+ * Can derive public keys but cannot sign transactions. Use this for
201
+ * watch-only wallets or when sharing identity information without
202
+ * exposing private keys.
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * const descriptor = "tr([fingerprint/86'/0'/0']xpub.../0/0)";
207
+ * const readonly = ReadonlyDescriptorIdentity.fromDescriptor(descriptor);
208
+ * const pubKey = await readonly.xOnlyPublicKey();
209
+ * ```
210
+ */
211
+ export class ReadonlyDescriptorIdentity {
212
+ constructor(descriptor) {
213
+ this.descriptor = descriptor;
214
+ const network = detectNetwork(descriptor);
215
+ const expansion = expand({ descriptor, network });
216
+ const keyInfo = expansion.expansionMap?.["@0"];
217
+ if (!keyInfo?.pubkey) {
218
+ throw new Error("Failed to derive public key from descriptor");
219
+ }
220
+ // For taproot, the library returns 32-byte x-only pubkey
221
+ this.xOnlyPubKey = keyInfo.pubkey;
222
+ // Get 33-byte compressed key with correct parity from the bip32 node
223
+ if (keyInfo.bip32 && keyInfo.keyPath) {
224
+ // Strip leading "/" — the library's derivePath prepends "m/" itself
225
+ const relPath = keyInfo.keyPath.replace(/^\//, "");
226
+ this.compressedPubKey = keyInfo.bip32.derivePath(relPath).publicKey;
227
+ }
228
+ else if (keyInfo.bip32) {
229
+ this.compressedPubKey = keyInfo.bip32.publicKey;
230
+ }
231
+ else {
232
+ throw new Error("Cannot determine compressed public key parity from descriptor");
233
+ }
234
+ }
235
+ /**
236
+ * Creates a ReadonlyDescriptorIdentity from an output descriptor.
237
+ *
238
+ * @param descriptor - Taproot descriptor: tr([fingerprint/path']xpub.../child/path)
239
+ */
240
+ static fromDescriptor(descriptor) {
241
+ return new ReadonlyDescriptorIdentity(descriptor);
242
+ }
243
+ async xOnlyPublicKey() {
244
+ return this.xOnlyPubKey;
245
+ }
246
+ async compressedPublicKey() {
247
+ return this.compressedPubKey;
248
+ }
249
+ }
package/dist/esm/index.js CHANGED
@@ -1,25 +1,26 @@
1
1
  import { Transaction } from './utils/transaction.js';
2
2
  import { SingleKey, ReadonlySingleKey } from './identity/singleKey.js';
3
+ import { SeedIdentity, MnemonicIdentity, ReadonlyDescriptorIdentity, } from './identity/seedIdentity.js';
3
4
  import { ArkAddress } from './script/address.js';
4
5
  import { VHTLC } from './script/vhtlc.js';
5
6
  import { DefaultVtxo } from './script/default.js';
6
- import { VtxoScript, TapTreeCoder, } from './script/base.js';
7
+ import { DelegateVtxo } from './script/delegate.js';
8
+ import { MessageBus, } from './worker/messageBus.js';
9
+ import { VtxoScript, TapTreeCoder, getSequence, } from './script/base.js';
7
10
  import { TxType, isSpendable, isSubdust, isRecoverable, isExpired, } from './wallet/index.js';
8
11
  import { Batch } from './wallet/batch.js';
9
- import { Wallet, ReadonlyWallet, waitForIncomingFunds, getSequence, } from './wallet/wallet.js';
12
+ import { Wallet, ReadonlyWallet, waitForIncomingFunds, } from './wallet/wallet.js';
10
13
  import { TxTree } from './tree/txTree.js';
11
14
  import { Ramps } from './wallet/ramps.js';
12
15
  import { isVtxoExpiringSoon, VtxoManager } from './wallet/vtxo-manager.js';
13
16
  import { ServiceWorkerWallet, ServiceWorkerReadonlyWallet, } from './wallet/serviceWorker/wallet.js';
14
17
  import { OnchainWallet } from './wallet/onchain.js';
15
- import { setupServiceWorker } from './wallet/serviceWorker/utils.js';
16
- import { Worker } from './wallet/serviceWorker/worker.js';
17
- import { Request } from './wallet/serviceWorker/request.js';
18
- import { Response } from './wallet/serviceWorker/response.js';
18
+ import { setupServiceWorker } from './worker/browser/utils.js';
19
19
  import { ESPLORA_URL, EsploraProvider, } from './providers/onchain.js';
20
20
  import { RestArkProvider, SettlementEventType, } from './providers/ark.js';
21
+ import { RestDelegatorProvider, } from './providers/delegator.js';
21
22
  import { CLTVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CSVMultisigTapscript, decodeTapscript, MultisigTapscript, } from './script/tapscript.js';
22
- import { hasBoardingTxExpired, buildOffchainTx, verifyTapscriptSignatures, combineTapscriptSigs, } from './utils/arkTransaction.js';
23
+ import { hasBoardingTxExpired, buildOffchainTx, verifyTapscriptSignatures, combineTapscriptSigs, isValidArkAddress, } from './utils/arkTransaction.js';
23
24
  import { VtxoTaprootTree, ConditionWitness, getArkPsbtFields, setArkPsbtField, ArkPsbtFieldKey, ArkPsbtFieldKeyType, CosignerPublicKey, VtxoTreeExpiry, } from './utils/unknownFields.js';
24
25
  import { Intent } from './intent/index.js';
25
26
  import { ArkNote } from './arknote/index.js';
@@ -27,35 +28,42 @@ import { networks } from './networks.js';
27
28
  import { RestIndexerProvider, IndexerTxType, ChainTxType, } from './providers/indexer.js';
28
29
  import { P2A } from './utils/anchor.js';
29
30
  import { Unroll } from './wallet/unroll.js';
30
- import { WalletRepositoryImpl } from './repositories/walletRepository.js';
31
- import { ContractRepositoryImpl } from './repositories/contractRepository.js';
32
31
  import { ArkError, maybeArkError } from './providers/errors.js';
33
32
  import { validateVtxoTxGraph, validateConnectorsTxGraph, } from './tree/validation.js';
34
33
  import { buildForfeitTx } from './forfeit.js';
34
+ import { IndexedDBWalletRepository, IndexedDBContractRepository, InMemoryWalletRepository, InMemoryContractRepository, MIGRATION_KEY, migrateWalletRepository, requiresMigration, getMigrationStatus, rollbackMigration, WalletRepositoryImpl, ContractRepositoryImpl, } from './repositories/index.js';
35
+ import { DelegatorManagerImpl } from './wallet/delegator.js';
35
36
  export * from './arkfee/index.js';
37
+ export * as asset from './asset/index.js';
38
+ // Contracts
39
+ import { ContractManager, ContractWatcher, contractHandlers, DefaultContractHandler, DelegateContractHandler, VHTLCContractHandler, encodeArkContract, decodeArkContract, contractFromArkContract, contractFromArkContractWithAddress, isArkContract, } from './contracts/index.js';
40
+ import { closeDatabase, openDatabase } from './db/manager.js';
41
+ import { WalletMessageHandler } from './wallet/serviceWorker/wallet-message-handler.js';
36
42
  export {
37
43
  // Wallets
38
- Wallet, ReadonlyWallet, SingleKey, ReadonlySingleKey, OnchainWallet, Ramps, VtxoManager,
44
+ Wallet, ReadonlyWallet, SingleKey, ReadonlySingleKey, SeedIdentity, MnemonicIdentity, ReadonlyDescriptorIdentity, OnchainWallet, Ramps, VtxoManager, DelegatorManagerImpl, RestDelegatorProvider,
39
45
  // Providers
40
46
  ESPLORA_URL, EsploraProvider, RestArkProvider, RestIndexerProvider,
41
47
  // Script-related
42
- ArkAddress, DefaultVtxo, VtxoScript, VHTLC,
48
+ ArkAddress, DefaultVtxo, DelegateVtxo, VtxoScript, VHTLC,
43
49
  // Enums
44
50
  TxType, IndexerTxType, ChainTxType, SettlementEventType,
45
51
  // Service Worker
46
- setupServiceWorker, Worker, ServiceWorkerWallet, ServiceWorkerReadonlyWallet, Request, Response,
52
+ setupServiceWorker, MessageBus, WalletMessageHandler, ServiceWorkerWallet, ServiceWorkerReadonlyWallet,
47
53
  // Tapscript
48
54
  decodeTapscript, MultisigTapscript, CSVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CLTVMultisigTapscript, TapTreeCoder,
49
55
  // Ark PSBT fields
50
56
  ArkPsbtFieldKey, ArkPsbtFieldKeyType, setArkPsbtField, getArkPsbtFields, CosignerPublicKey, VtxoTreeExpiry, VtxoTaprootTree, ConditionWitness,
51
57
  // Utils
52
- buildOffchainTx, verifyTapscriptSignatures, waitForIncomingFunds, hasBoardingTxExpired, combineTapscriptSigs, isVtxoExpiringSoon,
58
+ buildOffchainTx, verifyTapscriptSignatures, waitForIncomingFunds, hasBoardingTxExpired, combineTapscriptSigs, isVtxoExpiringSoon, isValidArkAddress,
53
59
  // Arknote
54
60
  ArkNote,
55
61
  // Network
56
62
  networks,
63
+ // DB
64
+ closeDatabase, openDatabase,
57
65
  // Repositories
58
- WalletRepositoryImpl, ContractRepositoryImpl,
66
+ IndexedDBWalletRepository, IndexedDBContractRepository, InMemoryWalletRepository, InMemoryContractRepository, MIGRATION_KEY, migrateWalletRepository, requiresMigration, getMigrationStatus, rollbackMigration, WalletRepositoryImpl, ContractRepositoryImpl,
59
67
  // Intent proof
60
68
  Intent,
61
69
  // TxTree
@@ -65,4 +73,6 @@ P2A, Unroll, Transaction,
65
73
  // Errors
66
74
  ArkError, maybeArkError,
67
75
  // Batch session
68
- Batch, validateVtxoTxGraph, validateConnectorsTxGraph, buildForfeitTx, isRecoverable, isSpendable, isSubdust, isExpired, getSequence, };
76
+ Batch, validateVtxoTxGraph, validateConnectorsTxGraph, buildForfeitTx, isRecoverable, isSpendable, isSubdust, isExpired, getSequence,
77
+ // Contracts
78
+ ContractManager, ContractWatcher, contractHandlers, DefaultContractHandler, DelegateContractHandler, VHTLCContractHandler, encodeArkContract, decodeArkContract, contractFromArkContract, contractFromArkContractWithAddress, isArkContract, };
@@ -1,6 +1,9 @@
1
1
  import { OP, Script, SigHash } from "@scure/btc-signer";
2
2
  import { schnorr } from "@noble/curves/secp256k1.js";
3
3
  import { Transaction } from '../utils/transaction.js';
4
+ import { ConditionWitness, VtxoTaprootTree } from '../utils/unknownFields.js';
5
+ import { hex } from "@scure/base";
6
+ import { getSequence, VtxoScript } from '../script/base.js';
4
7
  /**
5
8
  * Intent proof implementation for Bitcoin message signing.
6
9
  *
@@ -38,12 +41,13 @@ export var Intent;
38
41
  * @param outputs - Optional array of transaction outputs
39
42
  * @returns An unsigned Intent proof transaction
40
43
  */
41
- function create(message, inputs, outputs = []) {
44
+ function create(message, ins, outputs = []) {
42
45
  if (typeof message !== "string") {
43
46
  message = encodeMessage(message);
44
47
  }
45
- if (inputs.length == 0)
48
+ if (ins.length == 0)
46
49
  throw new Error("intent proof requires at least one input");
50
+ const inputs = ins.map(prepareCoinAsIntentProofInput);
47
51
  if (!validateInputs(inputs))
48
52
  throw new Error("invalid inputs");
49
53
  if (!validateOutputs(outputs))
@@ -202,3 +206,25 @@ function craftToSignTx(toSpend, inputs, outputs) {
202
206
  function hashMessage(message) {
203
207
  return schnorr.utils.taggedHash(TAG_INTENT_PROOF, new TextEncoder().encode(message));
204
208
  }
209
+ function prepareCoinAsIntentProofInput(coin) {
210
+ if (!("tapTree" in coin)) {
211
+ return coin;
212
+ }
213
+ const vtxoScript = VtxoScript.decode(coin.tapTree);
214
+ const sequence = getSequence(coin.intentTapLeafScript);
215
+ const unknown = [VtxoTaprootTree.encode(coin.tapTree)];
216
+ if (coin.extraWitness) {
217
+ unknown.push(ConditionWitness.encode(coin.extraWitness));
218
+ }
219
+ return {
220
+ txid: hex.decode(coin.txid),
221
+ index: coin.vout,
222
+ witnessUtxo: {
223
+ amount: BigInt(coin.value),
224
+ script: vtxoScript.pkScript,
225
+ },
226
+ sequence,
227
+ tapLeafScript: [coin.intentTapLeafScript],
228
+ unknown,
229
+ };
230
+ }
@@ -12,6 +12,7 @@ export var SettlementEventType;
12
12
  SettlementEventType["TreeNonces"] = "tree_nonces";
13
13
  SettlementEventType["TreeTx"] = "tree_tx";
14
14
  SettlementEventType["TreeSignature"] = "tree_signature";
15
+ SettlementEventType["StreamStarted"] = "stream_started";
15
16
  })(SettlementEventType || (SettlementEventType = {}));
16
17
  /**
17
18
  * REST-based Ark provider implementation.
@@ -420,6 +421,12 @@ export class RestArkProvider {
420
421
  signature: data.treeSignature.signature,
421
422
  };
422
423
  }
424
+ if (data.streamStarted) {
425
+ return {
426
+ type: SettlementEventType.StreamStarted,
427
+ id: data.streamStarted.id,
428
+ };
429
+ }
423
430
  // Skip heartbeat events
424
431
  if (data.heartbeat) {
425
432
  return null;
@@ -0,0 +1,62 @@
1
+ import { Intent } from '../intent/index.js';
2
+ /**
3
+ * REST-based Delegator provider implementation.
4
+ * @example
5
+ * ```typescript
6
+ * const provider = new RestDelegatorProvider('https://delegator.example.com');
7
+ * const info = await provider.getDelegateInfo();
8
+ * await provider.delegate(intent, forfeitTxs);
9
+ * ```
10
+ */
11
+ export class RestDelegatorProvider {
12
+ constructor(url) {
13
+ this.url = url;
14
+ }
15
+ async delegate(intent, forfeitTxs, options) {
16
+ const url = `${this.url}/v1/delegate`;
17
+ const response = await fetch(url, {
18
+ method: "POST",
19
+ headers: {
20
+ "Content-Type": "application/json",
21
+ },
22
+ body: JSON.stringify({
23
+ intent: {
24
+ message: Intent.encodeMessage(intent.message),
25
+ proof: intent.proof,
26
+ },
27
+ forfeit_txs: forfeitTxs,
28
+ reject_replace: options?.rejectReplace ?? false,
29
+ }),
30
+ });
31
+ if (!response.ok) {
32
+ const errorText = await response.text();
33
+ throw new Error(`Failed to delegate: ${errorText}`);
34
+ }
35
+ }
36
+ async getDelegateInfo() {
37
+ const url = `${this.url}/v1/delegator/info`;
38
+ const response = await fetch(url);
39
+ if (!response.ok) {
40
+ const errorText = await response.text();
41
+ throw new Error(`Failed to get delegate info: ${errorText}`);
42
+ }
43
+ const data = await response.json();
44
+ if (!isDelegateInfo(data)) {
45
+ throw new Error("Invalid delegate info");
46
+ }
47
+ return data;
48
+ }
49
+ }
50
+ function isDelegateInfo(data) {
51
+ return (!!data &&
52
+ typeof data === "object" &&
53
+ "pubkey" in data &&
54
+ "fee" in data &&
55
+ "delegatorAddress" in data &&
56
+ typeof data.pubkey === "string" &&
57
+ typeof data.fee === "string" &&
58
+ typeof data.delegatorAddress === "string" &&
59
+ data.pubkey !== "" &&
60
+ data.fee !== "" &&
61
+ data.delegatorAddress !== "");
62
+ }
@@ -9,6 +9,7 @@ function convertVtxo(vtxo) {
9
9
  value: Number(vtxo.amount),
10
10
  status: {
11
11
  confirmed: !vtxo.isSwept && !vtxo.isPreconfirmed,
12
+ isLeaf: !vtxo.isPreconfirmed,
12
13
  },
13
14
  virtualStatus: {
14
15
  state: vtxo.isSwept
@@ -27,6 +28,10 @@ function convertVtxo(vtxo) {
27
28
  createdAt: new Date(Number(vtxo.createdAt) * 1000),
28
29
  isUnrolled: vtxo.isUnrolled,
29
30
  isSpent: vtxo.isSpent,
31
+ assets: vtxo.assets?.map((a) => ({
32
+ assetId: a.assetId,
33
+ amount: Number(a.amount),
34
+ })),
30
35
  };
31
36
  }
32
37
  /**
@@ -1,5 +1,7 @@
1
+ import { hex } from "@scure/base";
1
2
  import { isFetchTimeoutError } from './ark.js';
2
3
  import { eventSourceIterator } from './utils.js';
4
+ import { MetadataList } from '../asset/index.js';
3
5
  export var IndexerTxType;
4
6
  (function (IndexerTxType) {
5
7
  IndexerTxType[IndexerTxType["INDEXER_TX_TYPE_UNSPECIFIED"] = 0] = "INDEXER_TX_TYPE_UNSPECIFIED";
@@ -298,6 +300,26 @@ export class RestIndexerProvider {
298
300
  page: data.page,
299
301
  };
300
302
  }
303
+ async getAssetDetails(assetId) {
304
+ const url = `${this.serverUrl}/v1/indexer/asset/${encodeURIComponent(assetId)}`;
305
+ const res = await fetch(url);
306
+ if (!res.ok) {
307
+ throw new Error(`Failed to fetch asset details: ${res.statusText}`);
308
+ }
309
+ const data = await res.json();
310
+ if (!Response.isGetAssetResponse(data)) {
311
+ throw new Error("Invalid get asset response");
312
+ }
313
+ const metadata = data.metadata?.length
314
+ ? parseAssetMetadata(data.metadata)
315
+ : undefined;
316
+ return {
317
+ assetId: data.assetId ?? assetId,
318
+ supply: Number(data.supply ?? 0),
319
+ metadata,
320
+ controlAssetId: data.controlAsset || undefined,
321
+ };
322
+ }
301
323
  async subscribeForScripts(scripts, subscriptionId) {
302
324
  const url = `${this.serverUrl}/v1/indexer/script/subscribe`;
303
325
  const res = await fetch(url, {
@@ -331,6 +353,29 @@ export class RestIndexerProvider {
331
353
  }
332
354
  }
333
355
  }
356
+ function parseAssetMetadata(metadata) {
357
+ const metadataList = MetadataList.fromString(metadata);
358
+ const out = {};
359
+ const decoder = new TextDecoder();
360
+ for (const { key, value } of metadataList.items) {
361
+ const keyString = decoder.decode(key);
362
+ switch (keyString) {
363
+ case "decimals":
364
+ const n = Number(decoder.decode(value));
365
+ out[keyString] = Number.isFinite(n) ? n : hex.encode(value);
366
+ break;
367
+ case "name":
368
+ case "ticker":
369
+ case "icon":
370
+ out[keyString] = decoder.decode(value);
371
+ break;
372
+ default:
373
+ out[keyString] = hex.encode(value);
374
+ break;
375
+ }
376
+ }
377
+ return out;
378
+ }
334
379
  function convertVtxo(vtxo) {
335
380
  return {
336
381
  txid: vtxo.outpoint.txid,
@@ -357,6 +402,10 @@ function convertVtxo(vtxo) {
357
402
  createdAt: new Date(Number(vtxo.createdAt) * 1000),
358
403
  isUnrolled: vtxo.isUnrolled,
359
404
  isSpent: vtxo.isSpent,
405
+ assets: vtxo.assets?.map((a) => ({
406
+ assetId: a.assetId,
407
+ amount: Number(a.amount),
408
+ })),
360
409
  };
361
410
  }
362
411
  // Unexported namespace for type guards only
@@ -431,6 +480,12 @@ var Response;
431
480
  return Array.isArray(data) && data.every(isTxid);
432
481
  }
433
482
  Response.isTxidArray = isTxidArray;
483
+ function isVtxoAsset(data) {
484
+ return (typeof data === "object" &&
485
+ data !== null &&
486
+ typeof data.assetId === "string" &&
487
+ typeof data.amount === "string");
488
+ }
434
489
  function isVtxo(data) {
435
490
  return (typeof data === "object" &&
436
491
  isOutpoint(data.outpoint) &&
@@ -446,7 +501,9 @@ var Response;
446
501
  (!data.settledBy || typeof data.settledBy === "string") &&
447
502
  (!data.arkTxid || typeof data.arkTxid === "string") &&
448
503
  Array.isArray(data.commitmentTxids) &&
449
- data.commitmentTxids.every(isTxid));
504
+ data.commitmentTxids.every(isTxid) &&
505
+ (data.assets === undefined ||
506
+ (Array.isArray(data.assets) && data.assets.every(isVtxoAsset))));
450
507
  }
451
508
  function isPageResponse(data) {
452
509
  return (typeof data === "object" &&
@@ -515,4 +572,14 @@ var Response;
515
572
  (!data.page || isPageResponse(data.page)));
516
573
  }
517
574
  Response.isVtxosResponse = isVtxosResponse;
575
+ function isGetAssetResponse(data) {
576
+ return (typeof data === "object" &&
577
+ data !== null &&
578
+ typeof data.assetId === "string" &&
579
+ typeof data.supply === "string" &&
580
+ (data.controlAsset === undefined ||
581
+ typeof data.controlAsset === "string") &&
582
+ (data.metadata === undefined || typeof data.metadata === "string"));
583
+ }
584
+ Response.isGetAssetResponse = isGetAssetResponse;
518
585
  })(Response || (Response = {}));
@@ -231,14 +231,14 @@ export class EsploraProvider {
231
231
  function isValidBlocksTip(tip) {
232
232
  return (Array.isArray(tip) &&
233
233
  tip.every((t) => {
234
- t &&
234
+ return (t &&
235
235
  typeof t === "object" &&
236
236
  typeof t.id === "string" &&
237
237
  t.id.length > 0 &&
238
238
  typeof t.height === "number" &&
239
239
  t.height >= 0 &&
240
240
  typeof t.mediantime === "number" &&
241
- t.mediantime > 0;
241
+ t.mediantime > 0);
242
242
  }));
243
243
  }
244
244
  const isExplorerTransaction = (tx) => {
@@ -14,6 +14,7 @@ export async function* eventSourceIterator(eventSource) {
14
14
  };
15
15
  const errorHandler = () => {
16
16
  const error = new Error("EventSource error");
17
+ error.name = "EventSourceError";
17
18
  if (errorResolve) {
18
19
  errorResolve(error);
19
20
  errorResolve = null;