@arkade-os/sdk 0.0.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.
Files changed (103) hide show
  1. package/README.md +312 -0
  2. package/dist/cjs/arknote/index.js +86 -0
  3. package/dist/cjs/forfeit.js +38 -0
  4. package/dist/cjs/identity/inMemoryKey.js +40 -0
  5. package/dist/cjs/identity/index.js +2 -0
  6. package/dist/cjs/index.js +48 -0
  7. package/dist/cjs/musig2/index.js +10 -0
  8. package/dist/cjs/musig2/keys.js +57 -0
  9. package/dist/cjs/musig2/nonces.js +44 -0
  10. package/dist/cjs/musig2/sign.js +102 -0
  11. package/dist/cjs/networks.js +26 -0
  12. package/dist/cjs/package.json +3 -0
  13. package/dist/cjs/providers/ark.js +530 -0
  14. package/dist/cjs/providers/onchain.js +61 -0
  15. package/dist/cjs/script/address.js +45 -0
  16. package/dist/cjs/script/base.js +51 -0
  17. package/dist/cjs/script/default.js +40 -0
  18. package/dist/cjs/script/tapscript.js +528 -0
  19. package/dist/cjs/script/vhtlc.js +84 -0
  20. package/dist/cjs/tree/signingSession.js +238 -0
  21. package/dist/cjs/tree/validation.js +184 -0
  22. package/dist/cjs/tree/vtxoTree.js +197 -0
  23. package/dist/cjs/utils/bip21.js +114 -0
  24. package/dist/cjs/utils/coinselect.js +73 -0
  25. package/dist/cjs/utils/psbt.js +124 -0
  26. package/dist/cjs/utils/transactionHistory.js +148 -0
  27. package/dist/cjs/utils/txSizeEstimator.js +95 -0
  28. package/dist/cjs/wallet/index.js +8 -0
  29. package/dist/cjs/wallet/serviceWorker/db/vtxo/idb.js +153 -0
  30. package/dist/cjs/wallet/serviceWorker/db/vtxo/index.js +2 -0
  31. package/dist/cjs/wallet/serviceWorker/request.js +75 -0
  32. package/dist/cjs/wallet/serviceWorker/response.js +187 -0
  33. package/dist/cjs/wallet/serviceWorker/wallet.js +332 -0
  34. package/dist/cjs/wallet/serviceWorker/worker.js +452 -0
  35. package/dist/cjs/wallet/wallet.js +720 -0
  36. package/dist/esm/arknote/index.js +81 -0
  37. package/dist/esm/forfeit.js +35 -0
  38. package/dist/esm/identity/inMemoryKey.js +36 -0
  39. package/dist/esm/identity/index.js +1 -0
  40. package/dist/esm/index.js +39 -0
  41. package/dist/esm/musig2/index.js +3 -0
  42. package/dist/esm/musig2/keys.js +21 -0
  43. package/dist/esm/musig2/nonces.js +8 -0
  44. package/dist/esm/musig2/sign.js +63 -0
  45. package/dist/esm/networks.js +22 -0
  46. package/dist/esm/package.json +3 -0
  47. package/dist/esm/providers/ark.js +526 -0
  48. package/dist/esm/providers/onchain.js +57 -0
  49. package/dist/esm/script/address.js +41 -0
  50. package/dist/esm/script/base.js +46 -0
  51. package/dist/esm/script/default.js +37 -0
  52. package/dist/esm/script/tapscript.js +491 -0
  53. package/dist/esm/script/vhtlc.js +81 -0
  54. package/dist/esm/tree/signingSession.js +200 -0
  55. package/dist/esm/tree/validation.js +179 -0
  56. package/dist/esm/tree/vtxoTree.js +157 -0
  57. package/dist/esm/utils/bip21.js +110 -0
  58. package/dist/esm/utils/coinselect.js +69 -0
  59. package/dist/esm/utils/psbt.js +118 -0
  60. package/dist/esm/utils/transactionHistory.js +145 -0
  61. package/dist/esm/utils/txSizeEstimator.js +91 -0
  62. package/dist/esm/wallet/index.js +5 -0
  63. package/dist/esm/wallet/serviceWorker/db/vtxo/idb.js +149 -0
  64. package/dist/esm/wallet/serviceWorker/db/vtxo/index.js +1 -0
  65. package/dist/esm/wallet/serviceWorker/request.js +72 -0
  66. package/dist/esm/wallet/serviceWorker/response.js +184 -0
  67. package/dist/esm/wallet/serviceWorker/wallet.js +328 -0
  68. package/dist/esm/wallet/serviceWorker/worker.js +448 -0
  69. package/dist/esm/wallet/wallet.js +716 -0
  70. package/dist/types/arknote/index.d.ts +17 -0
  71. package/dist/types/forfeit.d.ts +15 -0
  72. package/dist/types/identity/inMemoryKey.d.ts +12 -0
  73. package/dist/types/identity/index.d.ts +7 -0
  74. package/dist/types/index.d.ts +22 -0
  75. package/dist/types/musig2/index.d.ts +4 -0
  76. package/dist/types/musig2/keys.d.ts +9 -0
  77. package/dist/types/musig2/nonces.d.ts +13 -0
  78. package/dist/types/musig2/sign.d.ts +27 -0
  79. package/dist/types/networks.d.ts +16 -0
  80. package/dist/types/providers/ark.d.ts +126 -0
  81. package/dist/types/providers/onchain.d.ts +36 -0
  82. package/dist/types/script/address.d.ts +10 -0
  83. package/dist/types/script/base.d.ts +26 -0
  84. package/dist/types/script/default.d.ts +19 -0
  85. package/dist/types/script/tapscript.d.ts +94 -0
  86. package/dist/types/script/vhtlc.d.ts +31 -0
  87. package/dist/types/tree/signingSession.d.ts +32 -0
  88. package/dist/types/tree/validation.d.ts +22 -0
  89. package/dist/types/tree/vtxoTree.d.ts +32 -0
  90. package/dist/types/utils/bip21.d.ts +21 -0
  91. package/dist/types/utils/coinselect.d.ts +21 -0
  92. package/dist/types/utils/psbt.d.ts +11 -0
  93. package/dist/types/utils/transactionHistory.d.ts +2 -0
  94. package/dist/types/utils/txSizeEstimator.d.ts +27 -0
  95. package/dist/types/wallet/index.d.ts +122 -0
  96. package/dist/types/wallet/serviceWorker/db/vtxo/idb.d.ts +18 -0
  97. package/dist/types/wallet/serviceWorker/db/vtxo/index.d.ts +12 -0
  98. package/dist/types/wallet/serviceWorker/request.d.ts +68 -0
  99. package/dist/types/wallet/serviceWorker/response.d.ts +107 -0
  100. package/dist/types/wallet/serviceWorker/wallet.d.ts +23 -0
  101. package/dist/types/wallet/serviceWorker/worker.d.ts +26 -0
  102. package/dist/types/wallet/wallet.d.ts +42 -0
  103. package/package.json +88 -0
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BIP21 = exports.BIP21Error = void 0;
4
+ var BIP21Error;
5
+ (function (BIP21Error) {
6
+ BIP21Error["INVALID_URI"] = "Invalid BIP21 URI";
7
+ BIP21Error["INVALID_ADDRESS"] = "Invalid address";
8
+ })(BIP21Error || (exports.BIP21Error = BIP21Error = {}));
9
+ class BIP21 {
10
+ static create(params) {
11
+ const { address, ...options } = params;
12
+ // Build query string
13
+ const queryParams = {};
14
+ for (const [key, value] of Object.entries(options)) {
15
+ if (value === undefined)
16
+ continue;
17
+ if (key === "amount") {
18
+ if (!isFinite(value)) {
19
+ console.warn("Invalid amount");
20
+ continue;
21
+ }
22
+ if (value < 0) {
23
+ continue;
24
+ }
25
+ queryParams[key] = value;
26
+ }
27
+ else if (key === "ark") {
28
+ // Validate ARK address format
29
+ if (typeof value === "string" &&
30
+ (value.startsWith("ark") || value.startsWith("tark"))) {
31
+ queryParams[key] = value;
32
+ }
33
+ else {
34
+ console.warn("Invalid ARK address format");
35
+ }
36
+ }
37
+ else if (key === "sp") {
38
+ // Validate Silent Payment address format (placeholder)
39
+ if (typeof value === "string" && value.startsWith("sp")) {
40
+ queryParams[key] = value;
41
+ }
42
+ else {
43
+ console.warn("Invalid Silent Payment address format");
44
+ }
45
+ }
46
+ else if (typeof value === "string" || typeof value === "number") {
47
+ queryParams[key] = value;
48
+ }
49
+ }
50
+ const query = Object.keys(queryParams).length > 0
51
+ ? "?" +
52
+ new URLSearchParams(Object.fromEntries(Object.entries(queryParams).map(([k, v]) => [
53
+ k,
54
+ String(v),
55
+ ]))).toString()
56
+ : "";
57
+ return `bitcoin:${address ? address.toLowerCase() : ""}${query}`;
58
+ }
59
+ static parse(uri) {
60
+ if (!uri.toLowerCase().startsWith("bitcoin:")) {
61
+ throw new Error(BIP21Error.INVALID_URI);
62
+ }
63
+ // Remove bitcoin: prefix, preserving case of the rest
64
+ const withoutPrefix = uri.slice(uri.toLowerCase().indexOf("bitcoin:") + 8);
65
+ const [address, query] = withoutPrefix.split("?");
66
+ const params = {};
67
+ if (address) {
68
+ params.address = address.toLowerCase();
69
+ }
70
+ if (query) {
71
+ const queryParams = new URLSearchParams(query);
72
+ for (const [key, value] of queryParams.entries()) {
73
+ if (!value)
74
+ continue;
75
+ if (key === "amount") {
76
+ const amount = Number(value);
77
+ if (!isFinite(amount)) {
78
+ continue;
79
+ }
80
+ if (amount < 0) {
81
+ continue;
82
+ }
83
+ params[key] = amount;
84
+ }
85
+ else if (key === "ark") {
86
+ // Validate ARK address format
87
+ if (value.startsWith("ark") || value.startsWith("tark")) {
88
+ params[key] = value;
89
+ }
90
+ else {
91
+ console.warn("Invalid ARK address format");
92
+ }
93
+ }
94
+ else if (key === "sp") {
95
+ // Validate Silent Payment address format (placeholder)
96
+ if (value.startsWith("sp")) {
97
+ params[key] = value;
98
+ }
99
+ else {
100
+ console.warn("Invalid Silent Payment address format");
101
+ }
102
+ }
103
+ else {
104
+ params[key] = value;
105
+ }
106
+ }
107
+ }
108
+ return {
109
+ originalString: uri,
110
+ params,
111
+ };
112
+ }
113
+ }
114
+ exports.BIP21 = BIP21;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.selectCoins = selectCoins;
4
+ exports.selectVirtualCoins = selectVirtualCoins;
5
+ /**
6
+ * Select coins to reach a target amount, prioritizing those closer to expiry
7
+ * @param coins List of coins to select from
8
+ * @param targetAmount Target amount to reach in satoshis
9
+ * @returns Selected coins and change amount, or null if insufficient funds
10
+ */
11
+ function selectCoins(coins, targetAmount) {
12
+ // Sort coins by amount (descending)
13
+ const sortedCoins = [...coins].sort((a, b) => b.value - a.value);
14
+ const selectedCoins = [];
15
+ let selectedAmount = 0;
16
+ // Select coins until we have enough
17
+ for (const coin of sortedCoins) {
18
+ selectedCoins.push(coin);
19
+ selectedAmount += coin.value;
20
+ if (selectedAmount >= targetAmount) {
21
+ break;
22
+ }
23
+ }
24
+ // Check if we have enough
25
+ if (selectedAmount < targetAmount) {
26
+ return { inputs: null, changeAmount: 0 };
27
+ }
28
+ // Calculate change
29
+ const changeAmount = selectedAmount - targetAmount;
30
+ return {
31
+ inputs: selectedCoins,
32
+ changeAmount,
33
+ };
34
+ }
35
+ /**
36
+ * Select virtual coins to reach a target amount, prioritizing those closer to expiry
37
+ * @param coins List of virtual coins to select from
38
+ * @param targetAmount Target amount to reach in satoshis
39
+ * @returns Selected coins and change amount, or null if insufficient funds
40
+ */
41
+ function selectVirtualCoins(coins, targetAmount) {
42
+ // Sort VTXOs by expiry (ascending) and amount (descending)
43
+ const sortedCoins = [...coins].sort((a, b) => {
44
+ // First sort by expiry if available
45
+ const expiryA = a.virtualStatus.batchExpiry || Number.MAX_SAFE_INTEGER;
46
+ const expiryB = b.virtualStatus.batchExpiry || Number.MAX_SAFE_INTEGER;
47
+ if (expiryA !== expiryB) {
48
+ return expiryA - expiryB; // Earlier expiry first
49
+ }
50
+ // Then sort by amount
51
+ return b.value - a.value; // Larger amount first
52
+ });
53
+ const selectedCoins = [];
54
+ let selectedAmount = 0;
55
+ // Select coins until we have enough
56
+ for (const coin of sortedCoins) {
57
+ selectedCoins.push(coin);
58
+ selectedAmount += coin.value;
59
+ if (selectedAmount >= targetAmount) {
60
+ break;
61
+ }
62
+ }
63
+ // Check if we have enough
64
+ if (selectedAmount < targetAmount) {
65
+ return { inputs: null, changeAmount: 0 };
66
+ }
67
+ // Calculate change
68
+ const changeAmount = selectedAmount - targetAmount;
69
+ return {
70
+ inputs: selectedCoins,
71
+ changeAmount,
72
+ };
73
+ }
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VTXO_TAPROOT_TREE_KEY_PREFIX = exports.CONDITION_WITNESS_KEY_PREFIX = void 0;
4
+ exports.addVtxoTaprootTree = addVtxoTaprootTree;
5
+ exports.addConditionWitness = addConditionWitness;
6
+ exports.createVirtualTx = createVirtualTx;
7
+ const btc_signer_1 = require("@scure/btc-signer");
8
+ const tapscript_1 = require("../script/tapscript");
9
+ const base_1 = require("../script/base");
10
+ const address_1 = require("../script/address");
11
+ const base_2 = require("@scure/base");
12
+ const ARK_UNKNOWN_KEY_TYPE = 255;
13
+ // Constant for condition witness key prefix
14
+ exports.CONDITION_WITNESS_KEY_PREFIX = new TextEncoder().encode("condition");
15
+ exports.VTXO_TAPROOT_TREE_KEY_PREFIX = new TextEncoder().encode("taptree");
16
+ function addVtxoTaprootTree(inIndex, tx, scripts) {
17
+ tx.updateInput(inIndex, {
18
+ unknown: [
19
+ ...(tx.getInput(inIndex)?.unknown ?? []),
20
+ [
21
+ {
22
+ type: ARK_UNKNOWN_KEY_TYPE,
23
+ key: exports.VTXO_TAPROOT_TREE_KEY_PREFIX,
24
+ },
25
+ encodeTaprootTree(scripts),
26
+ ],
27
+ ],
28
+ });
29
+ }
30
+ function addConditionWitness(inIndex, tx, witness) {
31
+ const witnessBytes = btc_signer_1.RawWitness.encode(witness);
32
+ tx.updateInput(inIndex, {
33
+ unknown: [
34
+ ...(tx.getInput(inIndex)?.unknown ?? []),
35
+ [
36
+ {
37
+ type: ARK_UNKNOWN_KEY_TYPE,
38
+ key: exports.CONDITION_WITNESS_KEY_PREFIX,
39
+ },
40
+ witnessBytes,
41
+ ],
42
+ ],
43
+ });
44
+ }
45
+ function createVirtualTx(inputs, outputs) {
46
+ let lockTime;
47
+ for (const input of inputs) {
48
+ const tapscript = (0, tapscript_1.decodeTapscript)((0, base_1.scriptFromTapLeafScript)(input.tapLeafScript));
49
+ if (tapscript_1.CLTVMultisigTapscript.is(tapscript)) {
50
+ lockTime = Number(tapscript.params.absoluteTimelock);
51
+ }
52
+ }
53
+ const tx = new btc_signer_1.Transaction({
54
+ allowUnknown: true,
55
+ lockTime,
56
+ });
57
+ for (const [i, input] of inputs.entries()) {
58
+ tx.addInput({
59
+ txid: input.txid,
60
+ index: input.vout,
61
+ sequence: lockTime ? btc_signer_1.DEFAULT_SEQUENCE - 1 : undefined,
62
+ witnessUtxo: {
63
+ script: base_1.VtxoScript.decode(input.scripts).pkScript,
64
+ amount: BigInt(input.value),
65
+ },
66
+ tapLeafScript: [input.tapLeafScript],
67
+ });
68
+ // add BIP371 encoded taproot tree to the unknown key field
69
+ addVtxoTaprootTree(i, tx, input.scripts.map(base_2.hex.decode));
70
+ }
71
+ for (const output of outputs) {
72
+ tx.addOutput({
73
+ amount: output.amount,
74
+ script: address_1.ArkAddress.decode(output.address).pkScript,
75
+ });
76
+ }
77
+ return tx;
78
+ }
79
+ function encodeTaprootTree(leaves) {
80
+ const chunks = [];
81
+ // Write number of leaves as compact size uint
82
+ chunks.push(encodeCompactSizeUint(leaves.length));
83
+ for (const tapscript of leaves) {
84
+ // Write depth (always 1 for now)
85
+ chunks.push(new Uint8Array([1]));
86
+ // Write leaf version (0xc0 for tapscript)
87
+ chunks.push(new Uint8Array([0xc0]));
88
+ // Write script length and script
89
+ chunks.push(encodeCompactSizeUint(tapscript.length));
90
+ chunks.push(tapscript);
91
+ }
92
+ // Concatenate all chunks
93
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
94
+ const result = new Uint8Array(totalLength);
95
+ let offset = 0;
96
+ for (const chunk of chunks) {
97
+ result.set(chunk, offset);
98
+ offset += chunk.length;
99
+ }
100
+ return result;
101
+ }
102
+ function encodeCompactSizeUint(value) {
103
+ if (value < 0xfd) {
104
+ return new Uint8Array([value]);
105
+ }
106
+ else if (value <= 0xffff) {
107
+ const buffer = new Uint8Array(3);
108
+ buffer[0] = 0xfd;
109
+ new DataView(buffer.buffer).setUint16(1, value, true);
110
+ return buffer;
111
+ }
112
+ else if (value <= 0xffffffff) {
113
+ const buffer = new Uint8Array(5);
114
+ buffer[0] = 0xfe;
115
+ new DataView(buffer.buffer).setUint32(1, value, true);
116
+ return buffer;
117
+ }
118
+ else {
119
+ const buffer = new Uint8Array(9);
120
+ buffer[0] = 0xff;
121
+ new DataView(buffer.buffer).setBigUint64(1, BigInt(value), true);
122
+ return buffer;
123
+ }
124
+ }
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.vtxosToTxs = vtxosToTxs;
4
+ const wallet_1 = require("../wallet");
5
+ /**
6
+ * Helper function to find vtxos that were spent in a settlement
7
+ */
8
+ function findVtxosSpentInSettlement(vtxos, vtxo) {
9
+ if (vtxo.virtualStatus.state === "pending") {
10
+ return [];
11
+ }
12
+ return vtxos.filter((v) => {
13
+ if (!v.spentBy)
14
+ return false;
15
+ return v.spentBy === vtxo.virtualStatus.batchTxID;
16
+ });
17
+ }
18
+ /**
19
+ * Helper function to find vtxos that were spent in a payment
20
+ */
21
+ function findVtxosSpentInPayment(vtxos, vtxo) {
22
+ return vtxos.filter((v) => {
23
+ if (!v.spentBy)
24
+ return false;
25
+ return v.spentBy === vtxo.txid;
26
+ });
27
+ }
28
+ /**
29
+ * Helper function to find vtxos that resulted from a spentBy transaction
30
+ */
31
+ function findVtxosResultedFromSpentBy(vtxos, spentBy) {
32
+ return vtxos.filter((v) => {
33
+ if (v.virtualStatus.state !== "pending" &&
34
+ v.virtualStatus.batchTxID === spentBy) {
35
+ return true;
36
+ }
37
+ return v.txid === spentBy;
38
+ });
39
+ }
40
+ /**
41
+ * Helper function to reduce vtxos to their total amount
42
+ */
43
+ function reduceVtxosAmount(vtxos) {
44
+ return vtxos.reduce((sum, v) => sum + v.value, 0);
45
+ }
46
+ /**
47
+ * Helper function to get a vtxo from a list of vtxos
48
+ */
49
+ function getVtxo(resultedVtxos, spentVtxos) {
50
+ if (resultedVtxos.length === 0) {
51
+ return spentVtxos[0];
52
+ }
53
+ return resultedVtxos[0];
54
+ }
55
+ function vtxosToTxs(spendable, spent, boardingRounds) {
56
+ const txs = [];
57
+ // Receive case
58
+ // All vtxos are received unless:
59
+ // - they resulted from a settlement (either boarding or refresh)
60
+ // - they are the change of a spend tx
61
+ let vtxosLeftToCheck = [...spent];
62
+ for (const vtxo of [...spendable, ...spent]) {
63
+ if (vtxo.virtualStatus.state !== "pending" &&
64
+ boardingRounds.has(vtxo.virtualStatus.batchTxID || "")) {
65
+ continue;
66
+ }
67
+ const settleVtxos = findVtxosSpentInSettlement(vtxosLeftToCheck, vtxo);
68
+ vtxosLeftToCheck = removeVtxosFromList(vtxosLeftToCheck, settleVtxos);
69
+ const settleAmount = reduceVtxosAmount(settleVtxos);
70
+ if (vtxo.value <= settleAmount) {
71
+ continue; // settlement or change, ignore
72
+ }
73
+ const spentVtxos = findVtxosSpentInPayment(vtxosLeftToCheck, vtxo);
74
+ vtxosLeftToCheck = removeVtxosFromList(vtxosLeftToCheck, spentVtxos);
75
+ const spentAmount = reduceVtxosAmount(spentVtxos);
76
+ if (vtxo.value <= spentAmount) {
77
+ continue; // settlement or change, ignore
78
+ }
79
+ const txKey = {
80
+ roundTxid: vtxo.virtualStatus.batchTxID || "",
81
+ boardingTxid: "",
82
+ redeemTxid: "",
83
+ };
84
+ let settled = vtxo.virtualStatus.state !== "pending";
85
+ if (vtxo.virtualStatus.state === "pending") {
86
+ txKey.redeemTxid = vtxo.txid;
87
+ if (vtxo.spentBy) {
88
+ settled = true;
89
+ }
90
+ }
91
+ txs.push({
92
+ key: txKey,
93
+ amount: vtxo.value - settleAmount - spentAmount,
94
+ type: wallet_1.TxType.TxReceived,
95
+ createdAt: vtxo.createdAt.getTime(),
96
+ settled,
97
+ });
98
+ }
99
+ // send case
100
+ // All "spentBy" vtxos are payments unless:
101
+ // - they are settlements
102
+ // aggregate spent by spentId
103
+ const vtxosBySpentBy = new Map();
104
+ for (const v of spent) {
105
+ if (!v.spentBy)
106
+ continue;
107
+ if (!vtxosBySpentBy.has(v.spentBy)) {
108
+ vtxosBySpentBy.set(v.spentBy, []);
109
+ }
110
+ const currentVtxos = vtxosBySpentBy.get(v.spentBy);
111
+ vtxosBySpentBy.set(v.spentBy, [...currentVtxos, v]);
112
+ }
113
+ for (const [sb, vtxos] of vtxosBySpentBy) {
114
+ const resultedVtxos = findVtxosResultedFromSpentBy([...spendable, ...spent], sb);
115
+ const resultedAmount = reduceVtxosAmount(resultedVtxos);
116
+ const spentAmount = reduceVtxosAmount(vtxos);
117
+ if (spentAmount <= resultedAmount) {
118
+ continue; // settlement or change, ignore
119
+ }
120
+ const vtxo = getVtxo(resultedVtxos, vtxos);
121
+ const txKey = {
122
+ roundTxid: vtxo.virtualStatus.batchTxID || "",
123
+ boardingTxid: "",
124
+ redeemTxid: "",
125
+ };
126
+ if (vtxo.virtualStatus.state === "pending") {
127
+ txKey.redeemTxid = vtxo.txid;
128
+ }
129
+ txs.push({
130
+ key: txKey,
131
+ amount: spentAmount - resultedAmount,
132
+ type: wallet_1.TxType.TxSent,
133
+ createdAt: vtxo.createdAt.getTime(),
134
+ settled: true,
135
+ });
136
+ }
137
+ return txs;
138
+ }
139
+ function removeVtxosFromList(vtxos, vtxosToRemove) {
140
+ return vtxos.filter((v) => {
141
+ for (const vtxoToRemove of vtxosToRemove) {
142
+ if (v.txid === vtxoToRemove.txid && v.vout === vtxoToRemove.vout) {
143
+ return false;
144
+ }
145
+ }
146
+ return true;
147
+ });
148
+ }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TxWeightEstimator = void 0;
4
+ class TxWeightEstimator {
5
+ constructor(hasWitness, inputCount, outputCount, inputSize, inputWitnessSize, outputSize) {
6
+ this.hasWitness = hasWitness;
7
+ this.inputCount = inputCount;
8
+ this.outputCount = outputCount;
9
+ this.inputSize = inputSize;
10
+ this.inputWitnessSize = inputWitnessSize;
11
+ this.outputSize = outputSize;
12
+ }
13
+ static create() {
14
+ return new TxWeightEstimator(false, 0, 0, 0, 0, 0);
15
+ }
16
+ addKeySpendInput(isDefault = true) {
17
+ this.inputCount++;
18
+ this.inputWitnessSize += 64 + 1 + (isDefault ? 0 : 1);
19
+ this.inputSize += TxWeightEstimator.INPUT_SIZE;
20
+ this.hasWitness = true;
21
+ return this;
22
+ }
23
+ addP2PKHInput() {
24
+ this.inputCount++;
25
+ this.inputWitnessSize++;
26
+ this.inputSize +=
27
+ TxWeightEstimator.INPUT_SIZE +
28
+ TxWeightEstimator.P2PKH_SCRIPT_SIG_SIZE;
29
+ return this;
30
+ }
31
+ addTapscriptInput(leafWitnessSize, leafScriptSize, leafControlBlockSize) {
32
+ const controlBlockWitnessSize = 1 +
33
+ TxWeightEstimator.BASE_CONTROL_BLOCK_SIZE +
34
+ 1 +
35
+ leafScriptSize +
36
+ 1 +
37
+ leafControlBlockSize;
38
+ this.inputCount++;
39
+ this.inputWitnessSize += leafWitnessSize + controlBlockWitnessSize;
40
+ this.inputSize += TxWeightEstimator.INPUT_SIZE;
41
+ this.hasWitness = true;
42
+ this.inputCount++;
43
+ return this;
44
+ }
45
+ addP2WKHOutput() {
46
+ this.outputCount++;
47
+ this.outputSize +=
48
+ TxWeightEstimator.OUTPUT_SIZE + TxWeightEstimator.P2WKH_OUTPUT_SIZE;
49
+ return this;
50
+ }
51
+ vsize() {
52
+ const getVarIntSize = (n) => {
53
+ if (n < 0xfd)
54
+ return 1;
55
+ if (n < 0xffff)
56
+ return 3;
57
+ if (n < 0xffffffff)
58
+ return 5;
59
+ return 9;
60
+ };
61
+ const inputCount = getVarIntSize(this.inputCount);
62
+ const outputCount = getVarIntSize(this.outputCount);
63
+ // Calculate the size of the transaction without witness data
64
+ const txSizeStripped = TxWeightEstimator.BASE_TX_SIZE +
65
+ inputCount +
66
+ this.inputSize +
67
+ outputCount +
68
+ this.outputSize;
69
+ // Calculate the total weight
70
+ let weight = txSizeStripped * TxWeightEstimator.WITNESS_SCALE_FACTOR;
71
+ // Add witness data if present
72
+ if (this.hasWitness) {
73
+ weight +=
74
+ TxWeightEstimator.WITNESS_HEADER_SIZE + this.inputWitnessSize;
75
+ }
76
+ // Convert weight to vsize (weight / 4, rounded up)
77
+ return vsize(weight);
78
+ }
79
+ }
80
+ exports.TxWeightEstimator = TxWeightEstimator;
81
+ TxWeightEstimator.P2PKH_SCRIPT_SIG_SIZE = 1 + 73 + 1 + 33;
82
+ TxWeightEstimator.INPUT_SIZE = 32 + 4 + 1 + 4;
83
+ TxWeightEstimator.BASE_CONTROL_BLOCK_SIZE = 1 + 32;
84
+ TxWeightEstimator.OUTPUT_SIZE = 8 + 1;
85
+ TxWeightEstimator.P2WKH_OUTPUT_SIZE = 1 + 1 + 20;
86
+ TxWeightEstimator.BASE_TX_SIZE = 8 + 2; // Version + LockTime
87
+ TxWeightEstimator.WITNESS_HEADER_SIZE = 2; // Flag + Marker
88
+ TxWeightEstimator.WITNESS_SCALE_FACTOR = 4;
89
+ const vsize = (weight) => {
90
+ const value = BigInt(Math.ceil(weight / TxWeightEstimator.WITNESS_SCALE_FACTOR));
91
+ return {
92
+ value,
93
+ fee: (feeRate) => feeRate * value,
94
+ };
95
+ };
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TxType = void 0;
4
+ var TxType;
5
+ (function (TxType) {
6
+ TxType["TxSent"] = "SENT";
7
+ TxType["TxReceived"] = "RECEIVED";
8
+ })(TxType || (exports.TxType = TxType = {}));