@arkade-os/sdk 0.4.21 → 0.4.23
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 +95 -12
- package/dist/cjs/contracts/arkcontract.js +2 -1
- package/dist/cjs/contracts/contractWatcher.js +16 -18
- package/dist/cjs/identity/descriptor.js +75 -4
- package/dist/cjs/identity/hdCapableIdentity.js +2 -0
- package/dist/cjs/identity/seedIdentity.js +225 -103
- package/dist/cjs/identity/serialize.js +5 -0
- package/dist/cjs/identity/staticDescriptorProvider.js +1 -1
- package/dist/cjs/index.js +12 -3
- package/dist/cjs/providers/electrum.js +285 -79
- package/dist/cjs/providers/expoIndexer.js +1 -1
- package/dist/cjs/providers/indexer.js +2 -2
- package/dist/cjs/providers/onchain.js +9 -3
- package/dist/cjs/repositories/migrations/walletRepositoryImpl.js +6 -2
- package/dist/cjs/repositories/realm/walletRepository.js +2 -2
- package/dist/cjs/repositories/serialization.js +34 -1
- package/dist/cjs/repositories/sqlite/walletRepository.js +4 -2
- package/dist/cjs/script/address.js +2 -1
- package/dist/cjs/utils/transactionHistory.js +4 -4
- package/dist/cjs/wallet/asset-manager.js +18 -18
- package/dist/cjs/wallet/asset.js +10 -8
- package/dist/cjs/wallet/delegator.js +29 -20
- package/dist/cjs/wallet/hdDescriptorProvider.js +159 -0
- package/dist/cjs/wallet/index.js +5 -1
- package/dist/cjs/wallet/onchain.js +2 -1
- package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +4 -2
- package/dist/cjs/wallet/serviceWorker/wallet.js +5 -4
- package/dist/cjs/wallet/validation.js +2 -3
- package/dist/cjs/wallet/vtxo-manager.js +7 -5
- package/dist/cjs/wallet/wallet.js +13 -14
- package/dist/esm/contracts/arkcontract.js +2 -1
- package/dist/esm/contracts/contractWatcher.js +14 -16
- package/dist/esm/identity/descriptor.js +74 -5
- package/dist/esm/identity/hdCapableIdentity.js +1 -0
- package/dist/esm/identity/seedIdentity.js +225 -103
- package/dist/esm/identity/serialize.js +5 -0
- package/dist/esm/identity/staticDescriptorProvider.js +1 -1
- package/dist/esm/index.js +7 -4
- package/dist/esm/providers/electrum.js +284 -78
- package/dist/esm/providers/expoIndexer.js +1 -1
- package/dist/esm/providers/indexer.js +2 -2
- package/dist/esm/providers/onchain.js +9 -3
- package/dist/esm/repositories/migrations/walletRepositoryImpl.js +6 -2
- package/dist/esm/repositories/realm/walletRepository.js +3 -3
- package/dist/esm/repositories/serialization.js +27 -0
- package/dist/esm/repositories/sqlite/walletRepository.js +5 -3
- package/dist/esm/script/address.js +2 -1
- package/dist/esm/utils/transactionHistory.js +4 -4
- package/dist/esm/wallet/asset-manager.js +18 -18
- package/dist/esm/wallet/asset.js +10 -8
- package/dist/esm/wallet/delegator.js +29 -20
- package/dist/esm/wallet/hdDescriptorProvider.js +155 -0
- package/dist/esm/wallet/index.js +4 -0
- package/dist/esm/wallet/onchain.js +2 -1
- package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +4 -2
- package/dist/esm/wallet/serviceWorker/wallet.js +5 -4
- package/dist/esm/wallet/validation.js +2 -3
- package/dist/esm/wallet/vtxo-manager.js +7 -5
- package/dist/esm/wallet/wallet.js +12 -14
- package/dist/types/contracts/arkcontract.d.ts +1 -1
- package/dist/types/contracts/types.d.ts +5 -5
- package/dist/types/identity/descriptor.d.ts +26 -0
- package/dist/types/identity/descriptorProvider.d.ts +11 -4
- package/dist/types/identity/hdCapableIdentity.d.ts +44 -0
- package/dist/types/identity/index.d.ts +1 -0
- package/dist/types/identity/seedIdentity.d.ts +113 -29
- package/dist/types/identity/serialize.d.ts +12 -0
- package/dist/types/identity/staticDescriptorProvider.d.ts +1 -1
- package/dist/types/index.d.ts +6 -3
- package/dist/types/providers/electrum.d.ts +115 -15
- package/dist/types/providers/onchain.d.ts +6 -0
- package/dist/types/repositories/serialization.d.ts +26 -2
- package/dist/types/script/address.d.ts +1 -1
- package/dist/types/wallet/delegator.d.ts +8 -3
- package/dist/types/wallet/hdDescriptorProvider.d.ts +93 -0
- package/dist/types/wallet/index.d.ts +19 -10
- package/dist/types/wallet/onchain.d.ts +1 -1
- package/dist/types/wallet/serviceWorker/wallet.d.ts +1 -1
- package/dist/types/wallet/wallet.d.ts +4 -1
- package/package.json +4 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Wallet = exports.ReadonlyWallet = void 0;
|
|
3
|
+
exports.Wallet = exports.ReadonlyWallet = exports.getArkadeServerUrl = void 0;
|
|
4
4
|
exports.selectVirtualCoins = selectVirtualCoins;
|
|
5
5
|
exports.waitForIncomingFunds = waitForIncomingFunds;
|
|
6
6
|
const base_1 = require("@scure/base");
|
|
@@ -39,6 +39,8 @@ const contractManager_1 = require("../contracts/contractManager");
|
|
|
39
39
|
const handlers_1 = require("../contracts/handlers");
|
|
40
40
|
const helpers_1 = require("../contracts/handlers/helpers");
|
|
41
41
|
const syncCursors_1 = require("../utils/syncCursors");
|
|
42
|
+
const getArkadeServerUrl = ({ arkServerUrl, }) => arkServerUrl || _1.DEFAULT_ARKADE_SERVER_URL;
|
|
43
|
+
exports.getArkadeServerUrl = getArkadeServerUrl;
|
|
42
44
|
// Historical unilateral exit delay for mainnet (~7 days in seconds).
|
|
43
45
|
// Kept so existing wallets can still discover and spend VTXOs sent to the
|
|
44
46
|
// legacy address after arkd starts advertising a different delay.
|
|
@@ -125,10 +127,7 @@ class ReadonlyWallet {
|
|
|
125
127
|
// Use provided arkProvider instance or create a new one from arkServerUrl
|
|
126
128
|
const arkProvider = config.arkProvider ||
|
|
127
129
|
(() => {
|
|
128
|
-
|
|
129
|
-
throw new Error("Either arkProvider or arkServerUrl must be provided");
|
|
130
|
-
}
|
|
131
|
-
return new ark_1.RestArkProvider(config.arkServerUrl);
|
|
130
|
+
return new ark_1.RestArkProvider((0, exports.getArkadeServerUrl)(config));
|
|
132
131
|
})();
|
|
133
132
|
// Extract arkServerUrl from provider if not explicitly provided
|
|
134
133
|
const arkServerUrl = config.arkServerUrl || arkProvider.serverUrl;
|
|
@@ -307,7 +306,7 @@ class ReadonlyWallet {
|
|
|
307
306
|
continue;
|
|
308
307
|
if (vtxo.assets) {
|
|
309
308
|
for (const a of vtxo.assets) {
|
|
310
|
-
const current = assetBalances.get(a.assetId) ??
|
|
309
|
+
const current = assetBalances.get(a.assetId) ?? 0n;
|
|
311
310
|
assetBalances.set(a.assetId, current + a.amount);
|
|
312
311
|
}
|
|
313
312
|
}
|
|
@@ -1129,12 +1128,12 @@ class Wallet extends ReadonlyWallet {
|
|
|
1129
1128
|
for (const [, assets] of assetInputs) {
|
|
1130
1129
|
for (const asset of assets) {
|
|
1131
1130
|
const existing = allAssets.get(asset.assetId) ?? 0n;
|
|
1132
|
-
allAssets.set(asset.assetId, existing +
|
|
1131
|
+
allAssets.set(asset.assetId, existing + asset.amount);
|
|
1133
1132
|
}
|
|
1134
1133
|
}
|
|
1135
1134
|
outputAssets = [];
|
|
1136
1135
|
for (const [assetId, amount] of allAssets) {
|
|
1137
|
-
outputAssets.push({ assetId, amount
|
|
1136
|
+
outputAssets.push({ assetId, amount });
|
|
1138
1137
|
}
|
|
1139
1138
|
}
|
|
1140
1139
|
const recipients = params.outputs.map((output, i) => ({
|
|
@@ -1569,7 +1568,7 @@ class Wallet extends ReadonlyWallet {
|
|
|
1569
1568
|
* const txid = await wallet.send({
|
|
1570
1569
|
* address: 'ark1q...',
|
|
1571
1570
|
* amount: 1000, // (optional, default to dust) btc amount to send to the output
|
|
1572
|
-
* assets: [{ assetId: 'abc123...', amount:
|
|
1571
|
+
* assets: [{ assetId: 'abc123...', amount: 50n }] // (optional) list of assets to send
|
|
1573
1572
|
* });
|
|
1574
1573
|
* ```
|
|
1575
1574
|
*/
|
|
@@ -1600,7 +1599,7 @@ class Wallet extends ReadonlyWallet {
|
|
|
1600
1599
|
continue;
|
|
1601
1600
|
}
|
|
1602
1601
|
for (const receiverAsset of recipient.assets) {
|
|
1603
|
-
let amountToSelect =
|
|
1602
|
+
let amountToSelect = receiverAsset.amount;
|
|
1604
1603
|
// check if existing change covers the needed amount
|
|
1605
1604
|
const existingChange = assetChanges.get(receiverAsset.assetId) ?? 0n;
|
|
1606
1605
|
if (existingChange >= amountToSelect) {
|
|
@@ -1627,7 +1626,7 @@ class Wallet extends ReadonlyWallet {
|
|
|
1627
1626
|
continue;
|
|
1628
1627
|
}
|
|
1629
1628
|
const existing = assetChanges.get(a.assetId) ?? 0n;
|
|
1630
|
-
assetChanges.set(a.assetId, existing +
|
|
1629
|
+
assetChanges.set(a.assetId, existing + a.amount);
|
|
1631
1630
|
}
|
|
1632
1631
|
}
|
|
1633
1632
|
}
|
|
@@ -1647,7 +1646,7 @@ class Wallet extends ReadonlyWallet {
|
|
|
1647
1646
|
if (coin.assets) {
|
|
1648
1647
|
for (const asset of coin.assets) {
|
|
1649
1648
|
const existing = assetChanges.get(asset.assetId) ?? 0n;
|
|
1650
|
-
assetChanges.set(asset.assetId, existing +
|
|
1649
|
+
assetChanges.set(asset.assetId, existing + asset.amount);
|
|
1651
1650
|
}
|
|
1652
1651
|
}
|
|
1653
1652
|
}
|
|
@@ -1669,7 +1668,7 @@ class Wallet extends ReadonlyWallet {
|
|
|
1669
1668
|
if (coin.assets) {
|
|
1670
1669
|
for (const asset of coin.assets) {
|
|
1671
1670
|
const existing = assetChanges.get(asset.assetId) ?? 0n;
|
|
1672
|
-
assetChanges.set(asset.assetId, existing +
|
|
1671
|
+
assetChanges.set(asset.assetId, existing + asset.amount);
|
|
1673
1672
|
}
|
|
1674
1673
|
}
|
|
1675
1674
|
}
|
|
@@ -1684,7 +1683,7 @@ class Wallet extends ReadonlyWallet {
|
|
|
1684
1683
|
const changeAssets = [];
|
|
1685
1684
|
for (const [assetId, amount] of assetChanges) {
|
|
1686
1685
|
if (amount > 0n) {
|
|
1687
|
-
changeAssets.push({ assetId, amount
|
|
1686
|
+
changeAssets.push({ assetId, amount });
|
|
1688
1687
|
}
|
|
1689
1688
|
}
|
|
1690
1689
|
changeIndex = outputs.length;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { hex } from "@scure/base";
|
|
2
2
|
import { contractHandlers } from './handlers/index.js';
|
|
3
|
+
import { DEFAULT_ARKADE_HRP } from '../wallet/index.js';
|
|
3
4
|
/**
|
|
4
5
|
* Prefix for arkcontract strings.
|
|
5
6
|
*/
|
|
@@ -115,7 +116,7 @@ export function contractFromArkContract(encoded, options = {}) {
|
|
|
115
116
|
* @param options - Additional options
|
|
116
117
|
* @returns A complete Contract object
|
|
117
118
|
*/
|
|
118
|
-
export function contractFromArkContractWithAddress(encoded, serverPubKey, addressPrefix, options = {}) {
|
|
119
|
+
export function contractFromArkContractWithAddress(encoded, serverPubKey, addressPrefix = DEFAULT_ARKADE_HRP, options = {}) {
|
|
119
120
|
const parsed = decodeArkContract(encoded);
|
|
120
121
|
const handler = contractHandlers.getOrThrow(parsed.type);
|
|
121
122
|
const params = parsed.data;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { extendVirtualCoinForContract } from '../wallet/utils.js';
|
|
1
2
|
import { isEventSourceError } from '../providers/utils.js';
|
|
2
3
|
/**
|
|
3
4
|
* Watches multiple contracts for virtual output state changes with resilient connection handling.
|
|
@@ -550,18 +551,22 @@ export class ContractWatcher {
|
|
|
550
551
|
const state = this.contracts.get(contractScript);
|
|
551
552
|
if (!state)
|
|
552
553
|
return;
|
|
554
|
+
const extended = [];
|
|
555
|
+
for (const v of vtxos) {
|
|
556
|
+
try {
|
|
557
|
+
const extendedVtxo = extendVirtualCoinForContract(v, state.contract);
|
|
558
|
+
extended.push({ ...extendedVtxo, contractScript });
|
|
559
|
+
}
|
|
560
|
+
catch {
|
|
561
|
+
console.warn("failed to extend vtxo: ", v);
|
|
562
|
+
extended.push({ ...v, contractScript });
|
|
563
|
+
}
|
|
564
|
+
}
|
|
553
565
|
switch (eventType) {
|
|
554
566
|
case "vtxo_received":
|
|
555
567
|
this.eventCallback({
|
|
556
568
|
type: "vtxo_received",
|
|
557
|
-
vtxos:
|
|
558
|
-
...v,
|
|
559
|
-
contractScript,
|
|
560
|
-
// These fields may not be available from basic VirtualCoin
|
|
561
|
-
forfeitTapLeafScript: undefined,
|
|
562
|
-
intentTapLeafScript: undefined,
|
|
563
|
-
tapTree: undefined,
|
|
564
|
-
})),
|
|
569
|
+
vtxos: extended,
|
|
565
570
|
contractScript,
|
|
566
571
|
contract: state.contract,
|
|
567
572
|
timestamp,
|
|
@@ -570,14 +575,7 @@ export class ContractWatcher {
|
|
|
570
575
|
case "vtxo_spent":
|
|
571
576
|
this.eventCallback({
|
|
572
577
|
type: "vtxo_spent",
|
|
573
|
-
vtxos:
|
|
574
|
-
...v,
|
|
575
|
-
contractScript,
|
|
576
|
-
// These fields may not be available from basic VirtualCoin
|
|
577
|
-
forfeitTapLeafScript: undefined,
|
|
578
|
-
intentTapLeafScript: undefined,
|
|
579
|
-
tapTree: undefined,
|
|
580
|
-
})),
|
|
578
|
+
vtxos: extended,
|
|
581
579
|
contractScript,
|
|
582
580
|
contract: state.contract,
|
|
583
581
|
timestamp,
|
|
@@ -1,7 +1,72 @@
|
|
|
1
|
-
import { expand, networks
|
|
1
|
+
import { expand, networks } from "@bitcoinerlab/descriptors-scure";
|
|
2
2
|
import { hex } from "@scure/base";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* True iff `descriptor` is a Bitcoin mainnet descriptor (xpub-prefixed
|
|
5
|
+
* BIP32 key).
|
|
6
|
+
*
|
|
7
|
+
* Note: testnet, signet, regtest, mutinynet, and other non-mainnet
|
|
8
|
+
* networks all share the same `tpub` BIP32 version bytes — they cannot
|
|
9
|
+
* be distinguished from one another at the descriptor level. Callers
|
|
10
|
+
* that need a `Network` constants object for `expand()` pick
|
|
11
|
+
* `networks.bitcoin` vs `networks.testnet` themselves; callers that
|
|
12
|
+
* need the *actual* network the wallet is on must track that
|
|
13
|
+
* out-of-band.
|
|
14
|
+
*/
|
|
15
|
+
export function isMainnetDescriptor(descriptor) {
|
|
16
|
+
return !descriptor.includes("tpub");
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Shared "does `candidate` belong to the identity backed by
|
|
20
|
+
* `ourDescriptor`?" predicate.
|
|
21
|
+
*
|
|
22
|
+
* - HD descriptors (expanding to a `bip32` key) match by account xpub
|
|
23
|
+
* on both sides — index-agnostic, so a wildcard template and any
|
|
24
|
+
* concrete index under it all collapse to the same xpub.
|
|
25
|
+
* - Bare `tr(pubkey)` candidates fall back to comparing the candidate
|
|
26
|
+
* pubkey against `ourXOnlyPubkey` (the cached pubkey on the identity
|
|
27
|
+
* side, since pulling it from `ourDescriptor` would require an index
|
|
28
|
+
* substitution the caller already performed).
|
|
29
|
+
*/
|
|
30
|
+
export function descriptorIsOurs(candidate, ourDescriptor, ourXOnlyPubkey) {
|
|
31
|
+
if (!isDescriptor(candidate))
|
|
32
|
+
return false;
|
|
33
|
+
try {
|
|
34
|
+
const candidateInfo = expand({
|
|
35
|
+
descriptor: candidate,
|
|
36
|
+
network: isMainnetDescriptor(candidate)
|
|
37
|
+
? networks.bitcoin
|
|
38
|
+
: networks.testnet,
|
|
39
|
+
}).expansionMap?.["@0"];
|
|
40
|
+
if (!candidateInfo)
|
|
41
|
+
return false;
|
|
42
|
+
if (candidateInfo.bip32) {
|
|
43
|
+
const ourBip32 = expand({
|
|
44
|
+
descriptor: ourDescriptor,
|
|
45
|
+
network: isMainnetDescriptor(ourDescriptor)
|
|
46
|
+
? networks.bitcoin
|
|
47
|
+
: networks.testnet,
|
|
48
|
+
}).expansionMap?.["@0"]?.bip32;
|
|
49
|
+
if (!ourBip32)
|
|
50
|
+
return false;
|
|
51
|
+
return ourBip32.toBase58() === candidateInfo.bip32.toBase58();
|
|
52
|
+
}
|
|
53
|
+
if (candidateInfo.pubkey) {
|
|
54
|
+
// For tr() the library hands back a 32-byte x-only key, but
|
|
55
|
+
// strip a leading parity byte defensively so a 33-byte
|
|
56
|
+
// compressed key (mismatched length) doesn't silently
|
|
57
|
+
// false-negative against our 32-byte x-only side.
|
|
58
|
+
const candidatePub = candidateInfo.pubkey.length === 33
|
|
59
|
+
? candidateInfo.pubkey.subarray(1)
|
|
60
|
+
: candidateInfo.pubkey;
|
|
61
|
+
if (candidatePub.length !== ourXOnlyPubkey.length)
|
|
62
|
+
return false;
|
|
63
|
+
return hex.encode(candidatePub) === hex.encode(ourXOnlyPubkey);
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
5
70
|
}
|
|
6
71
|
/**
|
|
7
72
|
* Check if a string is a descriptor of the shape `tr(...)`.
|
|
@@ -43,7 +108,9 @@ export function extractPubKey(descriptor) {
|
|
|
43
108
|
if (!isDescriptor(descriptor)) {
|
|
44
109
|
return descriptor;
|
|
45
110
|
}
|
|
46
|
-
const network =
|
|
111
|
+
const network = isMainnetDescriptor(descriptor)
|
|
112
|
+
? networks.bitcoin
|
|
113
|
+
: networks.testnet;
|
|
47
114
|
const expansion = expand({ descriptor, network });
|
|
48
115
|
if (!expansion.expansionMap) {
|
|
49
116
|
throw new Error("Cannot extract pubkey from descriptor: expansion failed.");
|
|
@@ -70,7 +137,9 @@ export function parseHDDescriptor(descriptor) {
|
|
|
70
137
|
}
|
|
71
138
|
let expansion;
|
|
72
139
|
try {
|
|
73
|
-
const network =
|
|
140
|
+
const network = isMainnetDescriptor(descriptor)
|
|
141
|
+
? networks.bitcoin
|
|
142
|
+
: networks.testnet;
|
|
74
143
|
expansion = expand({ descriptor, network });
|
|
75
144
|
}
|
|
76
145
|
catch {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|