@buildonspark/spark-sdk 0.1.44 → 0.1.46
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/CHANGELOG.md +17 -0
- package/dist/{RequestLightningSendInput-BxbCtwpV.d.cts → RequestLightningSendInput-2cSh_In4.d.cts} +1 -1
- package/dist/{RequestLightningSendInput-RGel43ks.d.ts → RequestLightningSendInput-CN6BNg_g.d.ts} +1 -1
- package/dist/address/index.cjs +2 -2
- package/dist/address/index.d.cts +2 -2
- package/dist/address/index.d.ts +2 -2
- package/dist/address/index.js +2 -2
- package/dist/{chunk-EKFD62HN.js → chunk-4EMV7HHW.js} +2 -1
- package/dist/{chunk-4Q2ZDYYU.js → chunk-BGGEVUJK.js} +1157 -208
- package/dist/{chunk-CIZNCBKE.js → chunk-C2S227QR.js} +648 -45
- package/dist/{chunk-WPTRVD2V.js → chunk-DXR2PXJU.js} +15 -15
- package/dist/{chunk-NBCNYDWJ.js → chunk-HHNQ3ZHC.js} +2 -2
- package/dist/{chunk-DAXGVPVM.js → chunk-HSCLBJEL.js} +2 -2
- package/dist/{chunk-6AFUC5M2.js → chunk-HWJWKEIU.js} +8 -2
- package/dist/{chunk-A2ZLMH6I.js → chunk-JB64OQES.js} +259 -327
- package/dist/{chunk-KEKGSH7B.js → chunk-KMUMFYFX.js} +3 -3
- package/dist/chunk-LHRD2WT6.js +2374 -0
- package/dist/{chunk-HTMXTJRK.js → chunk-N5VZVCGJ.js} +4 -4
- package/dist/{chunk-SQKXGAIR.js → chunk-NTFKFRQ2.js} +1 -1
- package/dist/{chunk-K4BJARWM.js → chunk-OBFKIEMP.js} +1 -1
- package/dist/{chunk-UBT6EDVJ.js → chunk-OFCJFZ4I.js} +1 -1
- package/dist/{chunk-XX4RRWOX.js → chunk-UXDODSDT.js} +8 -10
- package/dist/graphql/objects/index.d.cts +5 -4
- package/dist/graphql/objects/index.d.ts +5 -4
- package/dist/index-CKL5DodV.d.cts +214 -0
- package/dist/index-COm59SPw.d.ts +214 -0
- package/dist/index.cjs +4026 -1315
- package/dist/index.d.cts +764 -19
- package/dist/index.d.ts +764 -19
- package/dist/index.js +23 -27
- package/dist/index.node.cjs +4026 -1319
- package/dist/index.node.d.cts +10 -8
- package/dist/index.node.d.ts +10 -8
- package/dist/index.node.js +23 -31
- package/dist/native/index.cjs +4027 -1316
- package/dist/native/index.d.cts +281 -85
- package/dist/native/index.d.ts +281 -85
- package/dist/native/index.js +4018 -1307
- package/dist/{network-CfxLnaot.d.cts → network-Css46DAz.d.cts} +1 -1
- package/dist/{network-CroCOQ0B.d.ts → network-hynb7iTZ.d.ts} +1 -1
- package/dist/proto/lrc20.cjs +222 -19
- package/dist/proto/lrc20.d.cts +1 -1
- package/dist/proto/lrc20.d.ts +1 -1
- package/dist/proto/lrc20.js +2 -2
- package/dist/proto/spark.cjs +1154 -205
- package/dist/proto/spark.d.cts +1 -1
- package/dist/proto/spark.d.ts +1 -1
- package/dist/proto/spark.js +3 -1
- package/dist/proto/spark_token.cjs +1377 -58
- package/dist/proto/spark_token.d.cts +153 -15
- package/dist/proto/spark_token.d.ts +153 -15
- package/dist/proto/spark_token.js +40 -4
- package/dist/{sdk-types-CTbTdDbE.d.ts → sdk-types-CKBsylfW.d.ts} +1 -1
- package/dist/{sdk-types-BeCBoozO.d.cts → sdk-types-Ct8xmN7l.d.cts} +1 -1
- package/dist/services/config.cjs +2 -2
- package/dist/services/config.d.cts +5 -4
- package/dist/services/config.d.ts +5 -4
- package/dist/services/config.js +6 -6
- package/dist/services/connection.cjs +2438 -262
- package/dist/services/connection.d.cts +5 -4
- package/dist/services/connection.d.ts +5 -4
- package/dist/services/connection.js +4 -4
- package/dist/services/index.cjs +5937 -3154
- package/dist/services/index.d.cts +7 -6
- package/dist/services/index.d.ts +7 -6
- package/dist/services/index.js +17 -15
- package/dist/services/lrc-connection.cjs +223 -20
- package/dist/services/lrc-connection.d.cts +5 -4
- package/dist/services/lrc-connection.d.ts +5 -4
- package/dist/services/lrc-connection.js +4 -4
- package/dist/services/token-transactions.cjs +840 -236
- package/dist/services/token-transactions.d.cts +25 -7
- package/dist/services/token-transactions.d.ts +25 -7
- package/dist/services/token-transactions.js +5 -4
- package/dist/services/wallet-config.cjs +3 -1
- package/dist/services/wallet-config.d.cts +7 -5
- package/dist/services/wallet-config.d.ts +7 -5
- package/dist/services/wallet-config.js +3 -1
- package/dist/signer/signer.cjs +1 -1
- package/dist/signer/signer.d.cts +3 -2
- package/dist/signer/signer.d.ts +3 -2
- package/dist/signer/signer.js +2 -2
- package/dist/{signer-D7vfYik9.d.ts → signer-BP6F__oR.d.cts} +2 -6
- package/dist/{signer-DaY8c60s.d.cts → signer-BVZJXcq7.d.ts} +2 -6
- package/dist/{spark-C4ZrsgjC.d.cts → spark-DbzGfse6.d.cts} +93 -15
- package/dist/{spark-C4ZrsgjC.d.ts → spark-DbzGfse6.d.ts} +93 -15
- package/dist/spark_bindings/native/index.cjs +183 -0
- package/dist/spark_bindings/native/index.d.cts +14 -0
- package/dist/spark_bindings/native/index.d.ts +14 -0
- package/dist/spark_bindings/native/index.js +141 -0
- package/dist/spark_bindings/wasm/index.cjs +1093 -0
- package/dist/spark_bindings/wasm/index.d.cts +47 -0
- package/dist/spark_bindings/wasm/index.d.ts +47 -0
- package/dist/{chunk-K4C4W5FC.js → spark_bindings/wasm/index.js} +7 -6
- package/dist/types/index.cjs +1156 -208
- package/dist/types/index.d.cts +5 -4
- package/dist/types/index.d.ts +5 -4
- package/dist/types/index.js +2 -2
- package/dist/types-C-Rp0Oo7.d.cts +46 -0
- package/dist/types-C-Rp0Oo7.d.ts +46 -0
- package/dist/utils/index.cjs +65 -13
- package/dist/utils/index.d.cts +14 -134
- package/dist/utils/index.d.ts +14 -134
- package/dist/utils/index.js +13 -13
- package/package.json +22 -2
- package/src/index.node.ts +0 -1
- package/src/index.ts +0 -1
- package/src/native/index.ts +1 -2
- package/src/proto/common.ts +5 -5
- package/src/proto/google/protobuf/descriptor.ts +34 -34
- package/src/proto/google/protobuf/duration.ts +2 -2
- package/src/proto/google/protobuf/empty.ts +2 -2
- package/src/proto/google/protobuf/timestamp.ts +2 -2
- package/src/proto/mock.ts +4 -4
- package/src/proto/spark.ts +1452 -185
- package/src/proto/spark_authn.ts +7 -7
- package/src/proto/spark_token.ts +1668 -105
- package/src/proto/validate/validate.ts +24 -24
- package/src/services/bolt11-spark.ts +62 -187
- package/src/services/coop-exit.ts +3 -0
- package/src/services/lrc20.ts +1 -1
- package/src/services/token-transactions.ts +197 -9
- package/src/services/transfer.ts +22 -0
- package/src/services/tree-creation.ts +13 -0
- package/src/services/wallet-config.ts +2 -2
- package/src/spark-wallet/spark-wallet.node.ts +0 -4
- package/src/spark-wallet/spark-wallet.ts +76 -108
- package/src/spark-wallet/types.ts +39 -3
- package/src/tests/bolt11-spark.test.ts +7 -15
- package/src/tests/integration/ssp/coop-exit.test.ts +7 -7
- package/src/tests/integration/swap.test.ts +453 -433
- package/src/tests/integration/transfer.test.ts +261 -248
- package/src/tests/token-identifier.test.ts +54 -0
- package/src/tests/tokens.test.ts +218 -23
- package/src/utils/token-hashing.ts +320 -44
- package/src/utils/token-identifier.ts +88 -0
- package/src/utils/token-transaction-validation.ts +350 -5
- package/src/utils/token-transactions.ts +12 -8
- package/src/utils/transaction.ts +0 -6
- package/dist/chunk-B3AMIGJG.js +0 -1073
- package/dist/index-CZmDdSts.d.cts +0 -829
- package/dist/index-ClIRO_3y.d.ts +0 -829
- package/dist/wasm-7OWFHDMS.js +0 -21
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { InternalValidationError } from "../errors/types.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
TokenTransaction as TokenTransactionV0,
|
|
4
|
+
TokenOutputToSpend as TokenOutputToSpendV0,
|
|
5
|
+
} from "../proto/spark.js";
|
|
6
|
+
import {
|
|
7
|
+
TokenTransaction as TokenTransaction,
|
|
8
|
+
TokenOutputToSpend as TokenOutputToSpend,
|
|
9
|
+
} from "../proto/spark_token.js";
|
|
3
10
|
|
|
4
11
|
function areByteArraysEqual(a: Uint8Array, b: Uint8Array): boolean {
|
|
5
12
|
if (a.length !== b.length) {
|
|
@@ -12,6 +19,332 @@ function hasDuplicates<T>(array: T[]): boolean {
|
|
|
12
19
|
return new Set(array).size !== array.length;
|
|
13
20
|
}
|
|
14
21
|
|
|
22
|
+
export function validateTokenTransactionV0(
|
|
23
|
+
finalTokenTransaction: TokenTransactionV0,
|
|
24
|
+
partialTokenTransaction: TokenTransactionV0,
|
|
25
|
+
signingOperators: Record<string, any>,
|
|
26
|
+
keyshareInfo: { ownerIdentifiers: string[]; threshold: number },
|
|
27
|
+
expectedWithdrawBondSats: number,
|
|
28
|
+
expectedWithdrawRelativeBlockLocktime: number,
|
|
29
|
+
expectedThreshold: number,
|
|
30
|
+
) {
|
|
31
|
+
if (finalTokenTransaction.network !== partialTokenTransaction.network) {
|
|
32
|
+
throw new InternalValidationError(
|
|
33
|
+
"Network mismatch in response token transaction",
|
|
34
|
+
{
|
|
35
|
+
value: finalTokenTransaction.network,
|
|
36
|
+
expected: partialTokenTransaction.network,
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!finalTokenTransaction.tokenInputs) {
|
|
42
|
+
throw new InternalValidationError(
|
|
43
|
+
"Token inputs missing in final transaction",
|
|
44
|
+
{
|
|
45
|
+
value: finalTokenTransaction,
|
|
46
|
+
},
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!partialTokenTransaction.tokenInputs) {
|
|
51
|
+
throw new InternalValidationError(
|
|
52
|
+
"Token inputs missing in partial transaction",
|
|
53
|
+
{
|
|
54
|
+
value: partialTokenTransaction,
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (
|
|
60
|
+
finalTokenTransaction.tokenInputs.$case !==
|
|
61
|
+
partialTokenTransaction.tokenInputs.$case
|
|
62
|
+
) {
|
|
63
|
+
throw new InternalValidationError(
|
|
64
|
+
`Transaction type mismatch: final transaction has ${finalTokenTransaction.tokenInputs.$case}, partial transaction has ${partialTokenTransaction.tokenInputs.$case}`,
|
|
65
|
+
{
|
|
66
|
+
value: finalTokenTransaction.tokenInputs.$case,
|
|
67
|
+
expected: partialTokenTransaction.tokenInputs.$case,
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (
|
|
73
|
+
finalTokenTransaction.sparkOperatorIdentityPublicKeys.length !==
|
|
74
|
+
partialTokenTransaction.sparkOperatorIdentityPublicKeys.length
|
|
75
|
+
) {
|
|
76
|
+
throw new InternalValidationError(
|
|
77
|
+
"Spark operator identity public keys count mismatch",
|
|
78
|
+
{
|
|
79
|
+
value: finalTokenTransaction.sparkOperatorIdentityPublicKeys.length,
|
|
80
|
+
expected:
|
|
81
|
+
partialTokenTransaction.sparkOperatorIdentityPublicKeys.length,
|
|
82
|
+
},
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (
|
|
87
|
+
partialTokenTransaction.tokenInputs.$case === "mintInput" &&
|
|
88
|
+
finalTokenTransaction.tokenInputs.$case === "mintInput"
|
|
89
|
+
) {
|
|
90
|
+
const finalMintInput = finalTokenTransaction.tokenInputs.mintInput;
|
|
91
|
+
const partialMintInput = partialTokenTransaction.tokenInputs.mintInput;
|
|
92
|
+
|
|
93
|
+
if (
|
|
94
|
+
!areByteArraysEqual(
|
|
95
|
+
finalMintInput.issuerPublicKey,
|
|
96
|
+
partialMintInput.issuerPublicKey,
|
|
97
|
+
)
|
|
98
|
+
) {
|
|
99
|
+
throw new InternalValidationError(
|
|
100
|
+
"Issuer public key mismatch in mint input",
|
|
101
|
+
{
|
|
102
|
+
value: finalMintInput.issuerPublicKey.toString(),
|
|
103
|
+
expected: partialMintInput.issuerPublicKey.toString(),
|
|
104
|
+
},
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
} else if (
|
|
108
|
+
partialTokenTransaction.tokenInputs.$case === "transferInput" &&
|
|
109
|
+
finalTokenTransaction.tokenInputs.$case === "transferInput"
|
|
110
|
+
) {
|
|
111
|
+
const finalTransferInput = finalTokenTransaction.tokenInputs.transferInput;
|
|
112
|
+
const partialTransferInput =
|
|
113
|
+
partialTokenTransaction.tokenInputs.transferInput;
|
|
114
|
+
|
|
115
|
+
if (
|
|
116
|
+
finalTransferInput.outputsToSpend.length !==
|
|
117
|
+
partialTransferInput.outputsToSpend.length
|
|
118
|
+
) {
|
|
119
|
+
throw new InternalValidationError(
|
|
120
|
+
"Outputs to spend count mismatch in transfer input",
|
|
121
|
+
{
|
|
122
|
+
value: finalTransferInput.outputsToSpend.length,
|
|
123
|
+
expected: partialTransferInput.outputsToSpend.length,
|
|
124
|
+
},
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
for (let i = 0; i < finalTransferInput.outputsToSpend.length; i++) {
|
|
129
|
+
const finalOutput = finalTransferInput.outputsToSpend[
|
|
130
|
+
i
|
|
131
|
+
] as TokenOutputToSpendV0;
|
|
132
|
+
const partialOutput = partialTransferInput.outputsToSpend[
|
|
133
|
+
i
|
|
134
|
+
] as TokenOutputToSpendV0;
|
|
135
|
+
|
|
136
|
+
if (!finalOutput) {
|
|
137
|
+
throw new InternalValidationError(
|
|
138
|
+
"Token output to spend missing in final transaction",
|
|
139
|
+
{
|
|
140
|
+
outputIndex: i,
|
|
141
|
+
value: finalOutput,
|
|
142
|
+
},
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (!partialOutput) {
|
|
147
|
+
throw new InternalValidationError(
|
|
148
|
+
"Token output to spend missing in partial transaction",
|
|
149
|
+
{
|
|
150
|
+
outputIndex: i,
|
|
151
|
+
value: partialOutput,
|
|
152
|
+
},
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (
|
|
157
|
+
!areByteArraysEqual(
|
|
158
|
+
finalOutput.prevTokenTransactionHash,
|
|
159
|
+
partialOutput.prevTokenTransactionHash,
|
|
160
|
+
)
|
|
161
|
+
) {
|
|
162
|
+
throw new InternalValidationError(
|
|
163
|
+
"Previous token transaction hash mismatch in transfer input",
|
|
164
|
+
{
|
|
165
|
+
outputIndex: i,
|
|
166
|
+
value: finalOutput.prevTokenTransactionHash.toString(),
|
|
167
|
+
expected: partialOutput.prevTokenTransactionHash.toString(),
|
|
168
|
+
},
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (
|
|
173
|
+
finalOutput.prevTokenTransactionVout !==
|
|
174
|
+
partialOutput.prevTokenTransactionVout
|
|
175
|
+
) {
|
|
176
|
+
throw new InternalValidationError(
|
|
177
|
+
"Previous token transaction vout mismatch in transfer input",
|
|
178
|
+
{
|
|
179
|
+
outputIndex: i,
|
|
180
|
+
value: finalOutput.prevTokenTransactionVout,
|
|
181
|
+
expected: partialOutput.prevTokenTransactionVout,
|
|
182
|
+
},
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (
|
|
189
|
+
finalTokenTransaction.tokenOutputs.length !==
|
|
190
|
+
partialTokenTransaction.tokenOutputs.length
|
|
191
|
+
) {
|
|
192
|
+
throw new InternalValidationError("Token outputs count mismatch", {
|
|
193
|
+
value: finalTokenTransaction.tokenOutputs.length,
|
|
194
|
+
expected: partialTokenTransaction.tokenOutputs.length,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
for (let i = 0; i < finalTokenTransaction.tokenOutputs.length; i++) {
|
|
199
|
+
const finalOutput = finalTokenTransaction.tokenOutputs[i];
|
|
200
|
+
const partialOutput = partialTokenTransaction.tokenOutputs[i];
|
|
201
|
+
|
|
202
|
+
if (!finalOutput) {
|
|
203
|
+
throw new InternalValidationError(
|
|
204
|
+
"Token output missing in final transaction",
|
|
205
|
+
{
|
|
206
|
+
outputIndex: i,
|
|
207
|
+
value: finalOutput,
|
|
208
|
+
},
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (!partialOutput) {
|
|
213
|
+
throw new InternalValidationError(
|
|
214
|
+
"Token output missing in partial transaction",
|
|
215
|
+
{
|
|
216
|
+
outputIndex: i,
|
|
217
|
+
value: partialOutput,
|
|
218
|
+
},
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (
|
|
223
|
+
!areByteArraysEqual(
|
|
224
|
+
finalOutput.ownerPublicKey,
|
|
225
|
+
partialOutput.ownerPublicKey,
|
|
226
|
+
)
|
|
227
|
+
) {
|
|
228
|
+
throw new InternalValidationError(
|
|
229
|
+
"Owner public key mismatch in token output",
|
|
230
|
+
{
|
|
231
|
+
outputIndex: i,
|
|
232
|
+
value: finalOutput.ownerPublicKey.toString(),
|
|
233
|
+
expected: partialOutput.ownerPublicKey.toString(),
|
|
234
|
+
},
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (
|
|
239
|
+
finalOutput.tokenPublicKey !== undefined &&
|
|
240
|
+
partialOutput.tokenPublicKey !== undefined &&
|
|
241
|
+
!areByteArraysEqual(
|
|
242
|
+
finalOutput.tokenPublicKey,
|
|
243
|
+
partialOutput.tokenPublicKey,
|
|
244
|
+
)
|
|
245
|
+
) {
|
|
246
|
+
throw new InternalValidationError(
|
|
247
|
+
"Token public key mismatch in token output",
|
|
248
|
+
{
|
|
249
|
+
outputIndex: i,
|
|
250
|
+
value: finalOutput.tokenPublicKey?.toString(),
|
|
251
|
+
expected: partialOutput.tokenPublicKey?.toString(),
|
|
252
|
+
},
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (
|
|
257
|
+
!areByteArraysEqual(finalOutput.tokenAmount, partialOutput.tokenAmount)
|
|
258
|
+
) {
|
|
259
|
+
throw new InternalValidationError(
|
|
260
|
+
"Token amount mismatch in token output",
|
|
261
|
+
{
|
|
262
|
+
outputIndex: i,
|
|
263
|
+
value: finalOutput.tokenAmount.toString(),
|
|
264
|
+
expected: partialOutput.tokenAmount.toString(),
|
|
265
|
+
},
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (finalOutput.withdrawBondSats !== undefined) {
|
|
270
|
+
if (finalOutput.withdrawBondSats !== expectedWithdrawBondSats) {
|
|
271
|
+
throw new InternalValidationError(
|
|
272
|
+
"Withdraw bond sats mismatch in token output",
|
|
273
|
+
{
|
|
274
|
+
outputIndex: i,
|
|
275
|
+
value: finalOutput.withdrawBondSats,
|
|
276
|
+
expected: expectedWithdrawBondSats,
|
|
277
|
+
},
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (finalOutput.withdrawRelativeBlockLocktime !== undefined) {
|
|
283
|
+
if (
|
|
284
|
+
finalOutput.withdrawRelativeBlockLocktime !==
|
|
285
|
+
expectedWithdrawRelativeBlockLocktime
|
|
286
|
+
) {
|
|
287
|
+
throw new InternalValidationError(
|
|
288
|
+
"Withdraw relative block locktime mismatch in token output",
|
|
289
|
+
{
|
|
290
|
+
outputIndex: i,
|
|
291
|
+
value: finalOutput.withdrawRelativeBlockLocktime,
|
|
292
|
+
expected: expectedWithdrawRelativeBlockLocktime,
|
|
293
|
+
},
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (keyshareInfo.threshold !== expectedThreshold) {
|
|
299
|
+
throw new InternalValidationError(
|
|
300
|
+
"Threshold mismatch: expected " +
|
|
301
|
+
expectedThreshold +
|
|
302
|
+
" but got " +
|
|
303
|
+
keyshareInfo.threshold,
|
|
304
|
+
{
|
|
305
|
+
field: "threshold",
|
|
306
|
+
value: keyshareInfo.threshold,
|
|
307
|
+
expected: expectedThreshold,
|
|
308
|
+
},
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (
|
|
314
|
+
keyshareInfo.ownerIdentifiers.length !==
|
|
315
|
+
Object.keys(signingOperators).length
|
|
316
|
+
) {
|
|
317
|
+
throw new InternalValidationError(
|
|
318
|
+
`Keyshare operator count (${keyshareInfo.ownerIdentifiers.length}) does not match signing operator count (${Object.keys(signingOperators).length})`,
|
|
319
|
+
{
|
|
320
|
+
keyshareInfo: keyshareInfo.ownerIdentifiers.length,
|
|
321
|
+
signingOperators: Object.keys(signingOperators).length,
|
|
322
|
+
},
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (hasDuplicates(keyshareInfo.ownerIdentifiers)) {
|
|
327
|
+
throw new InternalValidationError(
|
|
328
|
+
"Duplicate ownerIdentifiers found in keyshareInfo",
|
|
329
|
+
{
|
|
330
|
+
keyshareInfo: keyshareInfo.ownerIdentifiers,
|
|
331
|
+
},
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
for (const identifier of keyshareInfo.ownerIdentifiers) {
|
|
336
|
+
if (!signingOperators[identifier]) {
|
|
337
|
+
throw new InternalValidationError(
|
|
338
|
+
`Keyshare operator ${identifier} not found in signing operator list`,
|
|
339
|
+
{
|
|
340
|
+
keyshareInfo: identifier,
|
|
341
|
+
signingOperators: Object.keys(signingOperators),
|
|
342
|
+
},
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
15
348
|
export function validateTokenTransaction(
|
|
16
349
|
finalTokenTransaction: TokenTransaction,
|
|
17
350
|
partialTokenTransaction: TokenTransaction,
|
|
@@ -229,17 +562,19 @@ export function validateTokenTransaction(
|
|
|
229
562
|
}
|
|
230
563
|
|
|
231
564
|
if (
|
|
565
|
+
finalOutput.tokenPublicKey !== undefined &&
|
|
566
|
+
partialOutput.tokenPublicKey !== undefined &&
|
|
232
567
|
!areByteArraysEqual(
|
|
233
|
-
finalOutput.tokenPublicKey
|
|
234
|
-
partialOutput.tokenPublicKey
|
|
568
|
+
finalOutput.tokenPublicKey!,
|
|
569
|
+
partialOutput.tokenPublicKey!,
|
|
235
570
|
)
|
|
236
571
|
) {
|
|
237
572
|
throw new InternalValidationError(
|
|
238
573
|
"Token public key mismatch in token output",
|
|
239
574
|
{
|
|
240
575
|
outputIndex: i,
|
|
241
|
-
value: finalOutput.tokenPublicKey
|
|
242
|
-
expected: partialOutput.tokenPublicKey
|
|
576
|
+
value: finalOutput.tokenPublicKey!.toString(),
|
|
577
|
+
expected: partialOutput.tokenPublicKey!.toString(),
|
|
243
578
|
},
|
|
244
579
|
);
|
|
245
580
|
}
|
|
@@ -334,4 +669,14 @@ export function validateTokenTransaction(
|
|
|
334
669
|
);
|
|
335
670
|
}
|
|
336
671
|
}
|
|
672
|
+
|
|
673
|
+
if (
|
|
674
|
+
finalTokenTransaction.clientCreatedTimestamp!.getTime() !==
|
|
675
|
+
partialTokenTransaction.clientCreatedTimestamp!.getTime()
|
|
676
|
+
) {
|
|
677
|
+
throw new InternalValidationError("Client created timestamp mismatch", {
|
|
678
|
+
value: finalTokenTransaction.clientCreatedTimestamp,
|
|
679
|
+
expected: partialTokenTransaction.clientCreatedTimestamp,
|
|
680
|
+
});
|
|
681
|
+
}
|
|
337
682
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { bytesToHex, bytesToNumberBE } from "@noble/curves/abstract/utils";
|
|
2
2
|
import { OutputWithPreviousTransactionData } from "../proto/spark.js";
|
|
3
|
+
import { TokenBalanceMap } from "../spark-wallet/types.js";
|
|
3
4
|
|
|
4
5
|
export function calculateAvailableTokenAmount(
|
|
5
6
|
outputLeaves: OutputWithPreviousTransactionData[],
|
|
@@ -45,20 +46,23 @@ export function checkIfSelectedOutputsAreAvailable(
|
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
export function filterTokenBalanceForTokenPublicKey(
|
|
48
|
-
tokenBalances:
|
|
49
|
-
string,
|
|
50
|
-
{
|
|
51
|
-
balance: bigint;
|
|
52
|
-
}
|
|
53
|
-
>,
|
|
49
|
+
tokenBalances: TokenBalanceMap,
|
|
54
50
|
publicKey: string,
|
|
55
51
|
): { balance: bigint } {
|
|
56
|
-
if (!tokenBalances
|
|
52
|
+
if (!tokenBalances) {
|
|
53
|
+
return { balance: 0n };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const tokenBalance = [...tokenBalances.entries()].find(
|
|
57
|
+
([, info]) => info.tokenMetadata.tokenPublicKey === publicKey,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
if (!tokenBalance) {
|
|
57
61
|
return {
|
|
58
62
|
balance: 0n,
|
|
59
63
|
};
|
|
60
64
|
}
|
|
61
65
|
return {
|
|
62
|
-
balance:
|
|
66
|
+
balance: tokenBalance[1].balance,
|
|
63
67
|
};
|
|
64
68
|
}
|
package/src/utils/transaction.ts
CHANGED
|
@@ -87,15 +87,9 @@ export function getNextTransactionSequence(
|
|
|
87
87
|
nextSequence: number;
|
|
88
88
|
needRefresh: boolean;
|
|
89
89
|
} {
|
|
90
|
-
// Check if the previous sequence is valid. If not, the user could lose funds.
|
|
91
|
-
checkIfValidSequence(currSequence);
|
|
92
|
-
|
|
93
90
|
const currentTimelock = getCurrentTimelock(currSequence);
|
|
94
91
|
const nextTimelock = currentTimelock - TIME_LOCK_INTERVAL;
|
|
95
92
|
|
|
96
|
-
// Confirm that the next sequence is valid. This should never happen since bit 17-31 should all be 0.
|
|
97
|
-
checkIfValidSequence(nextTimelock);
|
|
98
|
-
|
|
99
93
|
if (forRefresh && nextTimelock <= 100 && currentTimelock > 0) {
|
|
100
94
|
return {
|
|
101
95
|
nextSequence: (1 << 30) | nextTimelock,
|