@arkade-os/sdk 0.4.14 → 0.4.16
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 +287 -215
- package/dist/cjs/arkfee/estimator.js +1 -1
- package/dist/cjs/arkfee/types.js +2 -1
- package/dist/cjs/arknote/index.js +43 -4
- package/dist/cjs/bip322/index.js +1 -1
- package/dist/cjs/contracts/arkcontract.js +1 -1
- package/dist/cjs/contracts/contractManager.js +40 -24
- package/dist/cjs/contracts/contractWatcher.js +29 -22
- package/dist/cjs/contracts/handlers/default.js +1 -1
- package/dist/cjs/contracts/handlers/delegate.js +1 -1
- package/dist/cjs/contracts/handlers/helpers.js +25 -1
- package/dist/cjs/contracts/handlers/vhtlc.js +2 -4
- package/dist/cjs/extension/asset/assetGroup.js +92 -5
- package/dist/cjs/extension/asset/assetId.js +67 -3
- package/dist/cjs/extension/asset/assetInput.js +18 -0
- package/dist/cjs/extension/asset/assetOutput.js +15 -0
- package/dist/cjs/extension/asset/assetRef.js +66 -0
- package/dist/cjs/extension/asset/metadata.js +15 -0
- package/dist/cjs/extension/asset/packet.js +4 -1
- package/dist/cjs/extension/index.js +1 -1
- package/dist/cjs/forfeit.js +14 -0
- package/dist/cjs/identity/index.js +6 -0
- package/dist/cjs/identity/seedIdentity.js +5 -5
- package/dist/cjs/identity/singleKey.js +4 -0
- package/dist/cjs/index.js +5 -3
- package/dist/cjs/intent/index.js +28 -12
- package/dist/cjs/providers/ark.js +3 -2
- package/dist/cjs/providers/delegator.js +20 -1
- package/dist/cjs/providers/expoArk.js +2 -2
- package/dist/cjs/providers/indexer.js +2 -2
- package/dist/cjs/providers/onchain.js +2 -1
- package/dist/cjs/repositories/realm/schemas.js +2 -2
- package/dist/cjs/repositories/realm/types.js +1 -1
- package/dist/cjs/script/address.js +37 -6
- package/dist/cjs/script/base.js +70 -1
- package/dist/cjs/script/default.js +3 -0
- package/dist/cjs/script/delegate.js +4 -0
- package/dist/cjs/script/tapscript.js +25 -4
- package/dist/cjs/script/vhtlc.js +35 -27
- package/dist/cjs/storage/fileSystem.js +1 -1
- package/dist/cjs/storage/inMemory.js +1 -1
- package/dist/cjs/storage/indexedDB.js +1 -1
- package/dist/cjs/storage/localStorage.js +1 -1
- package/dist/cjs/tree/validation.js +1 -1
- package/dist/cjs/utils/arkTransaction.js +5 -5
- package/dist/cjs/utils/bip21.js +16 -3
- package/dist/cjs/utils/syncCursors.js +4 -4
- package/dist/cjs/utils/transaction.js +1 -1
- package/dist/cjs/utils/transactionHistory.js +11 -11
- package/dist/cjs/utils/unknownFields.js +3 -3
- package/dist/cjs/wallet/asset-manager.js +4 -4
- package/dist/cjs/wallet/batch.js +5 -5
- package/dist/cjs/wallet/delegator.js +9 -8
- package/dist/cjs/wallet/expo/background.js +3 -3
- package/dist/cjs/wallet/expo/wallet.js +7 -7
- package/dist/cjs/wallet/index.js +43 -0
- package/dist/cjs/wallet/onchain.js +43 -5
- package/dist/cjs/wallet/ramps.js +44 -14
- package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +22 -22
- package/dist/cjs/wallet/serviceWorker/wallet.js +28 -24
- package/dist/cjs/wallet/unroll.js +12 -8
- package/dist/cjs/wallet/utils.js +1 -1
- package/dist/cjs/wallet/vtxo-manager.js +123 -82
- package/dist/cjs/wallet/wallet.js +231 -98
- package/dist/cjs/worker/expo/asyncStorageTaskQueue.js +1 -1
- package/dist/cjs/worker/expo/processors/contractPollProcessor.js +2 -2
- package/dist/cjs/worker/expo/taskRunner.js +3 -3
- package/dist/cjs/worker/messageBus.js +3 -0
- package/dist/esm/arkfee/estimator.js +1 -1
- package/dist/esm/arkfee/types.js +2 -1
- package/dist/esm/arknote/index.js +43 -4
- package/dist/esm/bip322/index.js +1 -1
- package/dist/esm/contracts/arkcontract.js +1 -1
- package/dist/esm/contracts/contractManager.js +40 -24
- package/dist/esm/contracts/contractWatcher.js +29 -22
- package/dist/esm/contracts/handlers/default.js +1 -1
- package/dist/esm/contracts/handlers/delegate.js +1 -1
- package/dist/esm/contracts/handlers/helpers.js +24 -1
- package/dist/esm/contracts/handlers/vhtlc.js +3 -5
- package/dist/esm/extension/asset/assetGroup.js +92 -5
- package/dist/esm/extension/asset/assetId.js +67 -3
- package/dist/esm/extension/asset/assetInput.js +18 -0
- package/dist/esm/extension/asset/assetOutput.js +15 -0
- package/dist/esm/extension/asset/assetRef.js +66 -0
- package/dist/esm/extension/asset/metadata.js +15 -0
- package/dist/esm/extension/asset/packet.js +4 -1
- package/dist/esm/extension/index.js +1 -1
- package/dist/esm/forfeit.js +14 -0
- package/dist/esm/identity/index.js +5 -0
- package/dist/esm/identity/seedIdentity.js +5 -5
- package/dist/esm/identity/singleKey.js +4 -0
- package/dist/esm/index.js +3 -2
- package/dist/esm/intent/index.js +28 -12
- package/dist/esm/providers/ark.js +3 -2
- package/dist/esm/providers/delegator.js +20 -1
- package/dist/esm/providers/expoArk.js +2 -2
- package/dist/esm/providers/indexer.js +2 -2
- package/dist/esm/providers/onchain.js +2 -1
- package/dist/esm/repositories/realm/schemas.js +2 -2
- package/dist/esm/repositories/realm/types.js +1 -1
- package/dist/esm/script/address.js +37 -6
- package/dist/esm/script/base.js +70 -1
- package/dist/esm/script/default.js +3 -0
- package/dist/esm/script/delegate.js +4 -0
- package/dist/esm/script/tapscript.js +25 -4
- package/dist/esm/script/vhtlc.js +35 -27
- package/dist/esm/storage/fileSystem.js +1 -1
- package/dist/esm/storage/inMemory.js +1 -1
- package/dist/esm/storage/indexedDB.js +1 -1
- package/dist/esm/storage/localStorage.js +1 -1
- package/dist/esm/tree/validation.js +1 -1
- package/dist/esm/utils/arkTransaction.js +5 -5
- package/dist/esm/utils/bip21.js +16 -3
- package/dist/esm/utils/syncCursors.js +4 -4
- package/dist/esm/utils/transaction.js +1 -1
- package/dist/esm/utils/transactionHistory.js +11 -11
- package/dist/esm/utils/unknownFields.js +3 -3
- package/dist/esm/wallet/asset-manager.js +4 -4
- package/dist/esm/wallet/batch.js +5 -5
- package/dist/esm/wallet/delegator.js +9 -8
- package/dist/esm/wallet/expo/background.js +3 -3
- package/dist/esm/wallet/expo/wallet.js +7 -7
- package/dist/esm/wallet/index.js +43 -0
- package/dist/esm/wallet/onchain.js +43 -5
- package/dist/esm/wallet/ramps.js +44 -14
- package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +22 -22
- package/dist/esm/wallet/serviceWorker/wallet.js +28 -24
- package/dist/esm/wallet/unroll.js +12 -8
- package/dist/esm/wallet/utils.js +1 -1
- package/dist/esm/wallet/vtxo-manager.js +122 -81
- package/dist/esm/wallet/wallet.js +232 -99
- package/dist/esm/worker/expo/asyncStorageTaskQueue.js +1 -1
- package/dist/esm/worker/expo/processors/contractPollProcessor.js +2 -2
- package/dist/esm/worker/expo/taskRunner.js +3 -3
- package/dist/esm/worker/messageBus.js +3 -0
- package/dist/types/arkfee/estimator.d.ts +1 -1
- package/dist/types/arkfee/types.d.ts +2 -1
- package/dist/types/arknote/index.d.ts +44 -4
- package/dist/types/bip322/index.d.ts +1 -1
- package/dist/types/contracts/arkcontract.d.ts +1 -1
- package/dist/types/contracts/contractManager.d.ts +40 -63
- package/dist/types/contracts/contractWatcher.d.ts +39 -18
- package/dist/types/contracts/handlers/default.d.ts +1 -1
- package/dist/types/contracts/handlers/delegate.d.ts +1 -1
- package/dist/types/contracts/handlers/helpers.d.ts +11 -1
- package/dist/types/contracts/types.d.ts +36 -26
- package/dist/types/extension/asset/assetGroup.d.ts +92 -1
- package/dist/types/extension/asset/assetId.d.ts +67 -3
- package/dist/types/extension/asset/assetInput.d.ts +18 -0
- package/dist/types/extension/asset/assetOutput.d.ts +15 -0
- package/dist/types/extension/asset/assetRef.d.ts +66 -0
- package/dist/types/extension/asset/metadata.d.ts +15 -0
- package/dist/types/extension/asset/packet.d.ts +4 -1
- package/dist/types/extension/index.d.ts +1 -1
- package/dist/types/forfeit.d.ts +14 -0
- package/dist/types/identity/index.d.ts +36 -0
- package/dist/types/identity/seedIdentity.d.ts +10 -8
- package/dist/types/identity/singleKey.d.ts +4 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/intent/index.d.ts +19 -6
- package/dist/types/providers/ark.d.ts +40 -2
- package/dist/types/providers/delegator.d.ts +54 -1
- package/dist/types/providers/expoArk.d.ts +2 -2
- package/dist/types/providers/indexer.d.ts +105 -2
- package/dist/types/providers/onchain.d.ts +62 -1
- package/dist/types/repositories/realm/schemas.d.ts +2 -2
- package/dist/types/repositories/realm/types.d.ts +2 -2
- package/dist/types/repositories/walletRepository.d.ts +16 -0
- package/dist/types/script/address.d.ts +35 -2
- package/dist/types/script/base.d.ts +66 -1
- package/dist/types/script/default.d.ts +3 -0
- package/dist/types/script/delegate.d.ts +4 -0
- package/dist/types/script/tapscript.d.ts +17 -2
- package/dist/types/script/vhtlc.d.ts +35 -27
- package/dist/types/storage/fileSystem.d.ts +1 -1
- package/dist/types/storage/inMemory.d.ts +1 -1
- package/dist/types/storage/index.d.ts +1 -1
- package/dist/types/storage/indexedDB.d.ts +1 -1
- package/dist/types/storage/localStorage.d.ts +1 -1
- package/dist/types/utils/arkTransaction.d.ts +3 -3
- package/dist/types/utils/bip21.d.ts +17 -0
- package/dist/types/utils/syncCursors.d.ts +4 -4
- package/dist/types/utils/transaction.d.ts +1 -1
- package/dist/types/utils/transactionHistory.d.ts +3 -3
- package/dist/types/utils/unknownFields.d.ts +5 -5
- package/dist/types/wallet/asset-manager.d.ts +3 -3
- package/dist/types/wallet/batch.d.ts +27 -7
- package/dist/types/wallet/delegator.d.ts +10 -0
- package/dist/types/wallet/expo/background.d.ts +4 -4
- package/dist/types/wallet/expo/wallet.d.ts +10 -10
- package/dist/types/wallet/index.d.ts +457 -25
- package/dist/types/wallet/onchain.d.ts +42 -4
- package/dist/types/wallet/ramps.d.ts +40 -10
- package/dist/types/wallet/serviceWorker/wallet-message-handler.d.ts +4 -4
- package/dist/types/wallet/serviceWorker/wallet.d.ts +71 -33
- package/dist/types/wallet/unroll.d.ts +8 -6
- package/dist/types/wallet/vtxo-manager.d.ts +146 -93
- package/dist/types/wallet/wallet.d.ts +91 -33
- package/dist/types/worker/expo/asyncStorageTaskQueue.d.ts +1 -1
- package/dist/types/worker/expo/processors/contractPollProcessor.d.ts +1 -1
- package/dist/types/worker/expo/taskRunner.d.ts +6 -6
- package/dist/types/worker/messageBus.d.ts +5 -3
- package/package.json +18 -10
package/dist/cjs/script/base.js
CHANGED
|
@@ -49,18 +49,35 @@ function scriptFromTapLeafScript(leaf) {
|
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
51
|
* VtxoScript is a script that contains a list of tapleaf scripts.
|
|
52
|
-
* It is used to create
|
|
52
|
+
* It is used to create virtual output scripts.
|
|
53
|
+
*
|
|
54
|
+
* @see ArkAddress
|
|
53
55
|
*
|
|
54
56
|
* @example
|
|
55
57
|
* ```typescript
|
|
56
58
|
* const vtxoScript = new VtxoScript([new Uint8Array(32), new Uint8Array(32)]);
|
|
59
|
+
* ```
|
|
57
60
|
*/
|
|
58
61
|
class VtxoScript {
|
|
62
|
+
/**
|
|
63
|
+
* Decode a virtual output script from an encoded TapTree.
|
|
64
|
+
*
|
|
65
|
+
* @param tapTree - Encoded TapTree bytes
|
|
66
|
+
* @returns Decoded virtual output script
|
|
67
|
+
* @throws Error if the TapTree cannot be decoded into a valid script set
|
|
68
|
+
* @see encode
|
|
69
|
+
*/
|
|
59
70
|
static decode(tapTree) {
|
|
60
71
|
const leaves = exports.TapTreeCoder.decode(tapTree);
|
|
61
72
|
const scripts = leaves.map((leaf) => leaf.script);
|
|
62
73
|
return new VtxoScript(scripts);
|
|
63
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Create a virtual output script from its tapleaf scripts.
|
|
77
|
+
*
|
|
78
|
+
* @param scripts - Raw tapscript bytes for each leaf
|
|
79
|
+
* @throws Error if the provided leaves cannot produce a valid Taproot tree
|
|
80
|
+
*/
|
|
64
81
|
constructor(scripts) {
|
|
65
82
|
this.scripts = scripts;
|
|
66
83
|
// reverse the scripts if the number of scripts is odd
|
|
@@ -81,6 +98,12 @@ class VtxoScript {
|
|
|
81
98
|
this.leaves = payment.tapLeafScript;
|
|
82
99
|
this.tweakedPublicKey = payment.tweakedPubkey;
|
|
83
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Encode the virtual output script to a TapTree byte representation.
|
|
103
|
+
*
|
|
104
|
+
* @returns Encoded TapTree bytes
|
|
105
|
+
* @see decode
|
|
106
|
+
*/
|
|
84
107
|
encode() {
|
|
85
108
|
const tapTree = exports.TapTreeCoder.encode(this.scripts.map((script) => ({
|
|
86
109
|
depth: 1,
|
|
@@ -89,18 +112,40 @@ class VtxoScript {
|
|
|
89
112
|
})));
|
|
90
113
|
return tapTree;
|
|
91
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Build the Arkade address corresponding to this virtual output script.
|
|
117
|
+
*
|
|
118
|
+
* @param prefix - Bech32 human-readable prefix
|
|
119
|
+
* @param serverPubKey - 32-byte Arkade server public key
|
|
120
|
+
* @returns Arkade address for this script
|
|
121
|
+
* @see ArkAddress
|
|
122
|
+
*/
|
|
92
123
|
address(prefix, serverPubKey) {
|
|
93
124
|
return new address_1.ArkAddress(serverPubKey, this.tweakedPublicKey, prefix);
|
|
94
125
|
}
|
|
95
126
|
get pkScript() {
|
|
96
127
|
return btc_signer_1.Script.encode(["OP_1", this.tweakedPublicKey]);
|
|
97
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Build the Taproot onchain address corresponding to this virtual output script.
|
|
131
|
+
*
|
|
132
|
+
* @param network - Bitcoin network descriptor
|
|
133
|
+
* @returns Taproot onchain address
|
|
134
|
+
* @see address
|
|
135
|
+
*/
|
|
98
136
|
onchainAddress(network) {
|
|
99
137
|
return (0, btc_signer_1.Address)(network).encode({
|
|
100
138
|
type: "tr",
|
|
101
139
|
pubkey: this.tweakedPublicKey,
|
|
102
140
|
});
|
|
103
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Look up a tapleaf script by its hex-encoded tapscript body.
|
|
144
|
+
*
|
|
145
|
+
* @param scriptHex - Hex-encoded tapscript body without the leaf version byte
|
|
146
|
+
* @returns Matching tapleaf script
|
|
147
|
+
* @throws Error if no matching leaf exists
|
|
148
|
+
*/
|
|
104
149
|
findLeaf(scriptHex) {
|
|
105
150
|
const leaf = this.leaves.find((leaf) => base_1.hex.encode(scriptFromTapLeafScript(leaf)) === scriptHex);
|
|
106
151
|
if (!leaf) {
|
|
@@ -108,6 +153,12 @@ class VtxoScript {
|
|
|
108
153
|
}
|
|
109
154
|
return leaf;
|
|
110
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Return all unilateral exit paths embedded in the virtual output script.
|
|
158
|
+
*
|
|
159
|
+
* @returns CSV-based exit paths found in the leaves
|
|
160
|
+
* @see getSequence
|
|
161
|
+
*/
|
|
111
162
|
exitPaths() {
|
|
112
163
|
const paths = [];
|
|
113
164
|
for (const leaf of this.leaves) {
|
|
@@ -130,6 +181,24 @@ class VtxoScript {
|
|
|
130
181
|
}
|
|
131
182
|
}
|
|
132
183
|
exports.VtxoScript = VtxoScript;
|
|
184
|
+
/**
|
|
185
|
+
* Extract the timelock value encoded in a timelocked tapleaf, if any.
|
|
186
|
+
*
|
|
187
|
+
* The return value is unit-ambiguous: for a CSV leaf it is a BIP-68
|
|
188
|
+
* nSequence (relative timelock); for a CLTV leaf it is an absolute
|
|
189
|
+
* nLockTime. Callers must know which leaf shape they are inspecting to
|
|
190
|
+
* interpret the number correctly, and must not copy a CSV result into
|
|
191
|
+
* `Transaction.lockTime` (or vice versa).
|
|
192
|
+
*
|
|
193
|
+
* @param tapLeafScript - Tapleaf script to inspect
|
|
194
|
+
* @returns The encoded timelock value, or `undefined` when neither a CSV
|
|
195
|
+
* nor CLTV path is present
|
|
196
|
+
* @see VtxoScript.exitPaths
|
|
197
|
+
*/
|
|
198
|
+
// TODO(next-major): return a discriminated union
|
|
199
|
+
// (`{ kind: "relative", nSequence } | { kind: "absolute", lockTime }`)
|
|
200
|
+
// so callers can't conflate the two. Deferred because changing the
|
|
201
|
+
// return type is a breaking change.
|
|
133
202
|
function getSequence(tapLeafScript) {
|
|
134
203
|
let sequence = undefined;
|
|
135
204
|
try {
|
|
@@ -25,6 +25,7 @@ var DefaultVtxo;
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
class Script extends base_1.VtxoScript {
|
|
28
|
+
/** Create the default virtual output script with one forfeit path and one exit path. */
|
|
28
29
|
constructor(options) {
|
|
29
30
|
const { pubKey, serverPubKey, csvTimelock = Script.DEFAULT_TIMELOCK, } = options;
|
|
30
31
|
const forfeitScript = tapscript_1.MultisigTapscript.encode({
|
|
@@ -39,9 +40,11 @@ var DefaultVtxo;
|
|
|
39
40
|
this.forfeitScript = base_2.hex.encode(forfeitScript);
|
|
40
41
|
this.exitScript = base_2.hex.encode(exitScript);
|
|
41
42
|
}
|
|
43
|
+
/** Return the forfeit tapleaf script. */
|
|
42
44
|
forfeit() {
|
|
43
45
|
return this.findLeaf(this.forfeitScript);
|
|
44
46
|
}
|
|
47
|
+
/** Return the unilateral exit tapleaf script. */
|
|
45
48
|
exit() {
|
|
46
49
|
return this.findLeaf(this.exitScript);
|
|
47
50
|
}
|
|
@@ -24,6 +24,7 @@ var DelegateVtxo;
|
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
26
|
class Script extends base_1.VtxoScript {
|
|
27
|
+
/** Create a delegated virtual output script with forfeit, exit, and delegate paths. */
|
|
27
28
|
constructor(options) {
|
|
28
29
|
const defaultVtxo = new default_1.DefaultVtxo.Script(options);
|
|
29
30
|
const { delegatePubKey, pubKey, serverPubKey } = options;
|
|
@@ -35,12 +36,15 @@ var DelegateVtxo;
|
|
|
35
36
|
this.defaultVtxo = defaultVtxo;
|
|
36
37
|
this.delegateScript = base_2.hex.encode(delegateScript);
|
|
37
38
|
}
|
|
39
|
+
/** Return the forfeit tapleaf script. */
|
|
38
40
|
forfeit() {
|
|
39
41
|
return this.findLeaf(this.defaultVtxo.forfeitScript);
|
|
40
42
|
}
|
|
43
|
+
/** Return the unilateral exit tapleaf script. */
|
|
41
44
|
exit() {
|
|
42
45
|
return this.findLeaf(this.defaultVtxo.exitScript);
|
|
43
46
|
}
|
|
47
|
+
/** Return the delegate tapleaf script. */
|
|
44
48
|
delegate() {
|
|
45
49
|
return this.findLeaf(this.delegateScript);
|
|
46
50
|
}
|
|
@@ -48,9 +48,9 @@ var TapscriptType;
|
|
|
48
48
|
TapscriptType["CLTVMultisig"] = "cltv-multisig";
|
|
49
49
|
})(TapscriptType || (exports.TapscriptType = TapscriptType = {}));
|
|
50
50
|
/**
|
|
51
|
-
* decodeTapscript is a function that decodes an
|
|
51
|
+
* decodeTapscript is a function that decodes an Arkade tapscript from a raw script.
|
|
52
52
|
*
|
|
53
|
-
* @throws {Error} if the script is not a valid
|
|
53
|
+
* @throws {Error} if the script is not a valid Arkade tapscript
|
|
54
54
|
* @example
|
|
55
55
|
* ```typescript
|
|
56
56
|
* const arkTapscript = decodeTapscript(new Uint8Array(32));
|
|
@@ -92,6 +92,7 @@ var MultisigTapscript;
|
|
|
92
92
|
MultisigType[MultisigType["CHECKSIG"] = 0] = "CHECKSIG";
|
|
93
93
|
MultisigType[MultisigType["CHECKSIGADD"] = 1] = "CHECKSIGADD";
|
|
94
94
|
})(MultisigType = MultisigTapscript.MultisigType || (MultisigTapscript.MultisigType = {}));
|
|
95
|
+
/** Encode a plain multisig tapscript. */
|
|
95
96
|
function encode(params) {
|
|
96
97
|
if (params.pubkeys.length === 0) {
|
|
97
98
|
throw new Error("At least 1 pubkey is required");
|
|
@@ -129,6 +130,7 @@ var MultisigTapscript;
|
|
|
129
130
|
};
|
|
130
131
|
}
|
|
131
132
|
MultisigTapscript.encode = encode;
|
|
133
|
+
/** Decode a plain multisig tapscript from raw script bytes. */
|
|
132
134
|
function decode(script) {
|
|
133
135
|
if (script.length === 0) {
|
|
134
136
|
throw new Error("Failed to decode: script is empty");
|
|
@@ -241,6 +243,7 @@ var MultisigTapscript;
|
|
|
241
243
|
script,
|
|
242
244
|
};
|
|
243
245
|
}
|
|
246
|
+
/** Return true when the tapscript is a plain multisig tapscript. */
|
|
244
247
|
function is(tapscript) {
|
|
245
248
|
return tapscript.type === TapscriptType.Multisig;
|
|
246
249
|
}
|
|
@@ -261,6 +264,7 @@ var MultisigTapscript;
|
|
|
261
264
|
*/
|
|
262
265
|
var CSVMultisigTapscript;
|
|
263
266
|
(function (CSVMultisigTapscript) {
|
|
267
|
+
/** Encode a CSV multisig tapscript. */
|
|
264
268
|
function encode(params) {
|
|
265
269
|
for (const pubkey of params.pubkeys) {
|
|
266
270
|
if (pubkey.length !== 32) {
|
|
@@ -287,6 +291,7 @@ var CSVMultisigTapscript;
|
|
|
287
291
|
};
|
|
288
292
|
}
|
|
289
293
|
CSVMultisigTapscript.encode = encode;
|
|
294
|
+
/** Decode a CSV multisig tapscript from raw script bytes. */
|
|
290
295
|
function decode(script) {
|
|
291
296
|
if (script.length === 0) {
|
|
292
297
|
throw new Error("Failed to decode: script is empty");
|
|
@@ -338,6 +343,7 @@ var CSVMultisigTapscript;
|
|
|
338
343
|
};
|
|
339
344
|
}
|
|
340
345
|
CSVMultisigTapscript.decode = decode;
|
|
346
|
+
/** Return true when the tapscript is a CSV multisig tapscript. */
|
|
341
347
|
function is(tapscript) {
|
|
342
348
|
return tapscript.type === TapscriptType.CSVMultisig;
|
|
343
349
|
}
|
|
@@ -357,6 +363,7 @@ var CSVMultisigTapscript;
|
|
|
357
363
|
*/
|
|
358
364
|
var ConditionCSVMultisigTapscript;
|
|
359
365
|
(function (ConditionCSVMultisigTapscript) {
|
|
366
|
+
/** Encode a condition + CSV multisig tapscript. */
|
|
360
367
|
function encode(params) {
|
|
361
368
|
const script = new Uint8Array([
|
|
362
369
|
...params.conditionScript,
|
|
@@ -370,6 +377,7 @@ var ConditionCSVMultisigTapscript;
|
|
|
370
377
|
};
|
|
371
378
|
}
|
|
372
379
|
ConditionCSVMultisigTapscript.encode = encode;
|
|
380
|
+
/** Decode a condition + CSV multisig tapscript from raw script bytes. */
|
|
373
381
|
function decode(script) {
|
|
374
382
|
if (script.length === 0) {
|
|
375
383
|
throw new Error("Failed to decode: script is empty");
|
|
@@ -413,6 +421,7 @@ var ConditionCSVMultisigTapscript;
|
|
|
413
421
|
};
|
|
414
422
|
}
|
|
415
423
|
ConditionCSVMultisigTapscript.decode = decode;
|
|
424
|
+
/** Return true when the tapscript is a condition + CSV multisig tapscript. */
|
|
416
425
|
function is(tapscript) {
|
|
417
426
|
return tapscript.type === TapscriptType.ConditionCSVMultisig;
|
|
418
427
|
}
|
|
@@ -432,6 +441,7 @@ var ConditionCSVMultisigTapscript;
|
|
|
432
441
|
*/
|
|
433
442
|
var ConditionMultisigTapscript;
|
|
434
443
|
(function (ConditionMultisigTapscript) {
|
|
444
|
+
/** Encode a condition + multisig tapscript. */
|
|
435
445
|
function encode(params) {
|
|
436
446
|
const script = new Uint8Array([
|
|
437
447
|
...params.conditionScript,
|
|
@@ -445,6 +455,7 @@ var ConditionMultisigTapscript;
|
|
|
445
455
|
};
|
|
446
456
|
}
|
|
447
457
|
ConditionMultisigTapscript.encode = encode;
|
|
458
|
+
/** Decode a condition + multisig tapscript from raw script bytes. */
|
|
448
459
|
function decode(script) {
|
|
449
460
|
if (script.length === 0) {
|
|
450
461
|
throw new Error("Failed to decode: script is empty");
|
|
@@ -488,6 +499,7 @@ var ConditionMultisigTapscript;
|
|
|
488
499
|
};
|
|
489
500
|
}
|
|
490
501
|
ConditionMultisigTapscript.decode = decode;
|
|
502
|
+
/** Return true when the tapscript is a condition + multisig tapscript. */
|
|
491
503
|
function is(tapscript) {
|
|
492
504
|
return tapscript.type === TapscriptType.ConditionMultisig;
|
|
493
505
|
}
|
|
@@ -507,6 +519,7 @@ var ConditionMultisigTapscript;
|
|
|
507
519
|
*/
|
|
508
520
|
var CLTVMultisigTapscript;
|
|
509
521
|
(function (CLTVMultisigTapscript) {
|
|
522
|
+
/** Encode a CLTV multisig tapscript. */
|
|
510
523
|
function encode(params) {
|
|
511
524
|
const locktime = MinimalScriptNum.encode(params.absoluteTimelock);
|
|
512
525
|
const asm = [
|
|
@@ -526,6 +539,7 @@ var CLTVMultisigTapscript;
|
|
|
526
539
|
};
|
|
527
540
|
}
|
|
528
541
|
CLTVMultisigTapscript.encode = encode;
|
|
542
|
+
/** Decode a CLTV multisig tapscript from raw script bytes. */
|
|
529
543
|
function decode(script) {
|
|
530
544
|
if (script.length === 0) {
|
|
531
545
|
throw new Error("Failed to decode: script is empty");
|
|
@@ -535,7 +549,7 @@ var CLTVMultisigTapscript;
|
|
|
535
549
|
throw new Error(`Invalid script: too short (expected at least 3)`);
|
|
536
550
|
}
|
|
537
551
|
const locktime = asm[0];
|
|
538
|
-
if (typeof locktime === "string"
|
|
552
|
+
if (typeof locktime === "string") {
|
|
539
553
|
throw new Error("Invalid script: expected locktime number");
|
|
540
554
|
}
|
|
541
555
|
if (asm[1] !== "CHECKLOCKTIMEVERIFY" || asm[2] !== "DROP") {
|
|
@@ -549,7 +563,13 @@ var CLTVMultisigTapscript;
|
|
|
549
563
|
catch (error) {
|
|
550
564
|
throw new Error(`Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`);
|
|
551
565
|
}
|
|
552
|
-
|
|
566
|
+
let absoluteTimelock;
|
|
567
|
+
if (typeof locktime === "number") {
|
|
568
|
+
absoluteTimelock = BigInt(locktime);
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
absoluteTimelock = MinimalScriptNum.decode(locktime);
|
|
572
|
+
}
|
|
553
573
|
const reconstructed = encode({
|
|
554
574
|
absoluteTimelock,
|
|
555
575
|
...multisig.params,
|
|
@@ -567,6 +587,7 @@ var CLTVMultisigTapscript;
|
|
|
567
587
|
};
|
|
568
588
|
}
|
|
569
589
|
CLTVMultisigTapscript.decode = decode;
|
|
590
|
+
/** Return true when the tapscript is a CLTV multisig tapscript. */
|
|
570
591
|
function is(tapscript) {
|
|
571
592
|
return tapscript.type === TapscriptType.CLTVMultisig;
|
|
572
593
|
}
|
package/dist/cjs/script/vhtlc.js
CHANGED
|
@@ -5,36 +5,38 @@ const btc_signer_1 = require("@scure/btc-signer");
|
|
|
5
5
|
const tapscript_1 = require("./tapscript");
|
|
6
6
|
const base_1 = require("@scure/base");
|
|
7
7
|
const base_2 = require("./base");
|
|
8
|
-
/**
|
|
9
|
-
* Virtual Hash Time Lock Contract (VHTLC) implementation.
|
|
10
|
-
*
|
|
11
|
-
* VHTLC is a contract that enables atomic swaps and conditional payments
|
|
12
|
-
* in the Ark protocol. It provides multiple spending paths:
|
|
13
|
-
*
|
|
14
|
-
* - **claim**: Receiver can claim funds by revealing the preimage
|
|
15
|
-
* - **refund**: Sender and receiver can collaboratively refund
|
|
16
|
-
* - **refundWithoutReceiver**: Sender can refund after locktime expires
|
|
17
|
-
* - **unilateralClaim**: Receiver can claim unilaterally after delay
|
|
18
|
-
* - **unilateralRefund**: Sender and receiver can refund unilaterally after delay
|
|
19
|
-
* - **unilateralRefundWithoutReceiver**: Sender can refund unilaterally after delay
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```typescript
|
|
23
|
-
* const vhtlc = new VHTLC.Script({
|
|
24
|
-
* sender: alicePubKey,
|
|
25
|
-
* receiver: bobPubKey,
|
|
26
|
-
* server: serverPubKey,
|
|
27
|
-
* preimageHash: hash160(secret),
|
|
28
|
-
* refundLocktime: BigInt(chainTip + 10),
|
|
29
|
-
* unilateralClaimDelay: { type: 'blocks', value: 100n },
|
|
30
|
-
* unilateralRefundDelay: { type: 'blocks', value: 102n },
|
|
31
|
-
* unilateralRefundWithoutReceiverDelay: { type: 'blocks', value: 103n }
|
|
32
|
-
* });
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
8
|
+
/** Virtual Hash Time Lock Contract (VHTLC) namespace. */
|
|
35
9
|
var VHTLC;
|
|
36
10
|
(function (VHTLC) {
|
|
11
|
+
/**
|
|
12
|
+
* Virtual Hash Time Lock Contract (VHTLC) script implementation.
|
|
13
|
+
*
|
|
14
|
+
* VHTLC enables atomic swaps and conditional payments in the Arkade protocol.
|
|
15
|
+
* It provides multiple spending paths:
|
|
16
|
+
*
|
|
17
|
+
* - **claim**: Receiver can claim funds by revealing the preimage
|
|
18
|
+
* - **refund**: Sender and receiver can collaboratively refund
|
|
19
|
+
* - **refundWithoutReceiver**: Sender can refund after locktime expires
|
|
20
|
+
* - **unilateralClaim**: Receiver can claim unilaterally after delay
|
|
21
|
+
* - **unilateralRefund**: Sender and receiver can refund unilaterally after delay
|
|
22
|
+
* - **unilateralRefundWithoutReceiver**: Sender can refund unilaterally after delay
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const vhtlc = new VHTLC.Script({
|
|
27
|
+
* sender: alicePubKey,
|
|
28
|
+
* receiver: bobPubKey,
|
|
29
|
+
* server: serverPubKey,
|
|
30
|
+
* preimageHash: hash160(secret),
|
|
31
|
+
* refundLocktime: BigInt(chainTip + 10),
|
|
32
|
+
* unilateralClaimDelay: { type: 'blocks', value: 100n },
|
|
33
|
+
* unilateralRefundDelay: { type: 'blocks', value: 102n },
|
|
34
|
+
* unilateralRefundWithoutReceiverDelay: { type: 'blocks', value: 103n }
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
37
38
|
class Script extends base_2.VtxoScript {
|
|
39
|
+
/** Create a VHTLC script from the supplied participant keys, hash, and timelocks. */
|
|
38
40
|
constructor(options) {
|
|
39
41
|
validateOptions(options);
|
|
40
42
|
const { sender, receiver, server, preimageHash, refundLocktime, unilateralClaimDelay, unilateralRefundDelay, unilateralRefundWithoutReceiverDelay, } = options;
|
|
@@ -79,21 +81,27 @@ var VHTLC;
|
|
|
79
81
|
this.unilateralRefundScript = base_1.hex.encode(unilateralRefundScript);
|
|
80
82
|
this.unilateralRefundWithoutReceiverScript = base_1.hex.encode(unilateralRefundWithoutReceiverScript);
|
|
81
83
|
}
|
|
84
|
+
/** Return the collaborative claim tapleaf script. */
|
|
82
85
|
claim() {
|
|
83
86
|
return this.findLeaf(this.claimScript);
|
|
84
87
|
}
|
|
88
|
+
/** Return the collaborative refund tapleaf script. */
|
|
85
89
|
refund() {
|
|
86
90
|
return this.findLeaf(this.refundScript);
|
|
87
91
|
}
|
|
92
|
+
/** Return the refund-without-receiver tapleaf script. */
|
|
88
93
|
refundWithoutReceiver() {
|
|
89
94
|
return this.findLeaf(this.refundWithoutReceiverScript);
|
|
90
95
|
}
|
|
96
|
+
/** Return the unilateral claim tapleaf script. */
|
|
91
97
|
unilateralClaim() {
|
|
92
98
|
return this.findLeaf(this.unilateralClaimScript);
|
|
93
99
|
}
|
|
100
|
+
/** Return the unilateral refund tapleaf script. */
|
|
94
101
|
unilateralRefund() {
|
|
95
102
|
return this.findLeaf(this.unilateralRefundScript);
|
|
96
103
|
}
|
|
104
|
+
/** Return the unilateral refund-without-receiver tapleaf script. */
|
|
97
105
|
unilateralRefundWithoutReceiver() {
|
|
98
106
|
return this.findLeaf(this.unilateralRefundWithoutReceiverScript);
|
|
99
107
|
}
|
|
@@ -37,7 +37,7 @@ exports.FileSystemStorageAdapter = void 0;
|
|
|
37
37
|
const fs = __importStar(require("fs/promises"));
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
39
|
/**
|
|
40
|
-
* @deprecated Use
|
|
40
|
+
* @deprecated Use repository implementations via `StorageConfig` instead.
|
|
41
41
|
*/
|
|
42
42
|
class FileSystemStorageAdapter {
|
|
43
43
|
constructor(dirPath) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.InMemoryStorageAdapter = void 0;
|
|
4
4
|
/**
|
|
5
|
-
* @deprecated Use
|
|
5
|
+
* @deprecated Use repository implementations via `StorageConfig` instead.
|
|
6
6
|
*/
|
|
7
7
|
class InMemoryStorageAdapter {
|
|
8
8
|
constructor() {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.IndexedDBStorageAdapter = void 0;
|
|
4
4
|
const db_1 = require("../repositories/indexedDB/db");
|
|
5
5
|
/**
|
|
6
|
-
* @deprecated Use
|
|
6
|
+
* @deprecated Use repository implementations via `StorageConfig` instead.
|
|
7
7
|
*/
|
|
8
8
|
class IndexedDBStorageAdapter {
|
|
9
9
|
constructor(dbName, version = db_1.DB_VERSION) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.LocalStorageAdapter = void 0;
|
|
4
4
|
/**
|
|
5
|
-
* @deprecated Use
|
|
5
|
+
* @deprecated Use repository implementations via `StorageConfig` instead.
|
|
6
6
|
*/
|
|
7
7
|
class LocalStorageAdapter {
|
|
8
8
|
getSafeLocalStorage() {
|
|
@@ -38,7 +38,7 @@ function validateConnectorsTxGraph(settlementTxB64, connectorsGraph) {
|
|
|
38
38
|
if (rootInput.index !== BATCH_OUTPUT_CONNECTORS_INDEX)
|
|
39
39
|
throw exports.ErrWrongSettlementTxid;
|
|
40
40
|
}
|
|
41
|
-
// ValidateVtxoTxGraph checks if the given
|
|
41
|
+
// ValidateVtxoTxGraph checks if the given virtual output tx graph is valid.
|
|
42
42
|
// The function validates:
|
|
43
43
|
// - the number of nodes
|
|
44
44
|
// - the number of leaves
|
|
@@ -21,7 +21,7 @@ const extension_1 = require("../extension");
|
|
|
21
21
|
*
|
|
22
22
|
* Creates one checkpoint transaction per input and a virtual transaction that
|
|
23
23
|
* combines all the checkpoints, sending to the specified outputs. This is the
|
|
24
|
-
* core function for creating
|
|
24
|
+
* core function for creating Arkade transactions.
|
|
25
25
|
*
|
|
26
26
|
* @param inputs - Array of virtual transaction inputs
|
|
27
27
|
* @param outputs - Array of transaction outputs
|
|
@@ -99,9 +99,9 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
99
99
|
return tx;
|
|
100
100
|
}
|
|
101
101
|
function buildCheckpointTx(vtxo, serverUnrollScript) {
|
|
102
|
-
// create the checkpoint
|
|
102
|
+
// create the checkpoint virtual output script from collaborative closure
|
|
103
103
|
const collaborativeClosure = (0, tapscript_1.decodeTapscript)((0, base_2.scriptFromTapLeafScript)(vtxo.tapLeafScript));
|
|
104
|
-
// create the checkpoint
|
|
104
|
+
// create the checkpoint virtual output script combining collaborative closure and server unroll script
|
|
105
105
|
const checkpointVtxoScript = new base_2.VtxoScript([
|
|
106
106
|
serverUnrollScript.script,
|
|
107
107
|
collaborativeClosure.script,
|
|
@@ -256,8 +256,8 @@ function combineTapscriptSigs(signedTx, originalTx) {
|
|
|
256
256
|
return originalTx;
|
|
257
257
|
}
|
|
258
258
|
/**
|
|
259
|
-
* Validates if a given string is a valid
|
|
260
|
-
* @param address The
|
|
259
|
+
* Validates if a given string is a valid Arkade address by attempting to decode it.
|
|
260
|
+
* @param address The Arkade address to validate.
|
|
261
261
|
* @returns True if the address is valid, false otherwise.
|
|
262
262
|
*/
|
|
263
263
|
function isValidArkAddress(address) {
|
package/dist/cjs/utils/bip21.js
CHANGED
|
@@ -7,6 +7,12 @@ var BIP21Error;
|
|
|
7
7
|
BIP21Error["INVALID_ADDRESS"] = "Invalid address";
|
|
8
8
|
})(BIP21Error || (exports.BIP21Error = BIP21Error = {}));
|
|
9
9
|
class BIP21 {
|
|
10
|
+
/**
|
|
11
|
+
* Create a BIP21 URI from the provided parameters.
|
|
12
|
+
*
|
|
13
|
+
* @param params - BIP21 parameters to encode
|
|
14
|
+
* @returns Encoded BIP21 URI
|
|
15
|
+
*/
|
|
10
16
|
static create(params) {
|
|
11
17
|
const { address, ...options } = params;
|
|
12
18
|
// Build query string
|
|
@@ -25,7 +31,7 @@ class BIP21 {
|
|
|
25
31
|
queryParams[key] = value;
|
|
26
32
|
}
|
|
27
33
|
else if (key === "ark") {
|
|
28
|
-
// Validate
|
|
34
|
+
// Validate Arkade address format
|
|
29
35
|
if (typeof value === "string" &&
|
|
30
36
|
(value.startsWith("ark") || value.startsWith("tark"))) {
|
|
31
37
|
queryParams[key] = value;
|
|
@@ -56,11 +62,18 @@ class BIP21 {
|
|
|
56
62
|
: "";
|
|
57
63
|
return `bitcoin:${address ? address.toLowerCase() : ""}${query}`;
|
|
58
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Parse a BIP21 URI and return its decoded parameters.
|
|
67
|
+
*
|
|
68
|
+
* @param uri - BIP21 URI to parse
|
|
69
|
+
* @returns Parsed BIP21 URI data
|
|
70
|
+
* @throws Error if the URI does not start with the `bitcoin:` scheme
|
|
71
|
+
*/
|
|
59
72
|
static parse(uri) {
|
|
60
73
|
if (!uri.toLowerCase().startsWith("bitcoin:")) {
|
|
61
74
|
throw new Error(BIP21Error.INVALID_URI);
|
|
62
75
|
}
|
|
63
|
-
// Remove bitcoin
|
|
76
|
+
// Remove the `bitcoin:` prefix while preserving the case of the rest.
|
|
64
77
|
const withoutPrefix = uri.slice(uri.toLowerCase().indexOf("bitcoin:") + 8);
|
|
65
78
|
const [address, query] = withoutPrefix.split("?");
|
|
66
79
|
const params = {};
|
|
@@ -83,7 +96,7 @@ class BIP21 {
|
|
|
83
96
|
params[key] = amount;
|
|
84
97
|
}
|
|
85
98
|
else if (key === "ark") {
|
|
86
|
-
// Validate
|
|
99
|
+
// Validate Arkade address format
|
|
87
100
|
if (value.startsWith("ark") || value.startsWith("tark")) {
|
|
88
101
|
params[key] = value;
|
|
89
102
|
}
|
|
@@ -11,7 +11,7 @@ exports.computeSyncWindow = computeSyncWindow;
|
|
|
11
11
|
exports.cursorCutoff = cursorCutoff;
|
|
12
12
|
/** Lag behind real-time to avoid racing with indexer writes. */
|
|
13
13
|
exports.SAFETY_LAG_MS = 30000;
|
|
14
|
-
/** Overlap window so boundary
|
|
14
|
+
/** Overlap window so boundary virtual outputs are never missed. */
|
|
15
15
|
exports.OVERLAP_MS = 60000;
|
|
16
16
|
/**
|
|
17
17
|
* Per-repository mutex that serializes wallet-state mutations so that
|
|
@@ -112,8 +112,8 @@ async function clearSyncCursors(repo, scripts) {
|
|
|
112
112
|
* Returns `undefined` when the script has no cursor (bootstrap needed).
|
|
113
113
|
*
|
|
114
114
|
* No upper bound (`before`) is applied to the query so that freshly
|
|
115
|
-
* created
|
|
116
|
-
* when advancing the cursor (see
|
|
115
|
+
* created virtual outputs are never excluded. The safety lag is applied only
|
|
116
|
+
* when advancing the cursor (see @see cursorCutoff).
|
|
117
117
|
*/
|
|
118
118
|
function computeSyncWindow(cursor) {
|
|
119
119
|
if (cursor === undefined)
|
|
@@ -123,7 +123,7 @@ function computeSyncWindow(cursor) {
|
|
|
123
123
|
}
|
|
124
124
|
/**
|
|
125
125
|
* The safe high-water mark for cursor advancement.
|
|
126
|
-
* Lags behind real-time by
|
|
126
|
+
* Lags behind real-time by @see SAFETY_LAG_MS so that virtual outputs still
|
|
127
127
|
* being indexed are re-queried on the next sync.
|
|
128
128
|
*
|
|
129
129
|
* When `requestStartedAt` is provided the cutoff is frozen to the
|
|
@@ -4,7 +4,7 @@ exports.Transaction = void 0;
|
|
|
4
4
|
const btc_signer_1 = require("@scure/btc-signer");
|
|
5
5
|
/**
|
|
6
6
|
* Transaction is a wrapper around the @scure/btc-signer Transaction class.
|
|
7
|
-
* It adds the
|
|
7
|
+
* It adds the Arkade protocol specific options to the transaction.
|
|
8
8
|
*/
|
|
9
9
|
class Transaction extends btc_signer_1.Transaction {
|
|
10
10
|
constructor(opts) {
|
|
@@ -48,13 +48,13 @@ function subtractAssets(spent, change) {
|
|
|
48
48
|
return Array.from(map, ([assetId, amount]) => ({ assetId, amount }));
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
|
-
* Builds the transaction history by analyzing virtual
|
|
51
|
+
* Builds the transaction history by analyzing virtual outputs, boarding transactions, and ignored commitments.
|
|
52
52
|
* History is sorted from newest to oldest and is composed only of SENT and RECEIVED transactions.
|
|
53
53
|
*
|
|
54
|
-
* @param {VirtualCoin[]} vtxos - An array of virtual
|
|
54
|
+
* @param {VirtualCoin[]} vtxos - An array of virtual outputs representing the user's transactions and balances.
|
|
55
55
|
* @param {ArkTransaction[]} allBoardingTxs - An array of boarding transactions to include in the history.
|
|
56
56
|
* @param {Set<string>} commitmentsToIgnore - A set of commitment IDs that should be excluded from processing.
|
|
57
|
-
* @return {ExtendedArkTransaction[]} A sorted array of extended
|
|
57
|
+
* @return {ExtendedArkTransaction[]} A sorted array of extended Arkade transactions, representing the transaction history.
|
|
58
58
|
*/
|
|
59
59
|
async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnore, getTxCreatedAt) {
|
|
60
60
|
const fromOldestVtxo = [...vtxos].sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
|
|
@@ -62,7 +62,7 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
|
|
|
62
62
|
let received = [];
|
|
63
63
|
for (const vtxo of fromOldestVtxo) {
|
|
64
64
|
if (vtxo.status.isLeaf) {
|
|
65
|
-
// If this
|
|
65
|
+
// If this virtual output is a leaf and it's not the settlement of a boarding or there's no virtual output refreshed by it,
|
|
66
66
|
// it's translated into a received batch transaction
|
|
67
67
|
if (!commitmentsToIgnore.has(vtxo.virtualStatus.commitmentTxIds[0]) &&
|
|
68
68
|
fromOldestVtxo.filter((v) => v.settledBy === vtxo.virtualStatus.commitmentTxIds[0]).length === 0) {
|
|
@@ -82,7 +82,7 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
else if (fromOldestVtxo.filter((v) => v.arkTxId === vtxo.txid).length === 0) {
|
|
85
|
-
// If this
|
|
85
|
+
// If this virtual output is preconfirmed and does not spend any other virtual outputs,
|
|
86
86
|
// it's translated into a received offchain transaction
|
|
87
87
|
const assets = collectAssets([vtxo]);
|
|
88
88
|
received.push({
|
|
@@ -95,15 +95,15 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
|
|
|
95
95
|
...(assets && { assets }),
|
|
96
96
|
});
|
|
97
97
|
}
|
|
98
|
-
// If the
|
|
98
|
+
// If the virtual output is spent, it's translated into a sent transaction unless:
|
|
99
99
|
// - it's been refreshed (we don't want to add any record in this case)
|
|
100
|
-
// - a sent transaction has been already added to avoid duplicates (can happen if many
|
|
100
|
+
// - a sent transaction has been already added to avoid duplicates (can happen if many virtual outputs have been spent in the same tx or forfeited in the same batch)
|
|
101
101
|
if (vtxo.isSpent) {
|
|
102
|
-
// If the
|
|
102
|
+
// If the virtual output is spent offchain, it's translated into an offchain sent tx
|
|
103
103
|
if (vtxo.arkTxId &&
|
|
104
104
|
!sent.some((s) => s.key.arkTxid === vtxo.arkTxId)) {
|
|
105
105
|
const changes = fromOldestVtxo.filter((_) => _.txid === vtxo.arkTxId);
|
|
106
|
-
// We want to find all the other
|
|
106
|
+
// We want to find all the other virtual outputs spent by the same transaction to
|
|
107
107
|
// calculate the full amount of the change.
|
|
108
108
|
const allSpent = fromOldestVtxo.filter((v) => v.arkTxId === vtxo.arkTxId);
|
|
109
109
|
const spentAmount = allSpent.reduce((acc, v) => acc + v.value, 0);
|
|
@@ -116,7 +116,7 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
|
|
|
116
116
|
}
|
|
117
117
|
else {
|
|
118
118
|
txAmount = spentAmount;
|
|
119
|
-
// TODO: fetch the
|
|
119
|
+
// TODO: fetch the virtual output with /v1/indexer/vtxos?outpoints=<vtxo.arkTxid:0> to know when the tx was made
|
|
120
120
|
txTime = getTxCreatedAt
|
|
121
121
|
? ((await getTxCreatedAt(vtxo.arkTxId)) ??
|
|
122
122
|
vtxo.createdAt.getTime() + 1)
|
|
@@ -133,7 +133,7 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
|
|
|
133
133
|
...(assets && { assets }),
|
|
134
134
|
});
|
|
135
135
|
}
|
|
136
|
-
// If the
|
|
136
|
+
// If the virtual output is forfeited in a batch and the total sum of forfeited virtual outputs is bigger than the sum of new virtual outputs,
|
|
137
137
|
// it's translated into an exit sent tx
|
|
138
138
|
if (vtxo.settledBy &&
|
|
139
139
|
!commitmentsToIgnore.has(vtxo.settledBy) &&
|