@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.
- package/README.md +483 -54
- package/dist/cjs/adapters/expo-db.js +35 -0
- package/dist/cjs/asset/assetGroup.js +141 -0
- package/dist/cjs/asset/assetId.js +88 -0
- package/dist/cjs/asset/assetInput.js +204 -0
- package/dist/cjs/asset/assetOutput.js +159 -0
- package/dist/cjs/asset/assetRef.js +82 -0
- package/dist/cjs/asset/index.js +24 -0
- package/dist/cjs/asset/metadata.js +172 -0
- package/dist/cjs/asset/packet.js +164 -0
- package/dist/cjs/asset/types.js +25 -0
- package/dist/cjs/asset/utils.js +105 -0
- package/dist/cjs/contracts/arkcontract.js +148 -0
- package/dist/cjs/contracts/contractManager.js +436 -0
- package/dist/cjs/contracts/contractWatcher.js +567 -0
- package/dist/cjs/contracts/handlers/default.js +85 -0
- package/dist/cjs/contracts/handlers/delegate.js +89 -0
- package/dist/cjs/contracts/handlers/helpers.js +105 -0
- package/dist/cjs/contracts/handlers/index.js +19 -0
- package/dist/cjs/contracts/handlers/registry.js +89 -0
- package/dist/cjs/contracts/handlers/vhtlc.js +193 -0
- package/dist/cjs/contracts/index.js +41 -0
- package/dist/cjs/contracts/types.js +2 -0
- package/dist/cjs/db/manager.js +97 -0
- package/dist/cjs/forfeit.js +12 -8
- package/dist/cjs/identity/index.js +1 -0
- package/dist/cjs/identity/seedIdentity.js +255 -0
- package/dist/cjs/index.js +70 -14
- package/dist/cjs/intent/index.js +28 -2
- package/dist/cjs/providers/ark.js +7 -0
- package/dist/cjs/providers/delegator.js +66 -0
- package/dist/cjs/providers/expoIndexer.js +5 -0
- package/dist/cjs/providers/indexer.js +68 -1
- package/dist/cjs/providers/onchain.js +2 -2
- package/dist/cjs/providers/utils.js +1 -0
- package/dist/cjs/repositories/contractRepository.js +0 -103
- package/dist/cjs/repositories/inMemory/contractRepository.js +55 -0
- package/dist/cjs/repositories/inMemory/walletRepository.js +80 -0
- package/dist/cjs/repositories/index.js +16 -0
- package/dist/cjs/repositories/indexedDB/contractRepository.js +187 -0
- package/dist/cjs/repositories/indexedDB/db.js +57 -0
- package/dist/cjs/repositories/indexedDB/schema.js +159 -0
- package/dist/cjs/repositories/indexedDB/walletRepository.js +338 -0
- package/dist/cjs/repositories/indexedDB/websqlAdapter.js +144 -0
- package/dist/cjs/repositories/migrations/contractRepositoryImpl.js +127 -0
- package/dist/cjs/repositories/migrations/fromStorageAdapter.js +66 -0
- package/dist/cjs/repositories/migrations/walletRepositoryImpl.js +180 -0
- package/dist/cjs/repositories/walletRepository.js +0 -169
- package/dist/cjs/script/base.js +54 -0
- package/dist/cjs/script/delegate.js +49 -0
- package/dist/cjs/storage/asyncStorage.js +4 -1
- package/dist/cjs/storage/fileSystem.js +3 -0
- package/dist/cjs/storage/inMemory.js +3 -0
- package/dist/cjs/storage/indexedDB.js +5 -1
- package/dist/cjs/storage/localStorage.js +3 -0
- package/dist/cjs/utils/arkTransaction.js +16 -0
- package/dist/cjs/utils/transactionHistory.js +50 -0
- package/dist/cjs/utils/txSizeEstimator.js +39 -14
- package/dist/cjs/wallet/asset-manager.js +338 -0
- package/dist/cjs/wallet/asset.js +117 -0
- package/dist/cjs/wallet/batch.js +1 -1
- package/dist/cjs/wallet/delegator.js +235 -0
- package/dist/cjs/wallet/expo/background.js +133 -0
- package/dist/cjs/wallet/expo/index.js +9 -0
- package/dist/cjs/wallet/expo/wallet.js +231 -0
- package/dist/cjs/wallet/onchain.js +57 -12
- package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +568 -0
- package/dist/cjs/wallet/serviceWorker/wallet.js +383 -102
- package/dist/cjs/wallet/unroll.js +7 -2
- package/dist/cjs/wallet/utils.js +60 -0
- package/dist/cjs/wallet/validation.js +151 -0
- package/dist/cjs/wallet/vtxo-manager.js +1 -1
- package/dist/cjs/wallet/wallet.js +702 -260
- package/dist/cjs/worker/browser/service-worker-manager.js +82 -0
- package/dist/cjs/{wallet/serviceWorker → worker/browser}/utils.js +2 -1
- package/dist/cjs/worker/expo/asyncStorageTaskQueue.js +78 -0
- package/dist/cjs/worker/expo/index.js +12 -0
- package/dist/cjs/worker/expo/processors/contractPollProcessor.js +61 -0
- package/dist/cjs/worker/expo/processors/index.js +6 -0
- package/dist/cjs/worker/expo/taskQueue.js +41 -0
- package/dist/cjs/worker/expo/taskRunner.js +57 -0
- package/dist/cjs/worker/messageBus.js +252 -0
- package/dist/esm/adapters/expo-db.js +27 -0
- package/dist/esm/asset/assetGroup.js +137 -0
- package/dist/esm/asset/assetId.js +84 -0
- package/dist/esm/asset/assetInput.js +199 -0
- package/dist/esm/asset/assetOutput.js +154 -0
- package/dist/esm/asset/assetRef.js +78 -0
- package/dist/esm/asset/index.js +8 -0
- package/dist/esm/asset/metadata.js +167 -0
- package/dist/esm/asset/packet.js +159 -0
- package/dist/esm/asset/types.js +22 -0
- package/dist/esm/asset/utils.js +99 -0
- package/dist/esm/contracts/arkcontract.js +141 -0
- package/dist/esm/contracts/contractManager.js +432 -0
- package/dist/esm/contracts/contractWatcher.js +563 -0
- package/dist/esm/contracts/handlers/default.js +82 -0
- package/dist/esm/contracts/handlers/delegate.js +86 -0
- package/dist/esm/contracts/handlers/helpers.js +66 -0
- package/dist/esm/contracts/handlers/index.js +12 -0
- package/dist/esm/contracts/handlers/registry.js +86 -0
- package/dist/esm/contracts/handlers/vhtlc.js +190 -0
- package/dist/esm/contracts/index.js +13 -0
- package/dist/esm/contracts/types.js +1 -0
- package/dist/esm/db/manager.js +92 -0
- package/dist/esm/forfeit.js +11 -8
- package/dist/esm/identity/index.js +1 -0
- package/dist/esm/identity/seedIdentity.js +249 -0
- package/dist/esm/index.js +25 -15
- package/dist/esm/intent/index.js +28 -2
- package/dist/esm/providers/ark.js +7 -0
- package/dist/esm/providers/delegator.js +62 -0
- package/dist/esm/providers/expoIndexer.js +5 -0
- package/dist/esm/providers/indexer.js +68 -1
- package/dist/esm/providers/onchain.js +2 -2
- package/dist/esm/providers/utils.js +1 -0
- package/dist/esm/repositories/contractRepository.js +1 -101
- package/dist/esm/repositories/inMemory/contractRepository.js +51 -0
- package/dist/esm/repositories/inMemory/walletRepository.js +76 -0
- package/dist/esm/repositories/index.js +8 -0
- package/dist/esm/repositories/indexedDB/contractRepository.js +183 -0
- package/dist/esm/repositories/indexedDB/db.js +42 -0
- package/dist/esm/repositories/indexedDB/schema.js +155 -0
- package/dist/esm/repositories/indexedDB/walletRepository.js +334 -0
- package/dist/esm/repositories/indexedDB/websqlAdapter.js +138 -0
- package/dist/esm/repositories/migrations/contractRepositoryImpl.js +121 -0
- package/dist/esm/repositories/migrations/fromStorageAdapter.js +58 -0
- package/dist/esm/repositories/migrations/walletRepositoryImpl.js +176 -0
- package/dist/esm/repositories/walletRepository.js +1 -167
- package/dist/esm/script/base.js +21 -1
- package/dist/esm/script/delegate.js +46 -0
- package/dist/esm/storage/asyncStorage.js +4 -1
- package/dist/esm/storage/fileSystem.js +3 -0
- package/dist/esm/storage/inMemory.js +3 -0
- package/dist/esm/storage/indexedDB.js +5 -1
- package/dist/esm/storage/localStorage.js +3 -0
- package/dist/esm/utils/arkTransaction.js +15 -0
- package/dist/esm/utils/transactionHistory.js +50 -0
- package/dist/esm/utils/txSizeEstimator.js +39 -14
- package/dist/esm/wallet/asset-manager.js +333 -0
- package/dist/esm/wallet/asset.js +111 -0
- package/dist/esm/wallet/batch.js +1 -1
- package/dist/esm/wallet/delegator.js +231 -0
- package/dist/esm/wallet/expo/background.js +128 -0
- package/dist/esm/wallet/expo/index.js +2 -0
- package/dist/esm/wallet/expo/wallet.js +194 -0
- package/dist/esm/wallet/onchain.js +57 -12
- package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +564 -0
- package/dist/esm/wallet/serviceWorker/wallet.js +382 -101
- package/dist/esm/wallet/unroll.js +7 -2
- package/dist/esm/wallet/utils.js +55 -0
- package/dist/esm/wallet/validation.js +139 -0
- package/dist/esm/wallet/vtxo-manager.js +1 -1
- package/dist/esm/wallet/wallet.js +704 -229
- package/dist/esm/worker/browser/service-worker-manager.js +76 -0
- package/dist/esm/{wallet/serviceWorker → worker/browser}/utils.js +2 -1
- package/dist/esm/worker/expo/asyncStorageTaskQueue.js +74 -0
- package/dist/esm/worker/expo/index.js +4 -0
- package/dist/esm/worker/expo/processors/contractPollProcessor.js +58 -0
- package/dist/esm/worker/expo/processors/index.js +1 -0
- package/dist/esm/worker/expo/taskQueue.js +37 -0
- package/dist/esm/worker/expo/taskRunner.js +54 -0
- package/dist/esm/worker/messageBus.js +248 -0
- package/dist/types/adapters/expo-db.d.ts +7 -0
- package/dist/types/asset/assetGroup.d.ts +28 -0
- package/dist/types/asset/assetId.d.ts +19 -0
- package/dist/types/asset/assetInput.d.ts +46 -0
- package/dist/types/asset/assetOutput.d.ts +39 -0
- package/dist/types/asset/assetRef.d.ts +25 -0
- package/dist/types/asset/index.d.ts +8 -0
- package/dist/types/asset/metadata.d.ts +37 -0
- package/dist/types/asset/packet.d.ts +27 -0
- package/dist/types/asset/types.d.ts +18 -0
- package/dist/types/asset/utils.d.ts +21 -0
- package/dist/types/contracts/arkcontract.d.ts +101 -0
- package/dist/types/contracts/contractManager.d.ts +331 -0
- package/dist/types/contracts/contractWatcher.d.ts +192 -0
- package/dist/types/contracts/handlers/default.d.ts +19 -0
- package/dist/types/contracts/handlers/delegate.d.ts +21 -0
- package/dist/types/contracts/handlers/helpers.d.ts +18 -0
- package/dist/types/contracts/handlers/index.d.ts +7 -0
- package/dist/types/contracts/handlers/registry.d.ts +65 -0
- package/dist/types/contracts/handlers/vhtlc.d.ts +32 -0
- package/dist/types/contracts/index.d.ts +14 -0
- package/dist/types/contracts/types.d.ts +222 -0
- package/dist/types/db/manager.d.ts +22 -0
- package/dist/types/forfeit.d.ts +2 -1
- package/dist/types/identity/index.d.ts +1 -0
- package/dist/types/identity/seedIdentity.d.ts +128 -0
- package/dist/types/index.d.ts +21 -12
- package/dist/types/intent/index.d.ts +2 -1
- package/dist/types/providers/ark.d.ts +11 -2
- package/dist/types/providers/delegator.d.ts +29 -0
- package/dist/types/providers/indexer.d.ts +11 -1
- package/dist/types/repositories/contractRepository.d.ts +30 -19
- package/dist/types/repositories/inMemory/contractRepository.d.ts +17 -0
- package/dist/types/repositories/inMemory/walletRepository.d.ts +26 -0
- package/dist/types/repositories/index.d.ts +7 -0
- package/dist/types/repositories/indexedDB/contractRepository.d.ts +21 -0
- package/dist/types/repositories/indexedDB/db.d.ts +56 -0
- package/dist/types/repositories/indexedDB/schema.d.ts +8 -0
- package/dist/types/repositories/indexedDB/walletRepository.d.ts +25 -0
- package/dist/types/repositories/indexedDB/websqlAdapter.d.ts +49 -0
- package/dist/types/repositories/migrations/contractRepositoryImpl.d.ts +24 -0
- package/dist/types/repositories/migrations/fromStorageAdapter.d.ts +19 -0
- package/dist/types/repositories/migrations/walletRepositoryImpl.d.ts +27 -0
- package/dist/types/repositories/walletRepository.d.ts +13 -24
- package/dist/types/script/base.d.ts +1 -0
- package/dist/types/script/delegate.d.ts +36 -0
- package/dist/types/storage/asyncStorage.d.ts +4 -0
- package/dist/types/storage/fileSystem.d.ts +3 -0
- package/dist/types/storage/inMemory.d.ts +3 -0
- package/dist/types/storage/index.d.ts +3 -0
- package/dist/types/storage/indexedDB.d.ts +3 -0
- package/dist/types/storage/localStorage.d.ts +3 -0
- package/dist/types/utils/arkTransaction.d.ts +6 -0
- package/dist/types/utils/txSizeEstimator.d.ts +12 -2
- package/dist/types/wallet/asset-manager.d.ts +78 -0
- package/dist/types/wallet/asset.d.ts +21 -0
- package/dist/types/wallet/batch.d.ts +1 -1
- package/dist/types/wallet/delegator.d.ts +24 -0
- package/dist/types/wallet/expo/background.d.ts +66 -0
- package/dist/types/wallet/expo/index.d.ts +4 -0
- package/dist/types/wallet/expo/wallet.d.ts +97 -0
- package/dist/types/wallet/index.d.ts +75 -2
- package/dist/types/wallet/onchain.d.ts +22 -1
- package/dist/types/wallet/serviceWorker/wallet-message-handler.d.ts +366 -0
- package/dist/types/wallet/serviceWorker/wallet.d.ts +20 -11
- package/dist/types/wallet/utils.d.ts +13 -1
- package/dist/types/wallet/validation.d.ts +24 -0
- package/dist/types/wallet/wallet.d.ts +111 -17
- package/dist/types/worker/browser/service-worker-manager.d.ts +21 -0
- package/dist/types/{wallet/serviceWorker → worker/browser}/utils.d.ts +2 -1
- package/dist/types/worker/expo/asyncStorageTaskQueue.d.ts +46 -0
- package/dist/types/worker/expo/index.d.ts +7 -0
- package/dist/types/worker/expo/processors/contractPollProcessor.d.ts +14 -0
- package/dist/types/worker/expo/processors/index.d.ts +1 -0
- package/dist/types/worker/expo/taskQueue.d.ts +50 -0
- package/dist/types/worker/expo/taskRunner.d.ts +42 -0
- package/dist/types/worker/messageBus.d.ts +109 -0
- package/package.json +71 -17
- package/dist/cjs/wallet/serviceWorker/request.js +0 -78
- package/dist/cjs/wallet/serviceWorker/response.js +0 -222
- package/dist/cjs/wallet/serviceWorker/worker.js +0 -655
- package/dist/esm/wallet/serviceWorker/request.js +0 -75
- package/dist/esm/wallet/serviceWorker/response.js +0 -219
- package/dist/esm/wallet/serviceWorker/worker.js +0 -651
- package/dist/types/wallet/serviceWorker/request.d.ts +0 -74
- package/dist/types/wallet/serviceWorker/response.d.ts +0 -123
- 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 {
|
|
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,
|
|
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 './
|
|
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,
|
|
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, };
|
package/dist/esm/intent/index.js
CHANGED
|
@@ -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,
|
|
44
|
+
function create(message, ins, outputs = []) {
|
|
42
45
|
if (typeof message !== "string") {
|
|
43
46
|
message = encodeMessage(message);
|
|
44
47
|
}
|
|
45
|
-
if (
|
|
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) => {
|