@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/esm/script/base.js
CHANGED
|
@@ -11,18 +11,35 @@ export function scriptFromTapLeafScript(leaf) {
|
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* VtxoScript is a script that contains a list of tapleaf scripts.
|
|
14
|
-
* It is used to create
|
|
14
|
+
* It is used to create virtual output scripts.
|
|
15
|
+
*
|
|
16
|
+
* @see ArkAddress
|
|
15
17
|
*
|
|
16
18
|
* @example
|
|
17
19
|
* ```typescript
|
|
18
20
|
* const vtxoScript = new VtxoScript([new Uint8Array(32), new Uint8Array(32)]);
|
|
21
|
+
* ```
|
|
19
22
|
*/
|
|
20
23
|
export class VtxoScript {
|
|
24
|
+
/**
|
|
25
|
+
* Decode a virtual output script from an encoded TapTree.
|
|
26
|
+
*
|
|
27
|
+
* @param tapTree - Encoded TapTree bytes
|
|
28
|
+
* @returns Decoded virtual output script
|
|
29
|
+
* @throws Error if the TapTree cannot be decoded into a valid script set
|
|
30
|
+
* @see encode
|
|
31
|
+
*/
|
|
21
32
|
static decode(tapTree) {
|
|
22
33
|
const leaves = TapTreeCoder.decode(tapTree);
|
|
23
34
|
const scripts = leaves.map((leaf) => leaf.script);
|
|
24
35
|
return new VtxoScript(scripts);
|
|
25
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Create a virtual output script from its tapleaf scripts.
|
|
39
|
+
*
|
|
40
|
+
* @param scripts - Raw tapscript bytes for each leaf
|
|
41
|
+
* @throws Error if the provided leaves cannot produce a valid Taproot tree
|
|
42
|
+
*/
|
|
26
43
|
constructor(scripts) {
|
|
27
44
|
this.scripts = scripts;
|
|
28
45
|
// reverse the scripts if the number of scripts is odd
|
|
@@ -43,6 +60,12 @@ export class VtxoScript {
|
|
|
43
60
|
this.leaves = payment.tapLeafScript;
|
|
44
61
|
this.tweakedPublicKey = payment.tweakedPubkey;
|
|
45
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Encode the virtual output script to a TapTree byte representation.
|
|
65
|
+
*
|
|
66
|
+
* @returns Encoded TapTree bytes
|
|
67
|
+
* @see decode
|
|
68
|
+
*/
|
|
46
69
|
encode() {
|
|
47
70
|
const tapTree = TapTreeCoder.encode(this.scripts.map((script) => ({
|
|
48
71
|
depth: 1,
|
|
@@ -51,18 +74,40 @@ export class VtxoScript {
|
|
|
51
74
|
})));
|
|
52
75
|
return tapTree;
|
|
53
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Build the Arkade address corresponding to this virtual output script.
|
|
79
|
+
*
|
|
80
|
+
* @param prefix - Bech32 human-readable prefix
|
|
81
|
+
* @param serverPubKey - 32-byte Arkade server public key
|
|
82
|
+
* @returns Arkade address for this script
|
|
83
|
+
* @see ArkAddress
|
|
84
|
+
*/
|
|
54
85
|
address(prefix, serverPubKey) {
|
|
55
86
|
return new ArkAddress(serverPubKey, this.tweakedPublicKey, prefix);
|
|
56
87
|
}
|
|
57
88
|
get pkScript() {
|
|
58
89
|
return Script.encode(["OP_1", this.tweakedPublicKey]);
|
|
59
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Build the Taproot onchain address corresponding to this virtual output script.
|
|
93
|
+
*
|
|
94
|
+
* @param network - Bitcoin network descriptor
|
|
95
|
+
* @returns Taproot onchain address
|
|
96
|
+
* @see address
|
|
97
|
+
*/
|
|
60
98
|
onchainAddress(network) {
|
|
61
99
|
return Address(network).encode({
|
|
62
100
|
type: "tr",
|
|
63
101
|
pubkey: this.tweakedPublicKey,
|
|
64
102
|
});
|
|
65
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Look up a tapleaf script by its hex-encoded tapscript body.
|
|
106
|
+
*
|
|
107
|
+
* @param scriptHex - Hex-encoded tapscript body without the leaf version byte
|
|
108
|
+
* @returns Matching tapleaf script
|
|
109
|
+
* @throws Error if no matching leaf exists
|
|
110
|
+
*/
|
|
66
111
|
findLeaf(scriptHex) {
|
|
67
112
|
const leaf = this.leaves.find((leaf) => hex.encode(scriptFromTapLeafScript(leaf)) === scriptHex);
|
|
68
113
|
if (!leaf) {
|
|
@@ -70,6 +115,12 @@ export class VtxoScript {
|
|
|
70
115
|
}
|
|
71
116
|
return leaf;
|
|
72
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Return all unilateral exit paths embedded in the virtual output script.
|
|
120
|
+
*
|
|
121
|
+
* @returns CSV-based exit paths found in the leaves
|
|
122
|
+
* @see getSequence
|
|
123
|
+
*/
|
|
73
124
|
exitPaths() {
|
|
74
125
|
const paths = [];
|
|
75
126
|
for (const leaf of this.leaves) {
|
|
@@ -91,6 +142,24 @@ export class VtxoScript {
|
|
|
91
142
|
return paths;
|
|
92
143
|
}
|
|
93
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Extract the timelock value encoded in a timelocked tapleaf, if any.
|
|
147
|
+
*
|
|
148
|
+
* The return value is unit-ambiguous: for a CSV leaf it is a BIP-68
|
|
149
|
+
* nSequence (relative timelock); for a CLTV leaf it is an absolute
|
|
150
|
+
* nLockTime. Callers must know which leaf shape they are inspecting to
|
|
151
|
+
* interpret the number correctly, and must not copy a CSV result into
|
|
152
|
+
* `Transaction.lockTime` (or vice versa).
|
|
153
|
+
*
|
|
154
|
+
* @param tapLeafScript - Tapleaf script to inspect
|
|
155
|
+
* @returns The encoded timelock value, or `undefined` when neither a CSV
|
|
156
|
+
* nor CLTV path is present
|
|
157
|
+
* @see VtxoScript.exitPaths
|
|
158
|
+
*/
|
|
159
|
+
// TODO(next-major): return a discriminated union
|
|
160
|
+
// (`{ kind: "relative", nSequence } | { kind: "absolute", lockTime }`)
|
|
161
|
+
// so callers can't conflate the two. Deferred because changing the
|
|
162
|
+
// return type is a breaking change.
|
|
94
163
|
export function getSequence(tapLeafScript) {
|
|
95
164
|
let sequence = undefined;
|
|
96
165
|
try {
|
|
@@ -22,6 +22,7 @@ export var DefaultVtxo;
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
class Script extends VtxoScript {
|
|
25
|
+
/** Create the default virtual output script with one forfeit path and one exit path. */
|
|
25
26
|
constructor(options) {
|
|
26
27
|
const { pubKey, serverPubKey, csvTimelock = Script.DEFAULT_TIMELOCK, } = options;
|
|
27
28
|
const forfeitScript = MultisigTapscript.encode({
|
|
@@ -36,9 +37,11 @@ export var DefaultVtxo;
|
|
|
36
37
|
this.forfeitScript = hex.encode(forfeitScript);
|
|
37
38
|
this.exitScript = hex.encode(exitScript);
|
|
38
39
|
}
|
|
40
|
+
/** Return the forfeit tapleaf script. */
|
|
39
41
|
forfeit() {
|
|
40
42
|
return this.findLeaf(this.forfeitScript);
|
|
41
43
|
}
|
|
44
|
+
/** Return the unilateral exit tapleaf script. */
|
|
42
45
|
exit() {
|
|
43
46
|
return this.findLeaf(this.exitScript);
|
|
44
47
|
}
|
|
@@ -21,6 +21,7 @@ export var DelegateVtxo;
|
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
23
|
class Script extends VtxoScript {
|
|
24
|
+
/** Create a delegated virtual output script with forfeit, exit, and delegate paths. */
|
|
24
25
|
constructor(options) {
|
|
25
26
|
const defaultVtxo = new DefaultVtxo.Script(options);
|
|
26
27
|
const { delegatePubKey, pubKey, serverPubKey } = options;
|
|
@@ -32,12 +33,15 @@ export var DelegateVtxo;
|
|
|
32
33
|
this.defaultVtxo = defaultVtxo;
|
|
33
34
|
this.delegateScript = hex.encode(delegateScript);
|
|
34
35
|
}
|
|
36
|
+
/** Return the forfeit tapleaf script. */
|
|
35
37
|
forfeit() {
|
|
36
38
|
return this.findLeaf(this.defaultVtxo.forfeitScript);
|
|
37
39
|
}
|
|
40
|
+
/** Return the unilateral exit tapleaf script. */
|
|
38
41
|
exit() {
|
|
39
42
|
return this.findLeaf(this.defaultVtxo.exitScript);
|
|
40
43
|
}
|
|
44
|
+
/** Return the delegate tapleaf script. */
|
|
41
45
|
delegate() {
|
|
42
46
|
return this.findLeaf(this.delegateScript);
|
|
43
47
|
}
|
|
@@ -11,9 +11,9 @@ export var TapscriptType;
|
|
|
11
11
|
TapscriptType["CLTVMultisig"] = "cltv-multisig";
|
|
12
12
|
})(TapscriptType || (TapscriptType = {}));
|
|
13
13
|
/**
|
|
14
|
-
* decodeTapscript is a function that decodes an
|
|
14
|
+
* decodeTapscript is a function that decodes an Arkade tapscript from a raw script.
|
|
15
15
|
*
|
|
16
|
-
* @throws {Error} if the script is not a valid
|
|
16
|
+
* @throws {Error} if the script is not a valid Arkade tapscript
|
|
17
17
|
* @example
|
|
18
18
|
* ```typescript
|
|
19
19
|
* const arkTapscript = decodeTapscript(new Uint8Array(32));
|
|
@@ -55,6 +55,7 @@ export var MultisigTapscript;
|
|
|
55
55
|
MultisigType[MultisigType["CHECKSIG"] = 0] = "CHECKSIG";
|
|
56
56
|
MultisigType[MultisigType["CHECKSIGADD"] = 1] = "CHECKSIGADD";
|
|
57
57
|
})(MultisigType = MultisigTapscript.MultisigType || (MultisigTapscript.MultisigType = {}));
|
|
58
|
+
/** Encode a plain multisig tapscript. */
|
|
58
59
|
function encode(params) {
|
|
59
60
|
if (params.pubkeys.length === 0) {
|
|
60
61
|
throw new Error("At least 1 pubkey is required");
|
|
@@ -92,6 +93,7 @@ export var MultisigTapscript;
|
|
|
92
93
|
};
|
|
93
94
|
}
|
|
94
95
|
MultisigTapscript.encode = encode;
|
|
96
|
+
/** Decode a plain multisig tapscript from raw script bytes. */
|
|
95
97
|
function decode(script) {
|
|
96
98
|
if (script.length === 0) {
|
|
97
99
|
throw new Error("Failed to decode: script is empty");
|
|
@@ -204,6 +206,7 @@ export var MultisigTapscript;
|
|
|
204
206
|
script,
|
|
205
207
|
};
|
|
206
208
|
}
|
|
209
|
+
/** Return true when the tapscript is a plain multisig tapscript. */
|
|
207
210
|
function is(tapscript) {
|
|
208
211
|
return tapscript.type === TapscriptType.Multisig;
|
|
209
212
|
}
|
|
@@ -224,6 +227,7 @@ export var MultisigTapscript;
|
|
|
224
227
|
*/
|
|
225
228
|
export var CSVMultisigTapscript;
|
|
226
229
|
(function (CSVMultisigTapscript) {
|
|
230
|
+
/** Encode a CSV multisig tapscript. */
|
|
227
231
|
function encode(params) {
|
|
228
232
|
for (const pubkey of params.pubkeys) {
|
|
229
233
|
if (pubkey.length !== 32) {
|
|
@@ -250,6 +254,7 @@ export var CSVMultisigTapscript;
|
|
|
250
254
|
};
|
|
251
255
|
}
|
|
252
256
|
CSVMultisigTapscript.encode = encode;
|
|
257
|
+
/** Decode a CSV multisig tapscript from raw script bytes. */
|
|
253
258
|
function decode(script) {
|
|
254
259
|
if (script.length === 0) {
|
|
255
260
|
throw new Error("Failed to decode: script is empty");
|
|
@@ -301,6 +306,7 @@ export var CSVMultisigTapscript;
|
|
|
301
306
|
};
|
|
302
307
|
}
|
|
303
308
|
CSVMultisigTapscript.decode = decode;
|
|
309
|
+
/** Return true when the tapscript is a CSV multisig tapscript. */
|
|
304
310
|
function is(tapscript) {
|
|
305
311
|
return tapscript.type === TapscriptType.CSVMultisig;
|
|
306
312
|
}
|
|
@@ -320,6 +326,7 @@ export var CSVMultisigTapscript;
|
|
|
320
326
|
*/
|
|
321
327
|
export var ConditionCSVMultisigTapscript;
|
|
322
328
|
(function (ConditionCSVMultisigTapscript) {
|
|
329
|
+
/** Encode a condition + CSV multisig tapscript. */
|
|
323
330
|
function encode(params) {
|
|
324
331
|
const script = new Uint8Array([
|
|
325
332
|
...params.conditionScript,
|
|
@@ -333,6 +340,7 @@ export var ConditionCSVMultisigTapscript;
|
|
|
333
340
|
};
|
|
334
341
|
}
|
|
335
342
|
ConditionCSVMultisigTapscript.encode = encode;
|
|
343
|
+
/** Decode a condition + CSV multisig tapscript from raw script bytes. */
|
|
336
344
|
function decode(script) {
|
|
337
345
|
if (script.length === 0) {
|
|
338
346
|
throw new Error("Failed to decode: script is empty");
|
|
@@ -376,6 +384,7 @@ export var ConditionCSVMultisigTapscript;
|
|
|
376
384
|
};
|
|
377
385
|
}
|
|
378
386
|
ConditionCSVMultisigTapscript.decode = decode;
|
|
387
|
+
/** Return true when the tapscript is a condition + CSV multisig tapscript. */
|
|
379
388
|
function is(tapscript) {
|
|
380
389
|
return tapscript.type === TapscriptType.ConditionCSVMultisig;
|
|
381
390
|
}
|
|
@@ -395,6 +404,7 @@ export var ConditionCSVMultisigTapscript;
|
|
|
395
404
|
*/
|
|
396
405
|
export var ConditionMultisigTapscript;
|
|
397
406
|
(function (ConditionMultisigTapscript) {
|
|
407
|
+
/** Encode a condition + multisig tapscript. */
|
|
398
408
|
function encode(params) {
|
|
399
409
|
const script = new Uint8Array([
|
|
400
410
|
...params.conditionScript,
|
|
@@ -408,6 +418,7 @@ export var ConditionMultisigTapscript;
|
|
|
408
418
|
};
|
|
409
419
|
}
|
|
410
420
|
ConditionMultisigTapscript.encode = encode;
|
|
421
|
+
/** Decode a condition + multisig tapscript from raw script bytes. */
|
|
411
422
|
function decode(script) {
|
|
412
423
|
if (script.length === 0) {
|
|
413
424
|
throw new Error("Failed to decode: script is empty");
|
|
@@ -451,6 +462,7 @@ export var ConditionMultisigTapscript;
|
|
|
451
462
|
};
|
|
452
463
|
}
|
|
453
464
|
ConditionMultisigTapscript.decode = decode;
|
|
465
|
+
/** Return true when the tapscript is a condition + multisig tapscript. */
|
|
454
466
|
function is(tapscript) {
|
|
455
467
|
return tapscript.type === TapscriptType.ConditionMultisig;
|
|
456
468
|
}
|
|
@@ -470,6 +482,7 @@ export var ConditionMultisigTapscript;
|
|
|
470
482
|
*/
|
|
471
483
|
export var CLTVMultisigTapscript;
|
|
472
484
|
(function (CLTVMultisigTapscript) {
|
|
485
|
+
/** Encode a CLTV multisig tapscript. */
|
|
473
486
|
function encode(params) {
|
|
474
487
|
const locktime = MinimalScriptNum.encode(params.absoluteTimelock);
|
|
475
488
|
const asm = [
|
|
@@ -489,6 +502,7 @@ export var CLTVMultisigTapscript;
|
|
|
489
502
|
};
|
|
490
503
|
}
|
|
491
504
|
CLTVMultisigTapscript.encode = encode;
|
|
505
|
+
/** Decode a CLTV multisig tapscript from raw script bytes. */
|
|
492
506
|
function decode(script) {
|
|
493
507
|
if (script.length === 0) {
|
|
494
508
|
throw new Error("Failed to decode: script is empty");
|
|
@@ -498,7 +512,7 @@ export var CLTVMultisigTapscript;
|
|
|
498
512
|
throw new Error(`Invalid script: too short (expected at least 3)`);
|
|
499
513
|
}
|
|
500
514
|
const locktime = asm[0];
|
|
501
|
-
if (typeof locktime === "string"
|
|
515
|
+
if (typeof locktime === "string") {
|
|
502
516
|
throw new Error("Invalid script: expected locktime number");
|
|
503
517
|
}
|
|
504
518
|
if (asm[1] !== "CHECKLOCKTIMEVERIFY" || asm[2] !== "DROP") {
|
|
@@ -512,7 +526,13 @@ export var CLTVMultisigTapscript;
|
|
|
512
526
|
catch (error) {
|
|
513
527
|
throw new Error(`Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`);
|
|
514
528
|
}
|
|
515
|
-
|
|
529
|
+
let absoluteTimelock;
|
|
530
|
+
if (typeof locktime === "number") {
|
|
531
|
+
absoluteTimelock = BigInt(locktime);
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
absoluteTimelock = MinimalScriptNum.decode(locktime);
|
|
535
|
+
}
|
|
516
536
|
const reconstructed = encode({
|
|
517
537
|
absoluteTimelock,
|
|
518
538
|
...multisig.params,
|
|
@@ -530,6 +550,7 @@ export var CLTVMultisigTapscript;
|
|
|
530
550
|
};
|
|
531
551
|
}
|
|
532
552
|
CLTVMultisigTapscript.decode = decode;
|
|
553
|
+
/** Return true when the tapscript is a CLTV multisig tapscript. */
|
|
533
554
|
function is(tapscript) {
|
|
534
555
|
return tapscript.type === TapscriptType.CLTVMultisig;
|
|
535
556
|
}
|
package/dist/esm/script/vhtlc.js
CHANGED
|
@@ -2,36 +2,38 @@ import { Script } from "@scure/btc-signer";
|
|
|
2
2
|
import { CLTVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CSVMultisigTapscript, MultisigTapscript, } from './tapscript.js';
|
|
3
3
|
import { hex } from "@scure/base";
|
|
4
4
|
import { VtxoScript } from './base.js';
|
|
5
|
-
/**
|
|
6
|
-
* Virtual Hash Time Lock Contract (VHTLC) implementation.
|
|
7
|
-
*
|
|
8
|
-
* VHTLC is a contract that enables atomic swaps and conditional payments
|
|
9
|
-
* in the Ark protocol. It provides multiple spending paths:
|
|
10
|
-
*
|
|
11
|
-
* - **claim**: Receiver can claim funds by revealing the preimage
|
|
12
|
-
* - **refund**: Sender and receiver can collaboratively refund
|
|
13
|
-
* - **refundWithoutReceiver**: Sender can refund after locktime expires
|
|
14
|
-
* - **unilateralClaim**: Receiver can claim unilaterally after delay
|
|
15
|
-
* - **unilateralRefund**: Sender and receiver can refund unilaterally after delay
|
|
16
|
-
* - **unilateralRefundWithoutReceiver**: Sender can refund unilaterally after delay
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* const vhtlc = new VHTLC.Script({
|
|
21
|
-
* sender: alicePubKey,
|
|
22
|
-
* receiver: bobPubKey,
|
|
23
|
-
* server: serverPubKey,
|
|
24
|
-
* preimageHash: hash160(secret),
|
|
25
|
-
* refundLocktime: BigInt(chainTip + 10),
|
|
26
|
-
* unilateralClaimDelay: { type: 'blocks', value: 100n },
|
|
27
|
-
* unilateralRefundDelay: { type: 'blocks', value: 102n },
|
|
28
|
-
* unilateralRefundWithoutReceiverDelay: { type: 'blocks', value: 103n }
|
|
29
|
-
* });
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
5
|
+
/** Virtual Hash Time Lock Contract (VHTLC) namespace. */
|
|
32
6
|
export var VHTLC;
|
|
33
7
|
(function (VHTLC) {
|
|
8
|
+
/**
|
|
9
|
+
* Virtual Hash Time Lock Contract (VHTLC) script implementation.
|
|
10
|
+
*
|
|
11
|
+
* VHTLC enables atomic swaps and conditional payments in the Arkade protocol.
|
|
12
|
+
* 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
|
+
*/
|
|
34
35
|
class Script extends VtxoScript {
|
|
36
|
+
/** Create a VHTLC script from the supplied participant keys, hash, and timelocks. */
|
|
35
37
|
constructor(options) {
|
|
36
38
|
validateOptions(options);
|
|
37
39
|
const { sender, receiver, server, preimageHash, refundLocktime, unilateralClaimDelay, unilateralRefundDelay, unilateralRefundWithoutReceiverDelay, } = options;
|
|
@@ -76,21 +78,27 @@ export var VHTLC;
|
|
|
76
78
|
this.unilateralRefundScript = hex.encode(unilateralRefundScript);
|
|
77
79
|
this.unilateralRefundWithoutReceiverScript = hex.encode(unilateralRefundWithoutReceiverScript);
|
|
78
80
|
}
|
|
81
|
+
/** Return the collaborative claim tapleaf script. */
|
|
79
82
|
claim() {
|
|
80
83
|
return this.findLeaf(this.claimScript);
|
|
81
84
|
}
|
|
85
|
+
/** Return the collaborative refund tapleaf script. */
|
|
82
86
|
refund() {
|
|
83
87
|
return this.findLeaf(this.refundScript);
|
|
84
88
|
}
|
|
89
|
+
/** Return the refund-without-receiver tapleaf script. */
|
|
85
90
|
refundWithoutReceiver() {
|
|
86
91
|
return this.findLeaf(this.refundWithoutReceiverScript);
|
|
87
92
|
}
|
|
93
|
+
/** Return the unilateral claim tapleaf script. */
|
|
88
94
|
unilateralClaim() {
|
|
89
95
|
return this.findLeaf(this.unilateralClaimScript);
|
|
90
96
|
}
|
|
97
|
+
/** Return the unilateral refund tapleaf script. */
|
|
91
98
|
unilateralRefund() {
|
|
92
99
|
return this.findLeaf(this.unilateralRefundScript);
|
|
93
100
|
}
|
|
101
|
+
/** Return the unilateral refund-without-receiver tapleaf script. */
|
|
94
102
|
unilateralRefundWithoutReceiver() {
|
|
95
103
|
return this.findLeaf(this.unilateralRefundWithoutReceiverScript);
|
|
96
104
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DB_VERSION } from '../repositories/indexedDB/db.js';
|
|
2
2
|
/**
|
|
3
|
-
* @deprecated Use
|
|
3
|
+
* @deprecated Use repository implementations via `StorageConfig` instead.
|
|
4
4
|
*/
|
|
5
5
|
export class IndexedDBStorageAdapter {
|
|
6
6
|
constructor(dbName, version = DB_VERSION) {
|
|
@@ -32,7 +32,7 @@ export function validateConnectorsTxGraph(settlementTxB64, connectorsGraph) {
|
|
|
32
32
|
if (rootInput.index !== BATCH_OUTPUT_CONNECTORS_INDEX)
|
|
33
33
|
throw ErrWrongSettlementTxid;
|
|
34
34
|
}
|
|
35
|
-
// ValidateVtxoTxGraph checks if the given
|
|
35
|
+
// ValidateVtxoTxGraph checks if the given virtual output tx graph is valid.
|
|
36
36
|
// The function validates:
|
|
37
37
|
// - the number of nodes
|
|
38
38
|
// - the number of leaves
|
|
@@ -14,7 +14,7 @@ import { Extension } from '../extension/index.js';
|
|
|
14
14
|
*
|
|
15
15
|
* Creates one checkpoint transaction per input and a virtual transaction that
|
|
16
16
|
* combines all the checkpoints, sending to the specified outputs. This is the
|
|
17
|
-
* core function for creating
|
|
17
|
+
* core function for creating Arkade transactions.
|
|
18
18
|
*
|
|
19
19
|
* @param inputs - Array of virtual transaction inputs
|
|
20
20
|
* @param outputs - Array of transaction outputs
|
|
@@ -92,9 +92,9 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
92
92
|
return tx;
|
|
93
93
|
}
|
|
94
94
|
function buildCheckpointTx(vtxo, serverUnrollScript) {
|
|
95
|
-
// create the checkpoint
|
|
95
|
+
// create the checkpoint virtual output script from collaborative closure
|
|
96
96
|
const collaborativeClosure = decodeTapscript(scriptFromTapLeafScript(vtxo.tapLeafScript));
|
|
97
|
-
// create the checkpoint
|
|
97
|
+
// create the checkpoint virtual output script combining collaborative closure and server unroll script
|
|
98
98
|
const checkpointVtxoScript = new VtxoScript([
|
|
99
99
|
serverUnrollScript.script,
|
|
100
100
|
collaborativeClosure.script,
|
|
@@ -249,8 +249,8 @@ export function combineTapscriptSigs(signedTx, originalTx) {
|
|
|
249
249
|
return originalTx;
|
|
250
250
|
}
|
|
251
251
|
/**
|
|
252
|
-
* Validates if a given string is a valid
|
|
253
|
-
* @param address The
|
|
252
|
+
* Validates if a given string is a valid Arkade address by attempting to decode it.
|
|
253
|
+
* @param address The Arkade address to validate.
|
|
254
254
|
* @returns True if the address is valid, false otherwise.
|
|
255
255
|
*/
|
|
256
256
|
export function isValidArkAddress(address) {
|
package/dist/esm/utils/bip21.js
CHANGED
|
@@ -4,6 +4,12 @@ export var BIP21Error;
|
|
|
4
4
|
BIP21Error["INVALID_ADDRESS"] = "Invalid address";
|
|
5
5
|
})(BIP21Error || (BIP21Error = {}));
|
|
6
6
|
export class BIP21 {
|
|
7
|
+
/**
|
|
8
|
+
* Create a BIP21 URI from the provided parameters.
|
|
9
|
+
*
|
|
10
|
+
* @param params - BIP21 parameters to encode
|
|
11
|
+
* @returns Encoded BIP21 URI
|
|
12
|
+
*/
|
|
7
13
|
static create(params) {
|
|
8
14
|
const { address, ...options } = params;
|
|
9
15
|
// Build query string
|
|
@@ -22,7 +28,7 @@ export class BIP21 {
|
|
|
22
28
|
queryParams[key] = value;
|
|
23
29
|
}
|
|
24
30
|
else if (key === "ark") {
|
|
25
|
-
// Validate
|
|
31
|
+
// Validate Arkade address format
|
|
26
32
|
if (typeof value === "string" &&
|
|
27
33
|
(value.startsWith("ark") || value.startsWith("tark"))) {
|
|
28
34
|
queryParams[key] = value;
|
|
@@ -53,11 +59,18 @@ export class BIP21 {
|
|
|
53
59
|
: "";
|
|
54
60
|
return `bitcoin:${address ? address.toLowerCase() : ""}${query}`;
|
|
55
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Parse a BIP21 URI and return its decoded parameters.
|
|
64
|
+
*
|
|
65
|
+
* @param uri - BIP21 URI to parse
|
|
66
|
+
* @returns Parsed BIP21 URI data
|
|
67
|
+
* @throws Error if the URI does not start with the `bitcoin:` scheme
|
|
68
|
+
*/
|
|
56
69
|
static parse(uri) {
|
|
57
70
|
if (!uri.toLowerCase().startsWith("bitcoin:")) {
|
|
58
71
|
throw new Error(BIP21Error.INVALID_URI);
|
|
59
72
|
}
|
|
60
|
-
// Remove bitcoin
|
|
73
|
+
// Remove the `bitcoin:` prefix while preserving the case of the rest.
|
|
61
74
|
const withoutPrefix = uri.slice(uri.toLowerCase().indexOf("bitcoin:") + 8);
|
|
62
75
|
const [address, query] = withoutPrefix.split("?");
|
|
63
76
|
const params = {};
|
|
@@ -80,7 +93,7 @@ export class BIP21 {
|
|
|
80
93
|
params[key] = amount;
|
|
81
94
|
}
|
|
82
95
|
else if (key === "ark") {
|
|
83
|
-
// Validate
|
|
96
|
+
// Validate Arkade address format
|
|
84
97
|
if (value.startsWith("ark") || value.startsWith("tark")) {
|
|
85
98
|
params[key] = value;
|
|
86
99
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Lag behind real-time to avoid racing with indexer writes. */
|
|
2
2
|
export const SAFETY_LAG_MS = 30000;
|
|
3
|
-
/** Overlap window so boundary
|
|
3
|
+
/** Overlap window so boundary virtual outputs are never missed. */
|
|
4
4
|
export const OVERLAP_MS = 60000;
|
|
5
5
|
/**
|
|
6
6
|
* Per-repository mutex that serializes wallet-state mutations so that
|
|
@@ -101,8 +101,8 @@ export async function clearSyncCursors(repo, scripts) {
|
|
|
101
101
|
* Returns `undefined` when the script has no cursor (bootstrap needed).
|
|
102
102
|
*
|
|
103
103
|
* No upper bound (`before`) is applied to the query so that freshly
|
|
104
|
-
* created
|
|
105
|
-
* when advancing the cursor (see
|
|
104
|
+
* created virtual outputs are never excluded. The safety lag is applied only
|
|
105
|
+
* when advancing the cursor (see @see cursorCutoff).
|
|
106
106
|
*/
|
|
107
107
|
export function computeSyncWindow(cursor) {
|
|
108
108
|
if (cursor === undefined)
|
|
@@ -112,7 +112,7 @@ export function computeSyncWindow(cursor) {
|
|
|
112
112
|
}
|
|
113
113
|
/**
|
|
114
114
|
* The safe high-water mark for cursor advancement.
|
|
115
|
-
* Lags behind real-time by
|
|
115
|
+
* Lags behind real-time by @see SAFETY_LAG_MS so that virtual outputs still
|
|
116
116
|
* being indexed are re-queried on the next sync.
|
|
117
117
|
*
|
|
118
118
|
* When `requestStartedAt` is provided the cutoff is frozen to the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Transaction as BtcSignerTransaction } from "@scure/btc-signer";
|
|
2
2
|
/**
|
|
3
3
|
* Transaction is a wrapper around the @scure/btc-signer Transaction class.
|
|
4
|
-
* It adds the
|
|
4
|
+
* It adds the Arkade protocol specific options to the transaction.
|
|
5
5
|
*/
|
|
6
6
|
export class Transaction extends BtcSignerTransaction {
|
|
7
7
|
constructor(opts) {
|
|
@@ -45,13 +45,13 @@ function subtractAssets(spent, change) {
|
|
|
45
45
|
return Array.from(map, ([assetId, amount]) => ({ assetId, amount }));
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
|
-
* Builds the transaction history by analyzing virtual
|
|
48
|
+
* Builds the transaction history by analyzing virtual outputs, boarding transactions, and ignored commitments.
|
|
49
49
|
* History is sorted from newest to oldest and is composed only of SENT and RECEIVED transactions.
|
|
50
50
|
*
|
|
51
|
-
* @param {VirtualCoin[]} vtxos - An array of virtual
|
|
51
|
+
* @param {VirtualCoin[]} vtxos - An array of virtual outputs representing the user's transactions and balances.
|
|
52
52
|
* @param {ArkTransaction[]} allBoardingTxs - An array of boarding transactions to include in the history.
|
|
53
53
|
* @param {Set<string>} commitmentsToIgnore - A set of commitment IDs that should be excluded from processing.
|
|
54
|
-
* @return {ExtendedArkTransaction[]} A sorted array of extended
|
|
54
|
+
* @return {ExtendedArkTransaction[]} A sorted array of extended Arkade transactions, representing the transaction history.
|
|
55
55
|
*/
|
|
56
56
|
export async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnore, getTxCreatedAt) {
|
|
57
57
|
const fromOldestVtxo = [...vtxos].sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
|
|
@@ -59,7 +59,7 @@ export async function buildTransactionHistory(vtxos, allBoardingTxs, commitments
|
|
|
59
59
|
let received = [];
|
|
60
60
|
for (const vtxo of fromOldestVtxo) {
|
|
61
61
|
if (vtxo.status.isLeaf) {
|
|
62
|
-
// If this
|
|
62
|
+
// 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,
|
|
63
63
|
// it's translated into a received batch transaction
|
|
64
64
|
if (!commitmentsToIgnore.has(vtxo.virtualStatus.commitmentTxIds[0]) &&
|
|
65
65
|
fromOldestVtxo.filter((v) => v.settledBy === vtxo.virtualStatus.commitmentTxIds[0]).length === 0) {
|
|
@@ -79,7 +79,7 @@ export async function buildTransactionHistory(vtxos, allBoardingTxs, commitments
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
else if (fromOldestVtxo.filter((v) => v.arkTxId === vtxo.txid).length === 0) {
|
|
82
|
-
// If this
|
|
82
|
+
// If this virtual output is preconfirmed and does not spend any other virtual outputs,
|
|
83
83
|
// it's translated into a received offchain transaction
|
|
84
84
|
const assets = collectAssets([vtxo]);
|
|
85
85
|
received.push({
|
|
@@ -92,15 +92,15 @@ export async function buildTransactionHistory(vtxos, allBoardingTxs, commitments
|
|
|
92
92
|
...(assets && { assets }),
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
|
-
// If the
|
|
95
|
+
// If the virtual output is spent, it's translated into a sent transaction unless:
|
|
96
96
|
// - it's been refreshed (we don't want to add any record in this case)
|
|
97
|
-
// - a sent transaction has been already added to avoid duplicates (can happen if many
|
|
97
|
+
// - 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)
|
|
98
98
|
if (vtxo.isSpent) {
|
|
99
|
-
// If the
|
|
99
|
+
// If the virtual output is spent offchain, it's translated into an offchain sent tx
|
|
100
100
|
if (vtxo.arkTxId &&
|
|
101
101
|
!sent.some((s) => s.key.arkTxid === vtxo.arkTxId)) {
|
|
102
102
|
const changes = fromOldestVtxo.filter((_) => _.txid === vtxo.arkTxId);
|
|
103
|
-
// We want to find all the other
|
|
103
|
+
// We want to find all the other virtual outputs spent by the same transaction to
|
|
104
104
|
// calculate the full amount of the change.
|
|
105
105
|
const allSpent = fromOldestVtxo.filter((v) => v.arkTxId === vtxo.arkTxId);
|
|
106
106
|
const spentAmount = allSpent.reduce((acc, v) => acc + v.value, 0);
|
|
@@ -113,7 +113,7 @@ export async function buildTransactionHistory(vtxos, allBoardingTxs, commitments
|
|
|
113
113
|
}
|
|
114
114
|
else {
|
|
115
115
|
txAmount = spentAmount;
|
|
116
|
-
// TODO: fetch the
|
|
116
|
+
// TODO: fetch the virtual output with /v1/indexer/vtxos?outpoints=<vtxo.arkTxid:0> to know when the tx was made
|
|
117
117
|
txTime = getTxCreatedAt
|
|
118
118
|
? ((await getTxCreatedAt(vtxo.arkTxId)) ??
|
|
119
119
|
vtxo.createdAt.getTime() + 1)
|
|
@@ -130,7 +130,7 @@ export async function buildTransactionHistory(vtxos, allBoardingTxs, commitments
|
|
|
130
130
|
...(assets && { assets }),
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
|
-
// If the
|
|
133
|
+
// 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,
|
|
134
134
|
// it's translated into an exit sent tx
|
|
135
135
|
if (vtxo.settledBy &&
|
|
136
136
|
!commitmentsToIgnore.has(vtxo.settledBy) &&
|